NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/54281: libedit: rl_line_buffer content leaks cross-prompt

>Number:         54281
>Category:       lib
>Synopsis:       libedit: rl_line_buffer content leaks cross-prompt
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 06 21:15:00 +0000 2019
>Originator:     Jonathan Perkins
>Release:        Sources as of 2019/06/06
It appears that rl_line_buffer isn't getting null-terminated consistently when the length shortens.  This is particularly observable in tab completion, where users may look at rl_line_buffer to see the full user input.

I'm proposing to null-terminate rl_line_buffer on modification.  While rl_end allows the user to determine the end, the null terminator appears to be compatible with how readline is behaving.

The intent is that code like this should work:
const std::string full_line = collected_line_ + std::string(rl_line_buffer);
Example code is below.  To repro with a binary from it, type "example", press enter, then press tab to trigger completions.

With the current libedit, output should be:
Test> example
Test> example
This is because "example" has leaked cross-prompt and is visible to completion in rl_line_buffer.

With this fix, output should be:
Test> example
This is because rl_line_buffer gets null-terminated, making rl_line_buffer an empty string (correctly)

Example code:

#include <stdlib.h>
#include <string.h>
#include "readline.h"

static char** DoComplete(const char* text, int start, int end) {
  char** results = (char**)malloc(sizeof(*results) * 3);
  results[0] = strdup(rl_line_buffer);
  results[1] = strdup(rl_line_buffer);
  results[2] = nullptr;
  return results;

int main(int argc, char** argv) {
  for (;;) {
    char* result = readline("Test> ");
    if (result == nullptr) break;
    rl_attempted_completion_function = DoComplete;
  return 0;

--- old/libedit/readline.c
+++ new/libedit/readline.c
@@ -2231,6 +2231,7 @@ static void
 	rl_point = (int)(li->cursor - li->buffer);
 	rl_end = (int)(li->lastchar - li->buffer);
+	rl_line_buffer[rl_end] = '\0';

Home | Main Index | Thread Index | Old Index