Thank you for narrowing it down, Bernhard. I’ve further isolated the problem to libreadline. I have attached a program based on the sample code from the libreadline documentation which exhibits the same behaviour.
Example run:
$ make
cc rlgets.c -lreadline -o rlgets
$ make test
bash -c "echo $'foo\nbar\n\cp\cu\cp\cu\cn\cj' | ./rlgets"
prompt> foo
prompt> bar
prompt>
free(): double free detected in tcache 2
bash: line 1: 556449 Done echo 'foo
bar
'
556450 Aborted (core dumped) | ./rlgets
make: *** [Makefile:5: test] Error 134
Ben Wong
rlgets.c
#include <readline/readline.h> /* readline() */#include
<readline/history.h> /* add_history() */#include <stdlib.h>
/* free() */
/* A static variable for holding the line. */static char *line_read =
(char *)NULL;
/* Read a string, and return a pointer to it.
Returns NULL on EOF. */char *
rl_gets (char *prompt)
{
/* If the buffer has already been allocated,
return the memory to the free pool. */
if (line_read)
{
free (line_read);
line_read = (char *)NULL;
}
/* Get a line from the user. */
line_read = readline (prompt);
/* If the line has any text in it,
save it on the history. */
if (line_read && *line_read)
add_history (line_read);
return (line_read);
}
int main(int argc, char *argv[]) {
char *buf;
rl_bind_key ('p'-'a'+1, rl_history_search_backward);
rl_bind_key ('n'-'a'+1, rl_history_search_forward);
read_history("history_file");
while (1) {
buf = rl_gets("prompt> ");
if (!buf) { break; }
if ( !strncmp(buf, "exit", 4) || !strncmp(buf, "quit", 4) ) { break; }
}
write_history ("history_file");
return 0;
}
Makefile
LDLIBS+=-lreadline
rlgets: rlgets.c
test: rlgets
bash -c "echo $$'foo\nbar\n\cp\cu\cp\cu\cn\cj' | ./rlgets"
clean:
rm rlgets history_file core *~ 2>/dev/null || true
On Fri, Jun 2, 2023 at 3:01 AM Bernhard Übelacker [email protected]
<http://mailto:[email protected]> wrote:
Hello,
> below is the top of a valgrind run
> with dbgsym package installed.
>
> Kind regards,
> Bernhard
>
>
#include <readline/readline.h> /* readline() */
#include <readline/history.h> /* add_history() */
#include <stdlib.h> /* free() */
/* A static variable for holding the line. */
static char *line_read = (char *)NULL;
/* Read a string, and return a pointer to it.
Returns NULL on EOF. */
char *
rl_gets (char *prompt)
{
/* If the buffer has already been allocated,
return the memory to the free pool. */
if (line_read)
{
free (line_read);
line_read = (char *)NULL;
}
/* Get a line from the user. */
line_read = readline (prompt);
/* If the line has any text in it,
save it on the history. */
if (line_read && *line_read)
add_history (line_read);
return (line_read);
}
int main(int argc, char *argv[]) {
char *buf;
rl_bind_key ('p'-'a'+1, rl_history_search_backward);
rl_bind_key ('n'-'a'+1, rl_history_search_forward);
read_history("history_file");
while (1) {
buf = rl_gets("prompt> ");
if (!buf) { break; }
if ( !strncmp(buf, "exit", 4) || !strncmp(buf, "quit", 4) ) { break; }
}
write_history ("history_file");
return 0;
}
Makefile
Description: Binary data

