commit bash-20170511 snapshot

This commit is contained in:
Chet Ramey
2017-05-11 14:45:50 -04:00
parent af2a77fbbc
commit 8a10051448
5 changed files with 97 additions and 32 deletions
+41
View File
@@ -13840,3 +13840,44 @@ builtins/read.def
a CTLESC the last time through the loop (skip_ctlesc == 0),
especially if i == 0. Another fuzzing bug from Eduardo Bustamante
<dualbus@gmail.com>
5/8
---
builtins/read.def
- read_mbchar: handle zreadn/zreadc/zread returning EOF in the middle
of an incomplete multibyte sequence. Fixes another fuzzing bug
- read_builtin: use mb_cur_max instead of constant 4 when deciding
whether the next character can exceed the number of bytes available
in input_string
lib/readline/input.c
- MinGW: include <conio.h> before <io.h>. Fix from Eli Zaretskii
<eliz@gnu.org>
builtins/read.def
- read_builtin: if we get input from readline, we need to get the
remainder of a multibyte character from rlbuf instead of calling
read_mbchar. Bug reported by Eduardo Bustamante <dualbus@gmail.com>
5/9
---
parse.y
- token_is_assignment: use the allocated buffer approach in all cases,
not just if we're not using bash malloc. This avoids the assignment
to t[i+1] writing beyond the end of the allocated token if
i == token_buffer_size - 1. Another fuzzing bug
- xparse_dolparen: if parse_string returns < 0, we clear out the
current shell_input_line before performing a longjmp, since we're
abandoning parsing of this command. This is consistent with how
the parser resynchronizes after other syntax errors
- GRAMMAR: add 'error yacc_EOF' production to handle a syntax error
that's immediately followed by an EOF after resynchronization.
Fixes another fuzzing bug
5/10
----
lib/readline/text.c
- _rl_set_mark_at_pos: don't let the mark be set to a position < 0.
Fixes a fuzzing bug
- rl_exchange_point_and_mark: don't do anything if the mark is already
less than 0
+27 -7
View File
@@ -381,7 +381,11 @@ read_builtin (list)
sync_buffered_stream (default_buffered_input);
#endif
#if 1
input_is_tty = isatty (fd);
#else
input_is_tty = 1;
#endif
if (input_is_tty == 0)
#ifndef __CYGWIN__
input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
@@ -606,7 +610,8 @@ read_builtin (list)
#endif
CHECK_ALRM;
if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
/* XXX -- use i + mb_cur_max (at least 4) for multibyte/read_mbchar */
if (i + (mb_cur_max > 4 ? mb_cur_max : 4) >= size)
{
char *t;
t = (char *)xrealloc (input_string, size += 128);
@@ -666,14 +671,28 @@ add_char:
CHECK_ALRM;
#if defined (HANDLE_MULTIBYTE)
# if 0
if (nchars > 0 && mb_cur_max > 1 && is_basic (c) == 0)
# else
/* XXX - what if C == 127? Can DEL introduce a multibyte sequence? */
if (mb_cur_max > 1 && is_basic (c) == 0)
# endif
{
input_string[i] = '\0'; /* for simplicity and debugging */
i += read_mbchar (fd, input_string, i, c, unbuffered_read);
/* If we got input from readline, grab the next multibyte char from
rlbuf. */
if (edit)
{
size_t clen;
clen = mbrlen (rlbuf + rlind - 1, mb_cur_max, (mbstate_t *)NULL);
/* We only deal with valid multibyte sequences longer than one
byte. If we get anything else, we leave the one character
copied and move on to the next. */
if ((int)clen > 1)
{
memcpy (input_string+i, rlbuf+rlind, clen-1);
i += clen - 1;
rlind += clen - 1;
}
}
else
i += read_mbchar (fd, input_string, i, c, unbuffered_read);
}
#endif
@@ -968,6 +987,7 @@ read_mbchar (fd, string, ind, ch, unbuffered)
if (ret == (size_t)-2)
{
ps = ps_back;
/* We don't want to be interrupted during a multibyte char read */
if (unbuffered == 2)
r = zreadn (fd, &c, 1);
@@ -975,7 +995,7 @@ read_mbchar (fd, string, ind, ch, unbuffered)
r = zread (fd, &c, 1);
else
r = zreadc (fd, &c);
if (r < 0)
if (r <= 0)
goto mbchar_return;
mbchar[i++] = c;
continue;
+1
View File
@@ -102,6 +102,7 @@ static int rl_gather_tyi PARAMS((void));
/* Windows isatty returns true for every character device, including the null
device, so we need to perform additional checks. */
#if defined (_WIN32) && !defined (__CYGWIN__)
#include <conio.h>
#include <io.h>
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
+3 -2
View File
@@ -1699,7 +1699,7 @@ rl_backward_char_search (int count, int key)
int
_rl_set_mark_at_pos (int position)
{
if (position > rl_end)
if (position < 0 || position > rl_end)
return 1;
rl_mark = position;
@@ -1720,9 +1720,10 @@ rl_exchange_point_and_mark (int count, int key)
if (rl_mark > rl_end)
rl_mark = -1;
if (rl_mark == -1)
if (rl_mark < 0)
{
rl_ding ();
rl_mark = 0; /* like _RL_FIX_POINT */
return 1;
}
else
+25 -23
View File
@@ -411,6 +411,14 @@ inputunit: simple_list simple_list_terminator
YYABORT;
}
}
| error yacc_EOF
{
/* EOF after an error. Do ignoreeof or not. Really
only interesting in non-interactive shells */
global_command = (COMMAND *)NULL;
handle_eof_input_unit ();
YYACCEPT;
}
| yacc_EOF
{
/* Case of EOF seen by itself. Do ignoreeof or
@@ -4313,9 +4321,13 @@ xparse_dolparen (base, string, indp, flags)
token_to_read = 0;
/* If parse_string returns < 0, we need to jump to top level with the
negative of the return value */
negative of the return value. We abandon the rest of this input line
first */
if (nc < 0)
jump_to_top_level (-nc); /* XXX */
{
clear_shell_input_line (); /* XXX */
jump_to_top_level (-nc); /* XXX */
}
/* Need to find how many characters parse_and_execute consumed, update
*indp, if flags != 0, copy the portion of the string parsed into RET
@@ -4714,37 +4726,27 @@ parse_cond_command ()
#if defined (ARRAY_VARS)
/* When this is called, it's guaranteed that we don't care about anything
in t beyond i. We do save and restore the chars, though. */
in t beyond i. We use a buffer with room for the characters we add just
in case assignment() ends up doing something like parsing a command
substitution that will reallocate atoken. We don't want to write beyond
the end of an allocated buffer. */
static int
token_is_assignment (t, i)
char *t;
int i;
{
int r;
char *atoken;
#if !defined (USING_BASH_MALLOC)
static char *token = 0;
atoken = xmalloc (i + 3);
memcpy (atoken, t, i);
atoken[i] = '=';
atoken[i+1] = '\0';
token = xrealloc (token, i + 3);
memcpy (token, t, i);
token[i] = '=';
token[i+1] = '\0';
r = assignment (atoken, (parser_state & PST_COMPASSIGN) != 0);
r = assignment (token, (parser_state & PST_COMPASSIGN) != 0);
free (atoken);
if (i + 3 > 4096) /* keep it from getting too big */
{
free (token);
token = 0;
}
#else
unsigned char c, c1;
c = t[i]; c1 = t[i+1];
t[i] = '='; t[i+1] = '\0';
r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
t[i] = c; t[i+1] = c1;
#endif
/* XXX - check that r == i to avoid returning false positive for
t containing `=' before t[i]. */
return (r > 0 && r == i);