script read errors are now fatal errors; fixes for readline asan issues

This commit is contained in:
Chet Ramey
2023-03-13 17:20:51 -04:00
parent 22cdf92bee
commit 01084938a1
10 changed files with 135 additions and 34 deletions
+61
View File
@@ -5571,3 +5571,64 @@ jobs.c
the foreground (J_FOREGROUND) as it would be if it had been continued
in the foreground with `fg'; if it is, we want to give the terminal
back to shell_pgrp
3/10
----
input.c
- fd_berror: returns true if the file descriptor passed as an arg
corresponds to a buffered stream with an error condition
parse.y
- shell_getc: use fd_berror instead of inline code
- shell_getc: if yy_getc returns EOF, immediately set line[0] to NULL
and set shell_input_line_terminator to READERR. Then exit immediately
with status 128 if index == 0, line[index] == NULL, and READERR.
Posix interp 1629
config-top.h
- FATAL_READERROR: now defined to 1 by default
lib/readline/display.c
- rl_expand_prompt: allocate an empty string for local_prompt if prompt
is the NULL or empty string. Fixes seg fault with rl_message and
empty prompt reported by Grisha Levit <grishalevit@gmail.com>
lib/readline/histexpand.c
- history_expand: if hist_extract_single_quoted returns an index at or
past the end of the string, correct the index and break the loop,
which will cause a return. Report and fix from
Grisha Levit <grishalevit@gmail.com>
3/13
----
lib/readline/vi_mode.c
- rl_domove_motion_callback: set the MOVE_FAILED flag in the context M
if rl_dispatch returns non-zero and other movement-command-specific
conditions are met. Right now, an unsuccessful `f' or `F' command
is failure.
- _rl_vi_domove_motion_cleanup: if the command is `c' or `C', we don't
enter insert mode if the MOVE_FAILED flag is set in the context M.
This is how standalone vi works.
lib/readline/kill.c
- rl_unix_filename_rubout: add some checks for rl_point > 0 before
looking at rl_line_buffer[rl_point - 1]. Report and fix from
Grisha Levit <grishalevit@gmail.com>
lib/readline/isearch.c
- _rl_isearch_dispatch: reset cxt->sline_index to 0 if it's past the
end of the history string (sline_len). Fixes asan bug reported by
Grisha Levit <grishalevit@gmail.com>
lib/readline/histexpand.c
- history_tokenize_word: don't increment the string index past the
NULL if the line ends in a backslash.Fixes asan bug reported by
Grisha Levit <grishalevit@gmail.com>
lib/readline/vi_mode.c
- rl_vi_yank_to,rl_vi_change_to,rl_vi_delete_to: if these are called
with an existing valid vimvcxt, save it and allocate a new one for
the current function call to use, then restore it before returning.
This prevents referencing vimvcxt after freeing it in the case that
these functions call each other recursively (e.g., y1y1, c1d1, etc.).
Fixes asan bug reported by Grisha Levit <grishalevit@gmail.com>
+3 -2
View File
@@ -196,8 +196,9 @@
#define ASSOC_KVPAIR_ASSIGNMENT 1
/* Define if you want read errors in non-interactive shells to be fatal
errors instead of the historical practice of treating them as EOF. */
/* #define FATAL_READERROR 1 */
errors instead of the historical practice of treating them as EOF. The
next version of POSIX will require this (interp 1629). */
#define FATAL_READERROR 1
/* Define to 0 if you want the `patsub_replacement' shell option to be disabled
by default. */
+9
View File
@@ -469,6 +469,15 @@ get_buffered_stream (int fd)
return (buffers && fd < nbuffers) ? buffers[fd] : (BUFFERED_STREAM *)0;
}
int
fd_berror (int fd)
{
BUFFERED_STREAM *bp;
bp = get_buffered_stream (default_buffered_input);
return (bp && berror (bp));
}
/* Read a buffer full of characters from BP, a buffered stream. */
static int
b_fill_buffer (BUFFERED_STREAM *bp)
+1
View File
@@ -122,6 +122,7 @@ extern void free_buffered_stream (BUFFERED_STREAM *);
extern int close_buffered_stream (BUFFERED_STREAM *);
extern int close_buffered_fd (int);
extern int sync_buffered_stream (int);
extern int fd_berror (int);
extern int buffered_getchar (void);
extern int buffered_ungetchar (int);
extern void with_input_from_buffered_stream (int, char *);
+5 -1
View File
@@ -620,7 +620,11 @@ rl_expand_prompt (char *prompt)
local_prompt_invis_chars[0] = 0;
if (prompt == 0 || *prompt == 0)
return (0);
{
local_prompt = xmalloc (sizeof (char));
local_prompt[0] = '\0';
return (0);
}
p = strrchr (prompt, '\n');
if (p == 0)
+10 -1
View File
@@ -984,6 +984,8 @@ history_expand (const char *hstring, char **output)
squote = 0;
if (string[i])
i++;
if (i >= l)
i = l;
}
for ( ; string[i]; i++)
@@ -1054,6 +1056,11 @@ history_expand (const char *hstring, char **output)
flag = (i > 0 && string[i - 1] == '$');
i++;
hist_string_extract_single_quoted (string, &i, flag);
if (i >= l)
{
i = l;
break;
}
}
else if (history_quotes_inhibit_expansion && string[i] == '\\')
{
@@ -1064,7 +1071,7 @@ history_expand (const char *hstring, char **output)
}
}
if (string[i] != history_expansion_char)
{
xfree (result);
@@ -1563,6 +1570,8 @@ get_word:
(delimiter != '"' || member (string[i], slashify_in_quotes)))
{
i++;
if (string[i] == 0)
break;
continue;
}
+3 -3
View File
@@ -783,7 +783,7 @@ opcode_dispatch:
else
cxt->sline_index += cxt->direction;
if (cxt->sline_index < 0)
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
{
cxt->sline_index = 0;
break;
@@ -816,8 +816,8 @@ opcode_dispatch:
if (cxt->sflags & SF_FAILED)
{
/* XXX - reset sline_index if < 0 */
if (cxt->sline_index < 0)
/* XXX - reset sline_index if < 0 or longer than the history line */
if (cxt->sline_index < 0 || cxt->sline_index > cxt->sline_len)
cxt->sline_index = 0;
break;
}
+7 -7
View File
@@ -348,15 +348,15 @@ rl_unix_filename_rubout (int count, int key)
if (count <= 0)
count = 1;
while (count--)
while (rl_point > 0 && count--)
{
c = rl_line_buffer[rl_point - 1];
/* First move backwards through whitespace */
while (rl_point && whitespace (c))
{
rl_point--;
c = rl_line_buffer[rl_point - 1];
if (--rl_point)
c = rl_line_buffer[rl_point - 1];
}
/* Consume one or more slashes. */
@@ -377,14 +377,14 @@ rl_unix_filename_rubout (int count, int key)
while (rl_point && (whitespace (c) || c == '/'))
{
rl_point--;
c = rl_line_buffer[rl_point - 1];
if (--rl_point)
c = rl_line_buffer[rl_point - 1];
}
while (rl_point && (whitespace (c) == 0) && c != '/')
{
rl_point--; /* XXX - multibyte? */
c = rl_line_buffer[rl_point - 1];
if (--rl_point) /* XXX - multibyte? */
c = rl_line_buffer[rl_point - 1];
}
}
+29 -6
View File
@@ -76,6 +76,10 @@
#define INCREMENT_POS(start) (start)++
#endif /* !HANDLE_MULTIBYTE */
/* Flags for the motion context */
#define MOVE_SUCCESS 0
#define MOVE_FAILED 0x01
/* This is global so other parts of the code can check whether the last
command was a text modification command. */
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
@@ -1152,7 +1156,7 @@ _rl_mvcxt_dispose (_rl_vimotion_cxt *m)
static int
rl_domove_motion_callback (_rl_vimotion_cxt *m)
{
int c;
int c, r, opoint;
_rl_vi_last_motion = c = m->motion;
@@ -1162,8 +1166,15 @@ rl_domove_motion_callback (_rl_vimotion_cxt *m)
rl_extend_line_buffer (rl_end + 1);
rl_line_buffer[rl_end++] = ' ';
rl_line_buffer[rl_end] = '\0';
opoint = rl_point;
_rl_dispatch (c, _rl_keymap);
r = _rl_dispatch (c, _rl_keymap);
/* Note in the context that the motion command failed. Right now we only do
this for unsuccessful searches (ones where _rl_dispatch returns non-zero
and point doesn't move). */
if (r != 0 && rl_point == opoint && (c == 'f' || c == 'F'))
m->flags |= MOVE_FAILED;
#if defined (READLINE_CALLBACKS)
if (RL_ISSTATE (RL_STATE_CALLBACK))
@@ -1198,7 +1209,7 @@ _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
{
/* 'c' and 'C' enter insert mode after the delete even if the motion
didn't delete anything, as long as the motion command is valid. */
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c))
if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c) && (m->flags & MOVE_FAILED) == 0)
return (vidomove_dispatch (m));
RL_UNSETSTATE (RL_STATE_VIMOTION);
return (-1);
@@ -1379,7 +1390,11 @@ rl_vi_delete_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_DELETE, key);
{
/* are we being called recursively or by `y' or `c'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
@@ -1478,7 +1493,11 @@ rl_vi_change_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_CHANGE, key);
{
/* are we being called recursively or by `y' or `d'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
_rl_vimvcxt->start = rl_point;
@@ -1557,7 +1576,11 @@ rl_vi_yank_to (int count, int key)
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
}
else if (_rl_vimvcxt)
_rl_mvcxt_init (_rl_vimvcxt, VIM_YANK, key);
{
/* are we being called recursively or by `c' or `d'? */
savecxt = _rl_vimvcxt;
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
}
else
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
_rl_vimvcxt->start = rl_point;
+7 -14
View File
@@ -2446,20 +2446,13 @@ shell_getc (int remove_quoted_newline)
if (i == 0)
shell_input_line_terminator = EOF;
if (i == 0 && bash_input.type == st_bstream)
{
BUFFERED_STREAM *bp;
bp = get_buffered_stream (default_buffered_input);
if (bp && berror (bp))
shell_input_line_terminator = READERR;
}
else
if (i == 0 && interactive_shell == 0 && bash_input.type == st_stream && ferror (stdin))
shell_input_line_terminator = READERR;
if (bash_input.type == st_bstream && fd_berror (default_buffered_input))
shell_input_line_terminator = READERR;
else if (interactive_shell == 0 && bash_input.type == st_stream && ferror (stdin))
shell_input_line_terminator = READERR;
/* If we want to make read errors cancel execution of any partial
line, take out the checks for i == 0 above and set i = 0 if
shell_input_line_terminator == READERR. */
/* We want to make read errors cancel execution of any partial
line, so we set i = 0 if shell_input_line_terminator == READERR. */
/* XXX TAG: bash-5.3 austingroup interp 1629 */
#if defined (FATAL_READERROR)
if (shell_input_line_terminator == READERR)
@@ -2715,7 +2708,7 @@ pop_alias:
{
#if defined (FATAL_READERROR)
report_error (_("script file read error: %s"), strerror (errno));
exit_shell (2);
exit_shell (128); /* POSIX mandated error status */
#else
/* Treat read errors like EOF here. */
return ((shell_input_line_index != 0) ? '\n' : EOF);