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;
}
  

Attachment: Makefile
Description: Binary data

Reply via email to