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

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) {
/* 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. */

View File

@ -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);

View File

@ -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))