diff options
author | Florian Weimer <fweimer@redhat.com> | 2014-10-10 11:04:10 +0100 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-11-16 11:42:49 +0100 |
commit | 264a53cb86ea2287f3ccb8a689c8b26293a1346f (patch) | |
tree | c20e89b05eeebe641664cb325a293f64631e0289 | |
parent | bb2185151734e70ea5dee4203ed82cbbae1db101 (diff) | |
download | external_bash-264a53cb86ea2287f3ccb8a689c8b26293a1346f.zip external_bash-264a53cb86ea2287f3ccb8a689c8b26293a1346f.tar.gz external_bash-264a53cb86ea2287f3ccb8a689c8b26293a1346f.tar.bz2 |
Bugfix: two local buffer overflows
Patch from upstream (with slight changes):
Patch-ID: bash42-051
There are two local buffer overflows in parse.y that can cause the shell
to dump core when given many here-documents attached to a single command
or many nested loops.
Change-Id: I018cb4e7c120cd9d0e6827c23c65ab4875583056
-rw-r--r-- | parse.y | 36 | ||||
-rw-r--r-- | y.tab.c | 37 |
2 files changed, 57 insertions, 16 deletions
@@ -167,6 +167,9 @@ static char *read_a_line __P((int)); static int reserved_word_acceptable __P((int)); static int yylex __P((void)); + +static void push_heredoc __P((REDIRECT *)); +static char *mk_alexpansion __P((char *)); static int alias_expand_token __P((char *)); static int time_command_acceptable __P((void)); static int special_case_tokens __P((char *)); @@ -264,7 +267,9 @@ int parser_state; /* Variables to manage the task of reading here documents, because we need to defer the reading until after a complete command has been collected. */ -static REDIRECT *redir_stack[10]; +#define HEREDOC_MAX 16 + +static REDIRECT *redir_stack[HEREDOC_MAX]; int need_here_doc; /* Where shell input comes from. History expansion is performed on each @@ -306,7 +311,7 @@ static int global_extglob; or `for WORD' begins. This is a nested command maximum, since the array index is decremented after a case, select, or for command is parsed. */ #define MAX_CASE_NEST 128 -static int word_lineno[MAX_CASE_NEST]; +static int word_lineno[MAX_CASE_NEST+1]; static int word_top = -1; /* If non-zero, it is the token that we want read_token to return @@ -519,42 +524,42 @@ redirection: '>' WORD source.dest = 0; redir.filename = $2; $$ = make_redirection (source, r_reading_until, redir, 0); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | NUMBER LESS_LESS WORD { source.dest = $1; redir.filename = $3; $$ = make_redirection (source, r_reading_until, redir, 0); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | REDIR_WORD LESS_LESS WORD { source.filename = $1; redir.filename = $3; $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | LESS_LESS_MINUS WORD { source.dest = 0; redir.filename = $2; $$ = make_redirection (source, r_deblank_reading_until, redir, 0); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | NUMBER LESS_LESS_MINUS WORD { source.dest = $1; redir.filename = $3; $$ = make_redirection (source, r_deblank_reading_until, redir, 0); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | REDIR_WORD LESS_LESS_MINUS WORD { source.filename = $1; redir.filename = $3; $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN); - redir_stack[need_here_doc++] = $$; + push_heredoc ($$); } | LESS_LESS_LESS WORD { @@ -2531,6 +2536,21 @@ yylex () which allow ESAC to be the next one read. */ static int esacs_needed_count; +static void +push_heredoc (r) + REDIRECT *r; +{ + if (need_here_doc >= HEREDOC_MAX) + { + last_command_exit_value = EX_BADUSAGE; + need_here_doc = 0; + report_syntax_error (_("maximum here-document count exceeded")); + reset_parser (); + exit_shell (last_command_exit_value); + } + redir_stack[need_here_doc++] = r; +} + void gather_here_documents () { @@ -318,6 +318,9 @@ static char *read_a_line __P((int)); static int reserved_word_acceptable __P((int)); static int yylex __P((void)); + +static void push_heredoc __P((REDIRECT *)); +static char *mk_alexpansion __P((char *)); static int alias_expand_token __P((char *)); static int time_command_acceptable __P((void)); static int special_case_tokens __P((char *)); @@ -415,7 +418,10 @@ int parser_state; /* Variables to manage the task of reading here documents, because we need to defer the reading until after a complete command has been collected. */ -static REDIRECT *redir_stack[10]; +#define HEREDOC_MAX 16 + +static REDIRECT *redir_stack[HEREDOC_MAX]; + int need_here_doc; /* Where shell input comes from. History expansion is performed on each @@ -457,7 +463,7 @@ static int global_extglob; or `for WORD' begins. This is a nested command maximum, since the array index is decremented after a case, select, or for command is parsed. */ #define MAX_CASE_NEST 128 -static int word_lineno[MAX_CASE_NEST]; +static int word_lineno[MAX_CASE_NEST+1]; static int word_top = -1; /* If non-zero, it is the token that we want read_token to return @@ -2297,7 +2303,7 @@ yyreduce: source.dest = 0; redir.filename = (yyvsp[(2) - (2)].word); (yyval.redirect) = make_redirection (source, r_reading_until, redir, 0); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -2307,7 +2313,7 @@ yyreduce: source.dest = (yyvsp[(1) - (3)].number); redir.filename = (yyvsp[(3) - (3)].word); (yyval.redirect) = make_redirection (source, r_reading_until, redir, 0); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -2317,7 +2323,7 @@ yyreduce: source.filename = (yyvsp[(1) - (3)].word); redir.filename = (yyvsp[(3) - (3)].word); (yyval.redirect) = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -2327,7 +2333,7 @@ yyreduce: source.dest = 0; redir.filename = (yyvsp[(2) - (2)].word); (yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, 0); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -2337,7 +2343,7 @@ yyreduce: source.dest = (yyvsp[(1) - (3)].number); redir.filename = (yyvsp[(3) - (3)].word); (yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, 0); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -2347,7 +2353,7 @@ yyreduce: source.filename = (yyvsp[(1) - (3)].word); redir.filename = (yyvsp[(3) - (3)].word); (yyval.redirect) = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN); - redir_stack[need_here_doc++] = (yyval.redirect); + push_heredoc (yyval.redirect); } break; @@ -4843,6 +4849,21 @@ yylex () which allow ESAC to be the next one read. */ static int esacs_needed_count; +static void +push_heredoc (r) + REDIRECT *r; +{ + if (need_here_doc >= HEREDOC_MAX) + { + last_command_exit_value = EX_BADUSAGE; + need_here_doc = 0; + report_syntax_error (_("maximum here-document count exceeded")); + reset_parser (); + exit_shell (last_command_exit_value); + } + redir_stack[need_here_doc++] = r; +} + void gather_here_documents () { |