From 908663e8fc371cade9ce5768333a84f1aff10287 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Tue, 27 Dec 2016 12:20:20 +0100 Subject: [PATCH] input: discard a verbatim 0x0A or 0x00 byte, depending on the mode This disallows entering a verbatim ^J (0x0A) when typing text or search terms, and disallows a verbatim ^@ (0x00) when typing a filename. Nano beeps when the disallowed code is attempted. This addresses https://savannah.gnu.org/bugs/?49897. --- src/nano.c | 14 +++----------- src/prompt.c | 47 +++++++++++------------------------------------ src/proto.h | 4 ++-- src/winio.c | 8 +++++++- 4 files changed, 23 insertions(+), 50 deletions(-) diff --git a/src/nano.c b/src/nano.c index 197194a9..0cd8b479 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1824,17 +1824,9 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) #endif while (i < output_len) { - /* If control codes are allowed, encode a verbatim null as a newline, - * and let a verbatim ^J create a whole new line. */ - if (allow_cntrls) { - if (output[i] == '\0') - output[i] = '\n'; - else if (output[i] == '\n') { - do_enter(); - i++; - continue; - } - } + /* Encode an embedded NUL byte as 0x0A. */ + if (output[i] == '\0') + output[i] = '\n'; /* Get the next multibyte character. */ char_len = parse_mbchar(output + i, char_buf, NULL); diff --git a/src/prompt.c b/src/prompt.c index 12ae3e20..0bb6daba 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -104,7 +104,7 @@ int do_statusbar_input(bool *ran_func, bool *finished) if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) { /* Inject all characters in the input buffer at once, filtering out * control characters. */ - do_statusbar_output(kbinput, kbinput_len, TRUE, NULL); + do_statusbar_output(kbinput, kbinput_len, TRUE); /* Empty the input buffer. */ kbinput_len = 0; @@ -139,18 +139,7 @@ int do_statusbar_input(bool *ran_func, bool *finished) s->scfunc == do_backspace)) ; else if (s->scfunc == do_verbatim_input) { - bool got_newline = FALSE; - /* Whether we got a verbatim ^J. */ - - do_statusbar_verbatim_input(&got_newline); - - /* If we got a verbatim ^J, remove it from the input buffer, - * fake a press of Enter, and indicate that we're done. */ - if (got_newline) { - get_input(NULL, 1); - input = KEY_ENTER; - *finished = TRUE; - } + do_statusbar_verbatim_input(); } else if (s->scfunc == do_cut_text_void) do_statusbar_cut_text(); else if (s->scfunc == do_delete) @@ -202,11 +191,10 @@ int do_statusbar_mouse(void) } #endif -/* The user typed input_len multibyte characters. Add them to the - * statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J, - * and filtering out ASCII control characters if filtering is TRUE. */ +/* The user typed input_len multibyte characters. Add them to the answer, + * filtering out ASCII control characters if filtering is TRUE. */ void do_statusbar_output(int *the_input, size_t input_len, - bool filtering, bool *got_newline) + bool filtering) { char *output = charalloc(input_len + 1); char *char_buf = charalloc(mb_cur_max()); @@ -220,18 +208,9 @@ void do_statusbar_output(int *the_input, size_t input_len, i = 0; while (i < input_len) { - /* When not filtering, convert nulls and stop at a newline. */ - if (!filtering) { - if (output[i] == '\0') - output[i] = '\n'; - else if (output[i] == '\n') { - /* Put back the rest of the characters for reparsing, - * indicate that we got a ^J and get out. */ - unparse_kbinput(output + i, input_len - i); - *got_newline = TRUE; - return; - } - } + /* Encode any NUL byte as 0x0A. */ + if (output[i] == '\0') + output[i] = '\n'; /* Interpret the next multibyte character. */ char_len = parse_mbchar(output + i, char_buf, NULL); @@ -369,19 +348,15 @@ void do_statusbar_prev_word(void) } #endif /* !NANO_TINY */ -/* Get verbatim input, setting got_newline to TRUE if we get a ^J as - * part of the verbatim input. */ -void do_statusbar_verbatim_input(bool *got_newline) +/* Get verbatim input and inject it into the answer, without filtering. */ +void do_statusbar_verbatim_input(void) { int *kbinput; size_t kbinput_len; - /* Read in all the verbatim characters. */ kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len); - /* Display all the verbatim characters at once, not filtering out - * control characters. */ - do_statusbar_output(kbinput, kbinput_len, FALSE, got_newline); + do_statusbar_output(kbinput, kbinput_len, FALSE); } /* Return the zero-based column position of the cursor in the answer. */ diff --git a/src/proto.h b/src/proto.h index 52350c9a..92f35773 100644 --- a/src/proto.h +++ b/src/proto.h @@ -485,7 +485,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls); int do_statusbar_mouse(void); #endif void do_statusbar_output(int *the_input, size_t input_len, - bool filtering, bool *got_newline); + bool filtering); void do_statusbar_home(void); void do_statusbar_end(void); void do_statusbar_left(void); @@ -497,7 +497,7 @@ void do_statusbar_cut_text(void); void do_statusbar_prev_word(void); void do_statusbar_next_word(void); #endif -void do_statusbar_verbatim_input(bool *got_newline); +void do_statusbar_verbatim_input(void); size_t statusbar_xplustabs(void); size_t get_statusbar_page_start(size_t start_col, size_t column); void reinit_statusbar_x(void); diff --git a/src/winio.c b/src/winio.c index 7df9cf2e..947176eb 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1442,9 +1442,15 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len) if (!ISSET(REBIND_KEYPAD)) keypad(win, FALSE); - /* Read in a stream of characters and interpret it if possible. */ + /* Read in one keycode, or one or two escapes. */ retval = parse_verbatim_kbinput(win, kbinput_len); + /* If the code is invalid in the current mode, discard it. */ + if ((*retval == '\n' && as_an_at) || (*retval == '\0' && !as_an_at)) { + *kbinput_len = 0; + beep(); + } + /* Turn flow control characters back on if necessary and turn the * keypad back on if necessary now that we're done. */ if (ISSET(PRESERVE))