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.
This commit is contained in:
Benno Schulenberg 2016-12-27 12:20:20 +01:00
parent 1fb820386b
commit 908663e8fc
4 changed files with 23 additions and 50 deletions

View File

@ -1824,17 +1824,9 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
#endif #endif
while (i < output_len) { while (i < output_len) {
/* If control codes are allowed, encode a verbatim null as a newline, /* Encode an embedded NUL byte as 0x0A. */
* and let a verbatim ^J create a whole new line. */ if (output[i] == '\0')
if (allow_cntrls) { output[i] = '\n';
if (output[i] == '\0')
output[i] = '\n';
else if (output[i] == '\n') {
do_enter();
i++;
continue;
}
}
/* Get the next multibyte character. */ /* Get the next multibyte character. */
char_len = parse_mbchar(output + i, char_buf, NULL); char_len = parse_mbchar(output + i, char_buf, NULL);

View File

@ -104,7 +104,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) { if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) {
/* Inject all characters in the input buffer at once, filtering out /* Inject all characters in the input buffer at once, filtering out
* control characters. */ * control characters. */
do_statusbar_output(kbinput, kbinput_len, TRUE, NULL); do_statusbar_output(kbinput, kbinput_len, TRUE);
/* Empty the input buffer. */ /* Empty the input buffer. */
kbinput_len = 0; kbinput_len = 0;
@ -139,18 +139,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
s->scfunc == do_backspace)) s->scfunc == do_backspace))
; ;
else if (s->scfunc == do_verbatim_input) { else if (s->scfunc == do_verbatim_input) {
bool got_newline = FALSE; do_statusbar_verbatim_input();
/* 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;
}
} else if (s->scfunc == do_cut_text_void) } else if (s->scfunc == do_cut_text_void)
do_statusbar_cut_text(); do_statusbar_cut_text();
else if (s->scfunc == do_delete) else if (s->scfunc == do_delete)
@ -202,11 +191,10 @@ int do_statusbar_mouse(void)
} }
#endif #endif
/* The user typed input_len multibyte characters. Add them to the /* The user typed input_len multibyte characters. Add them to the answer,
* statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J, * filtering out ASCII control characters if filtering is TRUE. */
* and filtering out ASCII control characters if filtering is TRUE. */
void do_statusbar_output(int *the_input, size_t input_len, 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 *output = charalloc(input_len + 1);
char *char_buf = charalloc(mb_cur_max()); char *char_buf = charalloc(mb_cur_max());
@ -220,18 +208,9 @@ void do_statusbar_output(int *the_input, size_t input_len,
i = 0; i = 0;
while (i < input_len) { while (i < input_len) {
/* When not filtering, convert nulls and stop at a newline. */ /* Encode any NUL byte as 0x0A. */
if (!filtering) { if (output[i] == '\0')
if (output[i] == '\0') output[i] = '\n';
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;
}
}
/* Interpret the next multibyte character. */ /* Interpret the next multibyte character. */
char_len = parse_mbchar(output + i, char_buf, NULL); char_len = parse_mbchar(output + i, char_buf, NULL);
@ -369,19 +348,15 @@ void do_statusbar_prev_word(void)
} }
#endif /* !NANO_TINY */ #endif /* !NANO_TINY */
/* Get verbatim input, setting got_newline to TRUE if we get a ^J as /* Get verbatim input and inject it into the answer, without filtering. */
* part of the verbatim input. */ void do_statusbar_verbatim_input(void)
void do_statusbar_verbatim_input(bool *got_newline)
{ {
int *kbinput; int *kbinput;
size_t kbinput_len; size_t kbinput_len;
/* Read in all the verbatim characters. */
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len); kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
/* Display all the verbatim characters at once, not filtering out do_statusbar_output(kbinput, kbinput_len, FALSE);
* control characters. */
do_statusbar_output(kbinput, kbinput_len, FALSE, got_newline);
} }
/* Return the zero-based column position of the cursor in the answer. */ /* Return the zero-based column position of the cursor in the answer. */

View File

@ -485,7 +485,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls);
int do_statusbar_mouse(void); int do_statusbar_mouse(void);
#endif #endif
void do_statusbar_output(int *the_input, size_t input_len, 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_home(void);
void do_statusbar_end(void); void do_statusbar_end(void);
void do_statusbar_left(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_prev_word(void);
void do_statusbar_next_word(void); void do_statusbar_next_word(void);
#endif #endif
void do_statusbar_verbatim_input(bool *got_newline); void do_statusbar_verbatim_input(void);
size_t statusbar_xplustabs(void); size_t statusbar_xplustabs(void);
size_t get_statusbar_page_start(size_t start_col, size_t column); size_t get_statusbar_page_start(size_t start_col, size_t column);
void reinit_statusbar_x(void); void reinit_statusbar_x(void);

View File

@ -1442,9 +1442,15 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
if (!ISSET(REBIND_KEYPAD)) if (!ISSET(REBIND_KEYPAD))
keypad(win, FALSE); 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); 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 /* Turn flow control characters back on if necessary and turn the
* keypad back on if necessary now that we're done. */ * keypad back on if necessary now that we're done. */
if (ISSET(PRESERVE)) if (ISSET(PRESERVE))