commit bash-20141003 snapshot

This commit is contained in:
Chet Ramey
2014-10-09 20:25:14 -04:00
parent 30595b57d9
commit 613d4ba419
30 changed files with 6247 additions and 29 deletions
+86 -5
View File
@@ -6790,7 +6790,8 @@ subst.c
----
variables.c
- initialize_shell_variables: when importing function definitions from
environment, use SEVAL_ONECMD flag for parse_and_execute
environment, use SEVAL_ONECMD flag for parse_and_execute. Part of
CVE-2014-6271
builtins/evalstring.c
- parse_and_execute: if SEVAL_ONECMD flag set, return immediately after
@@ -6812,11 +6813,12 @@ parse.y
parse.y
- push_heredoc: new function, pushes a here-doc redirection onto
redir_stack handling overflow of redir_stack. Exits on overflow.
Original fix from Florian Weimer <fweimer@redhat.com>
Original fix from Florian Weimer <fweimer@redhat.com>. Fix for
CVE-2014-7186
- change straight assignments to redir_stack to call push_redir
- add one to size of word_lineno stack to avoid off-by-one error
below in read_token_word. Overflow just results in line numbers
being wrong
being wrong. Fix for CVE-2014-7187
9/27
----
@@ -6846,7 +6848,86 @@ copy_cmd.c
- copy_redirects: before calling savestring on here_doc_eof, make
sure it's not NULL (it could have been the result of a here
document delimited by EOF or EOS). Fixes bug reported by
Michal Zalewski <lcamtuf@coredump.cx>.
Michal Zalewski <lcamtuf@coredump.cx>. Fix for CVE-2014-6277
make_cmd.c
- make_redirection: initialize here_doc_eof member to NULL
- make_redirection: initialize here_doc_eof member to NULL. Rest of
fix for CVE-2014-6277
9/29
----
parse.y
- current_input_line_state: return a sh_input_line_state_t containing
the current shell_input_line and its index and size variables
shell.h
- current_input_line_state: extern declaration
builtins/evalstring.c
- parse_and_execute: call reset_parser() before returning if
SEVAL_ONECMD set. Fixes bug reported by Michal Zalewski
<lcamtuf@coredump.cx> and designated CVE-2014-6278
- parse_and_execute: if we parse a function definition when
SEVAL_FUNCDEF is set, but don't consume the entire passed string,
throw an error, reset the parser, and return. Part of fix for
CVE-2014-6278
- parse_and_execute: if parsing the shell function definition when
SEVAL_FUNCDEF is set transforms the function name (e.g., if it
begins with a newline or begins or ends with whitespace), throw
an error, reset the parser, and return. Fixes bug reported by
Eric Kobrin <ekobrin@akamai.com>
10/2
----
jobs.c
- bgp_prune: don't do anything if bgpids.npid == 0 or bgpids.list == NULL.
This can happen if something gets run before the job control framework
is initialized. Bug report from <mancha1@zoho.com>
10/3
----
parse.y
- xparse_dolparen: don't set token_to_read to newline after calling
parse_string() and cleaning up when the shell is not interactive. This
makes the parser thing it's ok to read new commands even if it's not in
a state where that should be possible. Underlying fix for bug reported
by Michal Zalewski <lcamtuf@coredump.cx> and designated CVE-6278
- parser_remaining_input: new function, returns the portion of
shell_input_line that hasn't yet been read
- current_input_line_state: removed
shell.h
- parser_remaining_input: extern declaration
- current_input_line_state: removed
builtins/evalstring.c
- parse_and_execute: change code that checks whether parse_command has
consumed the entire passed string when SEVAL_FUNCDEF is used to use
parser_remaining_input instead of messing around with (new)
current_input_line_state. Part of fix for CVE-2014-6278
variables.c
- initialize_shell_variables: if we don't call parse_and_execute, free the
temporary string, since parse_and_execute won't. Report and fix from
Eric Kobrin <ekobrin@akamai.com>
10/4
----
print_cmd.c
- print_function_def: when in posix mode, print shell function
definitions as posix specifies them, without the leading
`function' keyword
general.c
- exportable_function_name: return 1 if the passed string can be
added to the environment as an exported function name. Currently
prohibits function names containing `/' and `=' from being
exported
general.h
- exportable_function_name: extern declaration
builtins/setattr.def
- set_or_show_attributes: if exporting a function with export -f,
call exportable_function_name to determine whether the function
should be exported; don't export function if it returns 0
+74 -4
View File
@@ -6790,7 +6790,8 @@ subst.c
----
variables.c
- initialize_shell_variables: when importing function definitions from
environment, use SEVAL_ONECMD flag for parse_and_execute
environment, use SEVAL_ONECMD flag for parse_and_execute. Part of
CVE-2014-6271
builtins/evalstring.c
- parse_and_execute: if SEVAL_ONECMD flag set, return immediately after
@@ -6812,11 +6813,12 @@ parse.y
parse.y
- push_heredoc: new function, pushes a here-doc redirection onto
redir_stack handling overflow of redir_stack. Exits on overflow.
Original fix from Florian Weimer <fweimer@redhat.com>
Original fix from Florian Weimer <fweimer@redhat.com>. Fix for
CVE-2014-7186
- change straight assignments to redir_stack to call push_redir
- add one to size of word_lineno stack to avoid off-by-one error
below in read_token_word. Overflow just results in line numbers
being wrong
being wrong. Fix for CVE-2014-7187
9/27
----
@@ -6846,4 +6848,72 @@ copy_cmd.c
- copy_redirects: before calling savestring on here_doc_eof, make
sure it's not NULL (it could have been the result of a here
document delimited by EOF or EOS). Fixes bug reported by
Michal Zalewski <lcamtuf@coredump.cx>.
Michal Zalewski <lcamtuf@coredump.cx>. Fix for CVE-2014-6277
make_cmd.c
- make_redirection: initialize here_doc_eof member to NULL. Rest of
fix for CVE-2014-6277
9/29
----
parse.y
- current_input_line_state: return a sh_input_line_state_t containing
the current shell_input_line and its index and size variables
shell.h
- current_input_line_state: extern declaration
builtins/evalstring.c
- parse_and_execute: call reset_parser() before returning if
SEVAL_ONECMD set. Fixes bug reported by Michal Zalewski
<lcamtuf@coredump.cx> and designated CVE-2014-6278
- parse_and_execute: if we parse a function definition when
SEVAL_FUNCDEF is set, but don't consume the entire passed string,
throw an error, reset the parser, and return. Part of fix for
CVE-2014-6278
- parse_and_execute: if parsing the shell function definition when
SEVAL_FUNCDEF is set transforms the function name (e.g., if it
begins with a newline or begins or ends with whitespace), throw
an error, reset the parser, and return. Fixes bug reported by
Eric Kobrin <ekobrin@akamai.com>
10/2
----
jobs.c
- bgp_prune: don't do anything if bgpids.npid == 0 or bgpids.list == NULL.
This can happen if something gets run before the job control framework
is initialized. Bug report from <mancha1@zoho.com>
10/3
----
parse.y
- xparse_dolparen: don't set token_to_read to newline after calling
parse_string() and cleaning up when the shell is not interactive. This
makes the parser thing it's ok to read new commands even if it's not in
a state where that should be possible. Underlying fix for bug reported
by Michal Zalewski <lcamtuf@coredump.cx> and designated CVE-6278
- parser_remaining_input: new function, returns the portion of
shell_input_line that hasn't yet been read
- current_input_line_state: removed
shell.h
- parser_remaining_input: extern declaration
- current_input_line_state: removed
builtins/evalstring.c
- parse_and_execute: change code that checks whether parse_command has
consumed the entire passed string when SEVAL_FUNCDEF is used to use
parser_remaining_input instead of messing around with (new)
current_input_line_state. Part of fix for CVE-2014-6278
variables.c
- initialize_shell_variables: if we don't call parse_and_execute, free the
temporary string, since parse_and_execute won't. Report and fix from
Eric Kobrin <ekobrin@akamai.com>
10/4
----
print_cmd.c
- print_function_def: when in posix mode, print shell function
definitions as posix specifies them, without the leading
`function' keyword
+6
View File
@@ -938,6 +938,11 @@ tests/exp3.sub f
tests/exp4.sub f
tests/exp5.sub f
tests/exp6.sub f
tests/exportfunc.tests f
tests/exportfunc.right f
tests/exportfunc1.sub f
tests/exportfunc2.sub f
tests/exportfunc3.sub f
tests/extglob.tests f
tests/extglob.right f
tests/extglob1.sub f
@@ -1131,6 +1136,7 @@ tests/run-dollars f
tests/run-errors f
tests/run-execscript f
tests/run-exp-tests f
tests/run-exportfunc f
tests/run-extglob f
tests/run-extglob2 f
tests/run-extglob3 f
+1300
View File
File diff suppressed because it is too large Load Diff
+22 -6
View File
@@ -312,12 +312,25 @@ parse_and_execute (string, from_file, flags)
{
struct fd_bitmap *bitmap;
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
if (flags & SEVAL_FUNCDEF)
{
internal_warning ("%s: ignoring function definition attempt", from_file);
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
break;
char *x;
/* If the command parses to something other than a straight
function definition, or if we have not consumed the entire
string, or if the parser has transformed the function
name (as parsing will if it begins or ends with shell
whitespace, for example), reject the attempt */
if (command->type != cm_function_def ||
((x = parser_remaining_input ()) && *x) ||
(STREQ (from_file, command->value.Function_def->name->word) == 0))
{
internal_warning (_("%s: ignoring function definition attempt"), from_file);
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
reset_parser ();
break;
}
}
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
@@ -382,7 +395,10 @@ parse_and_execute (string, from_file, flags)
discard_unwind_frame ("pe_dispose");
if (flags & SEVAL_ONECMD)
break;
{
reset_parser ();
break;
}
}
}
else
+5
View File
@@ -188,6 +188,11 @@ set_or_show_attributes (list, attribute, nodefs)
builtin_error (_("%s: not a function"), name);
any_failed++;
}
else if ((attribute & att_exported) && undo == 0 && exportable_function_name (name) == 0)
{
builtin_error (_("%s: cannot export"), name);
any_failed++;
}
else
SETVARATTR (var, attribute, undo);
+560
View File
@@ -0,0 +1,560 @@
This file is setattr.def, from which is created setattr.c.
It implements the builtins "export" and "readonly", in Bash.
Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES setattr.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
extern int posixly_correct;
extern int array_needs_making;
extern char *this_command_name;
extern sh_builtin_func_t *this_shell_builtin;
#ifdef ARRAY_VARS
extern int declare_builtin __P((WORD_LIST *));
#endif
#define READONLY_OR_EXPORT \
(this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
$BUILTIN export
$FUNCTION export_builtin
$SHORT_DOC export [-fn] [name[=value] ...] or export -p
Set export attribute for shell variables.
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
Options:
-f refer to shell functions
-n remove the export property from each NAME
-p display a list of all exported variables and functions
An argument of `--' disables further option processing.
Exit Status:
Returns success unless an invalid option is given or NAME is invalid.
$END
/* For each variable name in LIST, make that variable appear in the
environment passed to simple commands. If there is no LIST, then
print all such variables. An argument of `-n' says to remove the
exported attribute from variables named in LIST. An argument of
-f indicates that the names present in LIST refer to functions. */
int
export_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_exported, 0));
}
$BUILTIN readonly
$FUNCTION readonly_builtin
$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
Mark shell variables as unchangeable.
Mark each NAME as read-only; the values of these NAMEs may not be
changed by subsequent assignment. If VALUE is supplied, assign VALUE
before marking as read-only.
Options:
-a refer to indexed array variables
-A refer to associative array variables
-f refer to shell functions
-p display a list of all readonly variables or functions, depending on
whether or not the -f option is given
An argument of `--' disables further option processing.
Exit Status:
Returns success unless an invalid option is given or NAME is invalid.
$END
/* For each variable name in LIST, make that variable readonly. Given an
empty LIST, print out all existing readonly variables. */
int
readonly_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_readonly, 0));
}
#if defined (ARRAY_VARS)
# define ATTROPTS "aAfnp"
#else
# define ATTROPTS "fnp"
#endif
/* For each variable name in LIST, make that variable have the specified
ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
remaining names in LIST (doesn't work for readonly). */
int
set_or_show_attributes (list, attribute, nodefs)
register WORD_LIST *list;
int attribute, nodefs;
{
register SHELL_VAR *var;
int assign, undo, any_failed, assign_error, opt;
int functions_only, arrays_only, assoc_only;
int aflags;
char *name;
#if defined (ARRAY_VARS)
WORD_LIST *nlist, *tlist;
WORD_DESC *w;
#endif
functions_only = arrays_only = assoc_only = 0;
undo = any_failed = assign_error = 0;
/* Read arguments from the front of the list. */
reset_internal_getopt ();
while ((opt = internal_getopt (list, ATTROPTS)) != -1)
{
switch (opt)
{
case 'n':
undo = 1;
break;
case 'f':
functions_only = 1;
break;
#if defined (ARRAY_VARS)
case 'a':
arrays_only = 1;
break;
case 'A':
assoc_only = 1;
break;
#endif
case 'p':
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list)
{
if (attribute & att_exported)
array_needs_making = 1;
/* Cannot undo readonly status, silently disallowed. */
if (undo && (attribute & att_readonly))
attribute &= ~att_readonly;
while (list)
{
name = list->word->word;
if (functions_only) /* xxx -f name */
{
var = find_function (name);
if (var == 0)
{
builtin_error (_("%s: not a function"), name);
any_failed++;
}
else if (exportable_function_name (name) == 0)
{
builtin_error (_("%s: cannot export"), name);
any_failed++;
}
else
SETVARATTR (var, attribute, undo);
list = list->next;
continue;
}
/* xxx [-np] name[=value] */
assign = assignment (name, 0);
aflags = 0;
if (assign)
{
name[assign] = '\0';
if (name[assign - 1] == '+')
{
aflags |= ASS_APPEND;
name[assign - 1] = '\0';
}
}
if (legal_identifier (name) == 0)
{
sh_invalidid (name);
if (assign)
assign_error++;
else
any_failed++;
list = list->next;
continue;
}
if (assign) /* xxx [-np] name=value */
{
name[assign] = '=';
if (aflags & ASS_APPEND)
name[assign - 1] = '+';
#if defined (ARRAY_VARS)
/* Let's try something here. Turn readonly -a xxx=yyy into
declare -ra xxx=yyy and see what that gets us. */
if (arrays_only || assoc_only)
{
tlist = list->next;
list->next = (WORD_LIST *)NULL;
w = arrays_only ? make_word ("-ra") : make_word ("-rA");
nlist = make_word_list (w, list);
opt = declare_builtin (nlist);
if (opt != EXECUTION_SUCCESS)
assign_error++;
list->next = tlist;
dispose_word (w);
free (nlist);
}
else
#endif
/* This word has already been expanded once with command
and parameter expansion. Call do_assignment_no_expand (),
which does not do command or parameter substitution. If
the assignment is not performed correctly, flag an error. */
if (do_assignment_no_expand (name) == 0)
assign_error++;
name[assign] = '\0';
if (aflags & ASS_APPEND)
name[assign - 1] = '\0';
}
set_var_attribute (name, attribute, undo);
list = list->next;
}
}
else
{
SHELL_VAR **variable_list;
register int i;
if ((attribute & att_function) || functions_only)
{
variable_list = all_shell_functions ();
if (attribute != att_function)
attribute &= ~att_function; /* so declare -xf works, for example */
}
else
variable_list = all_shell_variables ();
#if defined (ARRAY_VARS)
if (attribute & att_array)
{
arrays_only++;
if (attribute != att_array)
attribute &= ~att_array;
}
else if (attribute & att_assoc)
{
assoc_only++;
if (attribute != att_assoc)
attribute &= ~att_assoc;
}
#endif
if (variable_list)
{
for (i = 0; var = variable_list[i]; i++)
{
#if defined (ARRAY_VARS)
if (arrays_only && array_p (var) == 0)
continue;
else if (assoc_only && assoc_p (var) == 0)
continue;
#endif
if ((var->attributes & attribute))
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
if (any_failed = sh_chkwrite (any_failed))
break;
}
}
free (variable_list);
}
}
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}
/* Show all variable variables (v == 1) or functions (v == 0) with
attributes. */
int
show_all_var_attributes (v, nodefs)
int v, nodefs;
{
SHELL_VAR **variable_list, *var;
int any_failed;
register int i;
variable_list = v ? all_shell_variables () : all_shell_functions ();
if (variable_list == 0)
return (EXECUTION_SUCCESS);
for (i = any_failed = 0; var = variable_list[i]; i++)
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
if (any_failed = sh_chkwrite (any_failed))
break;
}
free (variable_list);
return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
/* Show the attributes for shell variable VAR. If NODEFS is non-zero,
don't show function definitions along with the name. If PATTR is
non-zero, it indicates we're being called from `export' or `readonly'.
In POSIX mode, this prints the name of the calling builtin (`export'
or `readonly') instead of `declare', and doesn't print function defs
when called by `export' or `readonly'. */
int
show_var_attributes (var, pattr, nodefs)
SHELL_VAR *var;
int pattr, nodefs;
{
char flags[16], *x;
int i;
i = 0;
/* pattr == 0 means we are called from `declare'. */
if (pattr == 0 || posixly_correct == 0)
{
#if defined (ARRAY_VARS)
if (array_p (var))
flags[i++] = 'a';
if (assoc_p (var))
flags[i++] = 'A';
#endif
if (function_p (var))
flags[i++] = 'f';
if (integer_p (var))
flags[i++] = 'i';
if (nameref_p (var))
flags[i++] = 'n';
if (readonly_p (var))
flags[i++] = 'r';
if (trace_p (var))
flags[i++] = 't';
if (exported_p (var))
flags[i++] = 'x';
if (capcase_p (var))
flags[i++] = 'c';
if (lowercase_p (var))
flags[i++] = 'l';
if (uppercase_p (var))
flags[i++] = 'u';
}
else
{
#if defined (ARRAY_VARS)
if (array_p (var))
flags[i++] = 'a';
if (assoc_p (var))
flags[i++] = 'A';
#endif
if (function_p (var))
flags[i++] = 'f';
}
flags[i] = '\0';
/* If we're printing functions with definitions, print the function def
first, then the attributes, instead of printing output that can't be
reused as input to recreate the current state. */
if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
{
printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
nodefs++;
if (pattr == 0 && i == 1 && flags[0] == 'f')
return 0; /* don't print `declare -f name' */
}
if (pattr == 0 || posixly_correct == 0)
printf ("declare -%s ", i ? flags : "-");
else if (i)
printf ("%s -%s ", this_command_name, flags);
else
printf ("%s ", this_command_name);
#if defined (ARRAY_VARS)
if (invisible_p (var) && (array_p (var) || assoc_p (var)))
printf ("%s\n", var->name);
else if (array_p (var))
print_array_assignment (var, 1);
else if (assoc_p (var))
print_assoc_assignment (var, 1);
else
#endif
/* force `readonly' and `export' to not print out function definitions
when in POSIX mode. */
if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
printf ("%s\n", var->name);
else if (function_p (var))
printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
else if (invisible_p (var) || var_isset (var) == 0)
printf ("%s\n", var->name);
else
{
x = sh_double_quote (value_cell (var));
printf ("%s=%s\n", var->name, x);
free (x);
}
return (0);
}
int
show_name_attributes (name, nodefs)
char *name;
int nodefs;
{
SHELL_VAR *var;
#if 0
var = find_variable_tempenv (name);
#else
var = find_variable_noref (name);
#endif
if (var /* && invisible_p (var) == 0 */) /* XXX bash-4.4/bash-5.0 */
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
return (0);
}
else
return (1);
}
int
show_func_attributes (name, nodefs)
char *name;
int nodefs;
{
SHELL_VAR *var;
var = find_function (name);
if (var)
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
return (0);
}
else
return (1);
}
void
set_var_attribute (name, attribute, undo)
char *name;
int attribute, undo;
{
SHELL_VAR *var, *tv, *v;
char *tvalue;
if (undo)
var = find_variable (name);
else
{
tv = find_tempenv_variable (name);
/* XXX -- need to handle case where tv is a temp variable in a
function-scope context, since function_env has been merged into
the local variables table. */
if (tv && tempvar_p (tv))
{
tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
var = bind_variable (tv->name, tvalue, 0);
var->attributes |= tv->attributes & ~att_tempvar;
/* This avoids an error message when propagating a read-only var
later on. */
if (var->context == 0 && (attribute & att_readonly))
{
/* Don't bother to set the `propagate to the global variables
table' flag if we've just bound the variable in that table */
v = find_global_variable (tv->name);
if (v != var)
VSETATTR (tv, att_propagate);
}
else
VSETATTR (tv, att_propagate);
if (var->context != 0)
VSETATTR (var, att_propagate);
SETVARATTR (tv, attribute, undo); /* XXX */
stupidly_hack_special_variables (tv->name);
free (tvalue);
}
else
{
var = find_variable_notempenv (name);
if (var == 0)
{
var = bind_variable (name, (char *)NULL, 0);
if (no_invisible_vars == 0)
VSETATTR (var, att_invisible);
}
else if (var->context != 0)
VSETATTR (var, att_propagate);
}
}
if (var)
SETVARATTR (var, attribute, undo);
if (var && (exported_p (var) || (attribute & att_exported)))
array_needs_making++; /* XXX */
}
+1 -1
View File
@@ -459,7 +459,7 @@ char **argv;
void
builtin_usage()
{
fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS);
fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, prog, OPTIONS);
}
#ifndef HAVE_STRERROR
+22 -1
View File
@@ -245,15 +245,36 @@ check_identifier (word, check_word)
return (1);
}
/* Return 1 if STRING is a function name that the shell will import from
the environment. Currently we reject attempts to import shell functions
containing slashes, beginning with newlines or containing blanks. In
Posix mode, we require that STRING be a valid shell identifier. Not
used yet. */
int
legal_function_name (string)
importable_function_name (string, len)
char *string;
size_t len;
{
if (absolute_program (string)) /* don't allow slash */
return 0;
if (*string == '\n') /* can't start with a newline */
return 0;
if (shellblank (*string) || shellblank(string[len-1]))
return 0;
return (posixly_correct ? legal_identifier (string) : 1);
}
int
exportable_function_name (string)
char *string;
{
if (absolute_program (string))
return 0;
if (mbschr (string, '=') != 0)
return 0;
return 1;
}
/* Return 1 if STRING comprises a valid alias name. The shell accepts
essentially all characters except those which must be quoted to the
parser (which disqualifies them from alias expansion anyway) and `/'. */
+23 -1
View File
@@ -53,6 +53,7 @@ extern int interactive_comments;
extern int check_hashed_filenames;
extern int source_uses_path;
extern int source_searches_cwd;
extern int posixly_correct;
static char *bash_special_tilde_expansions __P((char *));
static int unquoted_tilde_word __P((const char *));
@@ -244,15 +245,36 @@ check_identifier (word, check_word)
return (1);
}
/* Return 1 if STRING is a function name that the shell will import from
the environment. Currently we reject attempts to import shell functions
containing slashes, beginning with newlines or containing blanks. In
Posix mode, we require that STRING be a valid shell identifier. Not
used yet. */
int
legal_function_name (string)
importable_function_name (string, len)
char *string;
size_t len;
{
if (absolute_program (string)) /* don't allow slash */
return 0;
if (*string == '\n') /* can't start with a newline */
return 0;
if (shellblank (*string) || shellblank(string[len-1]))
return 0;
return (posixly_correct ? legal_identifier (string) : 1);
}
int
exportable_function_name (string)
char *string;
{
if (absolute_program (name))
return 0;
if (mbschr (string, '=') != 0)
return 0;
return 1;
}
/* Return 1 if STRING comprises a valid alias name. The shell accepts
essentially all characters except those which must be quoted to the
parser (which disqualifies them from alias expansion anyway) and `/'. */
+2 -1
View File
@@ -283,7 +283,8 @@ extern void print_rlimtype __P((RLIMTYPE, int));
extern int all_digits __P((char *));
extern int legal_number __P((const char *, intmax_t *));
extern int legal_identifier __P((char *));
extern int legal_function_name __P((char *));
extern int importable_function_name __P((char *, size_t));
extern int exportable_function_name __P((char *));
extern int check_identifier __P((WORD_DESC *, int));
extern int legal_alias_name __P((char *, int));
extern int assignment __P((const char *, int));
+1
View File
@@ -283,6 +283,7 @@ extern void print_rlimtype __P((RLIMTYPE, int));
extern int all_digits __P((char *));
extern int legal_number __P((const char *, intmax_t *));
extern int legal_identifier __P((char *));
extern int importable_function_name __P((char *, size_t));
extern int check_identifier __P((WORD_DESC *, int));
extern int legal_alias_name __P((char *, int));
extern int assignment __P((const char *, int));
+3
View File
@@ -772,6 +772,9 @@ bgp_prune ()
{
struct pidstat *ps;
if (bgpids.npid == 0 || bgpids.list == 0)
return; /* just paranoia */
while (bgpids.npid > js.c_childmax)
{
ps = bgpids.list;
+13 -2
View File
@@ -2538,6 +2538,16 @@ shell_ungetc (c)
eol_ungetc_lookahead = c;
}
char *
parser_remaining_input ()
{
if (shell_input_line == 0)
return 0;
if (shell_input_line_index < 0 || shell_input_line_index >= shell_input_line_len)
return '\0'; /* XXX */
return (shell_input_line + shell_input_line_index);
}
#ifdef INCLUDE_UNUSED
/* Back the input pointer up by one, effectively `ungetting' a character. */
static void
@@ -4034,6 +4044,7 @@ xparse_dolparen (base, string, indp, flags)
/*(*/
parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
shell_eof_token = ')';
parse_string (string, "command substitution", sflags, &ep);
shell_eof_token = orig_eof_token;
@@ -4041,8 +4052,8 @@ xparse_dolparen (base, string, indp, flags)
reset_parser ();
/* reset_parser clears shell_input_line and associated variables */
restore_input_line_state (&ls);
if (interactive)
token_to_read = 0;
token_to_read = 0;
/* Need to find how many characters parse_and_execute consumed, update
*indp, if flags != 0, copy the portion of the string parsed into RET
+1 -1
View File
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
#define PATCHLEVEL 25
#define PATCHLEVEL 28
#endif /* _PATCHLEVEL_H_ */
+6 -1
View File
@@ -51,6 +51,7 @@ extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
#endif
extern int indirection_level;
extern int posixly_correct;
static int indentation;
static int indentation_amount = 4;
@@ -1275,7 +1276,11 @@ print_function_def (func)
REDIRECT *func_redirects;
func_redirects = NULL;
cprintf ("function %s () \n", func->name->word);
/* When in posix mode, print functions as posix specifies them. */
if (posixly_correct == 0)
cprintf ("function %s () \n", func->name->word);
else
cprintf ("%s () \n", func->name->word);
add_unwind_protect (reset_locals, 0);
indent (indentation);
+1595
View File
File diff suppressed because it is too large Load Diff
+1911
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -180,6 +180,8 @@ typedef struct _sh_input_line_state_t {
} sh_input_line_state_t;
/* Let's try declaring these here. */
extern char *parser_remaining_input __P((void));
extern sh_parser_state_t *save_parser_state __P((sh_parser_state_t *));
extern void restore_parser_state __P((sh_parser_state_t *));
+16
View File
@@ -0,0 +1,16 @@
exportfunc ok 1
exportfunc ok 2
./exportfunc.tests: line 24: cve7169-bad: No such file or directory
./exportfunc.tests: eval: line 30: syntax error: unexpected end of file
./exportfunc.tests: line 30: cve7169-bad2: No such file or directory
./exportfunc1.sub: line 1: maximum here-document count exceeded
/usr/local/build/bash/bash-current/bash: warning: here-document at line 0 delimited by end-of-file (wanted `a')
./exportfunc.tests: line 51: HELLO_WORLD: No such file or directory
eval ok
./exportfunc3.sub: line 10: export: foo=bar: cannot export
status: 1
equals-1
/usr/local/build/bash/bash-current/bash: foo=bar: command not found
bad echo
./exportfunc3.sub: line 23: export: /bin/echo: cannot export
bar
+71
View File
@@ -0,0 +1,71 @@
# normal operation
foo()
{
echo exportfunc ok 1
}
export -f foo
${THIS_SH} -c foo
unset -f foo
foo-a ()
{
echo exportfunc ok 2
}
export -f foo-a
${THIS_SH} -c 'foo-a'
# CVE-2014-6271
env -i BASH_FUNC_foo%%='() { echo cve6271 ok; } ; echo BAD' ${THIS_SH} -c foo 2>/dev/null
# CVE-2014-7169
rm -f cve7169-bad
env -i BASH_FUNC_X%%='() { (a)=>\' ${THIS_SH} -c cve7169-bad 2>/dev/null
: < cve7169-bad
rm -f cve7169-bad
echo cve7169-bad2 > bar
rm -f cve7169-bad2
eval 'X() { (a)>\' ; . ./bar 2>/dev/null
: < cve7169-bad2
rm -f cve7169-bad2 bar
# CVE-2014-7186
${THIS_SH} ./exportfunc1.sub
# CVE-2014-7187
${THIS_SH} ./exportfunc2.sub
# CVE-2014-6277
env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<0 0" ${THIS_SH} -c foo 2>/dev/null
env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<`perl -e '{print "A"x100000}'` 0" ${THIS_SH} -c foo 2>/dev/null
${THIS_SH} -c "f(){ x(){ _;}; x(){ _;}<<a;}"
# CVE-2014-6278
env 'BASH_FUNC_FOO%%=() { 0;}>r[0${$(}0 {>"$(id >/dev/tty)"; }' ${THIS_SH} -c : 2>/dev/null
rm -f HELLO_WORLD
env BASH_FUNC_FOO%%='() { 0;}>r[0${$(}0 {>HELLO_WORLD; }' ${THIS_SH} -c : 2>/dev/null
: < HELLO_WORLD
env BASH_FUNC_x%%='() { _;}>_[$($())] { echo vuln;}' ${THIS_SH} -c : 2>/dev/null
env -i BASH_FUNC_x%%='() { _; } >_[${ $() }] { id; }' ${THIS_SH} -c : 2>/dev/null
env BASH_FUNC_x%%=$'() { _;}>_[$($())]\n{ echo vuln;}' ${THIS_SH} -c : 2>/dev/null
eval 'x() { _;}>_[$($())] { echo vuln;}' 2>/dev/null
eval 'foo() { _; } >_[${ $() }] ;{ echo eval ok; }'
# other tests fixed in bash43-030 concerning function name transformation
env $'BASH_FUNC_\nfoo%%=() { echo transform-1; }' ${THIS_SH} -c foo 2>/dev/null
env $'BASH_FUNC_foo\n%%=() { echo transform-2; }' ${THIS_SH} -c foo 2>/dev/null
env $'BASH_FUNC_ foo %%=() { echo transform-3; }' ${THIS_SH} -c foo 2>/dev/null
unset -f foo
env $'BASH_FUNC_#badname%%'=$'() { :; }\nfoo () { echo transform-4; } ' ${THIS_SH} -c 'foo' 2>/dev/null
# tests of exported names
${THIS_SH} ./exportfunc3.sub
+68
View File
@@ -0,0 +1,68 @@
# normal operation
foo()
{
echo exportfunc ok 1
}
export -f foo
${THIS_SH} -c foo
unset -f foo
foo-a ()
{
echo exportfunc ok 2
}
export -f foo-a
${THIS_SH} -c 'foo-a'
# CVE-2014-6271
env -i BASH_FUNC_foo%%='() { echo cve6271 ok; } ; echo BAD' ${THIS_SH} -c foo 2>/dev/null
# CVE-2014-7169
rm -f cve7169-bad
env -i BASH_FUNC_X%%='() { (a)=>\' ${THIS_SH} -c cve7169-bad 2>/dev/null
: < cve7169-bad
rm -f cve7169-bad
echo cve7169-bad2 > bar
rm -f cve7169-bad2
eval 'X() { (a)>\' ; . ./bar 2>/dev/null
: < cve7169-bad2
rm -f cve7169-bad2 bar
# CVE-2014-7186
${THIS_SH} ./exportfunc1.sub
# CVE-2014-7187
${THIS_SH} ./exportfunc2.sub
# CVE-2014-6277
env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<0 0" ${THIS_SH} -c foo 2>/dev/null
env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<`perl -e '{print "A"x100000}'` 0" ${THIS_SH} -c foo 2>/dev/null
${THIS_SH} -c "f(){ x(){ _;}; x(){ _;}<<a;}"
# CVE-2014-6278
env 'BASH_FUNC_FOO%%=() { 0;}>r[0${$(}0 {>"$(id >/dev/tty)"; }' ${THIS_SH} -c : 2>/dev/null
rm -f HELLO_WORLD
env BASH_FUNC_FOO%%='() { 0;}>r[0${$(}0 {>HELLO_WORLD; }' ${THIS_SH} -c : 2>/dev/null
: < HELLO_WORLD
env BASH_FUNC_x%%='() { _;}>_[$($())] { echo vuln;}' ${THIS_SH} -c : 2>/dev/null
env -i BASH_FUNC_x%%='() { _; } >_[${ $() }] { id; }' ${THIS_SH} -c : 2>/dev/null
env BASH_FUNC_x%%=$'() { _;}>_[$($())]\n{ echo vuln;}' ${THIS_SH} -c : 2>/dev/null
eval 'x() { _;}>_[$($())] { echo vuln;}' 2>/dev/null
eval 'foo() { _; } >_[${ $() }] ;{ echo eval ok; }'
# other tests fixed in bash43-030 concerning function name transformation
env $'BASH_FUNC_\nfoo%%=() { echo transform-1; }' ${THIS_SH} -c foo 2>/dev/null
env $'BASH_FUNC_foo\n%%=() { echo transform-2; }' ${THIS_SH} -c foo 2>/dev/null
env $'BASH_FUNC_ foo %%=() { echo transform-3; }' ${THIS_SH} -c foo 2>/dev/null
unset -f foo
env $'BASH_FUNC_#badname%%'=$'() { :; }\nfoo () { echo transform-4; } ' ${THIS_SH} -c 'foo' 2>/dev/null
+21
View File
@@ -0,0 +1,21 @@
cat <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
EOF
echo after EOF
+400
View File
@@ -0,0 +1,400 @@
for x1 in ; do :
for x2 in ; do :
for x3 in ; do :
for x4 in ; do :
for x5 in ; do :
for x6 in ; do :
for x7 in ; do :
for x8 in ; do :
for x9 in ; do :
for x10 in ; do :
for x11 in ; do :
for x12 in ; do :
for x13 in ; do :
for x14 in ; do :
for x15 in ; do :
for x16 in ; do :
for x17 in ; do :
for x18 in ; do :
for x19 in ; do :
for x20 in ; do :
for x21 in ; do :
for x22 in ; do :
for x23 in ; do :
for x24 in ; do :
for x25 in ; do :
for x26 in ; do :
for x27 in ; do :
for x28 in ; do :
for x29 in ; do :
for x30 in ; do :
for x31 in ; do :
for x32 in ; do :
for x33 in ; do :
for x34 in ; do :
for x35 in ; do :
for x36 in ; do :
for x37 in ; do :
for x38 in ; do :
for x39 in ; do :
for x40 in ; do :
for x41 in ; do :
for x42 in ; do :
for x43 in ; do :
for x44 in ; do :
for x45 in ; do :
for x46 in ; do :
for x47 in ; do :
for x48 in ; do :
for x49 in ; do :
for x50 in ; do :
for x51 in ; do :
for x52 in ; do :
for x53 in ; do :
for x54 in ; do :
for x55 in ; do :
for x56 in ; do :
for x57 in ; do :
for x58 in ; do :
for x59 in ; do :
for x60 in ; do :
for x61 in ; do :
for x62 in ; do :
for x63 in ; do :
for x64 in ; do :
for x65 in ; do :
for x66 in ; do :
for x67 in ; do :
for x68 in ; do :
for x69 in ; do :
for x70 in ; do :
for x71 in ; do :
for x72 in ; do :
for x73 in ; do :
for x74 in ; do :
for x75 in ; do :
for x76 in ; do :
for x77 in ; do :
for x78 in ; do :
for x79 in ; do :
for x80 in ; do :
for x81 in ; do :
for x82 in ; do :
for x83 in ; do :
for x84 in ; do :
for x85 in ; do :
for x86 in ; do :
for x87 in ; do :
for x88 in ; do :
for x89 in ; do :
for x90 in ; do :
for x91 in ; do :
for x92 in ; do :
for x93 in ; do :
for x94 in ; do :
for x95 in ; do :
for x96 in ; do :
for x97 in ; do :
for x98 in ; do :
for x99 in ; do :
for x100 in ; do :
for x101 in ; do :
for x102 in ; do :
for x103 in ; do :
for x104 in ; do :
for x105 in ; do :
for x106 in ; do :
for x107 in ; do :
for x108 in ; do :
for x109 in ; do :
for x110 in ; do :
for x111 in ; do :
for x112 in ; do :
for x113 in ; do :
for x114 in ; do :
for x115 in ; do :
for x116 in ; do :
for x117 in ; do :
for x118 in ; do :
for x119 in ; do :
for x120 in ; do :
for x121 in ; do :
for x122 in ; do :
for x123 in ; do :
for x124 in ; do :
for x125 in ; do :
for x126 in ; do :
for x127 in ; do :
for x128 in ; do :
for x129 in ; do :
for x130 in ; do :
for x131 in ; do :
for x132 in ; do :
for x133 in ; do :
for x134 in ; do :
for x135 in ; do :
for x136 in ; do :
for x137 in ; do :
for x138 in ; do :
for x139 in ; do :
for x140 in ; do :
for x141 in ; do :
for x142 in ; do :
for x143 in ; do :
for x144 in ; do :
for x145 in ; do :
for x146 in ; do :
for x147 in ; do :
for x148 in ; do :
for x149 in ; do :
for x150 in ; do :
for x151 in ; do :
for x152 in ; do :
for x153 in ; do :
for x154 in ; do :
for x155 in ; do :
for x156 in ; do :
for x157 in ; do :
for x158 in ; do :
for x159 in ; do :
for x160 in ; do :
for x161 in ; do :
for x162 in ; do :
for x163 in ; do :
for x164 in ; do :
for x165 in ; do :
for x166 in ; do :
for x167 in ; do :
for x168 in ; do :
for x169 in ; do :
for x170 in ; do :
for x171 in ; do :
for x172 in ; do :
for x173 in ; do :
for x174 in ; do :
for x175 in ; do :
for x176 in ; do :
for x177 in ; do :
for x178 in ; do :
for x179 in ; do :
for x180 in ; do :
for x181 in ; do :
for x182 in ; do :
for x183 in ; do :
for x184 in ; do :
for x185 in ; do :
for x186 in ; do :
for x187 in ; do :
for x188 in ; do :
for x189 in ; do :
for x190 in ; do :
for x191 in ; do :
for x192 in ; do :
for x193 in ; do :
for x194 in ; do :
for x195 in ; do :
for x196 in ; do :
for x197 in ; do :
for x198 in ; do :
for x199 in ; do :
for x200 in ; do :
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
done
+25
View File
@@ -0,0 +1,25 @@
# test function names that cannot be exported
unset foo # remove from environment if necessary
function foo=bar
{
echo equals-1
}
export -f 'foo=bar'
echo status: $?
foo\=bar
printenv | grep 'foo=bar'
${THIS_SH} -c 'foo\=bar'
function /bin/echo
{
echo bad echo
}
/bin/echo foo
export -f '/bin/echo'
${THIS_SH} -c '/bin/echo bar'
+2
View File
@@ -0,0 +1,2 @@
${THIS_SH} ./exportfunc.tests > /tmp/xx 2>&1
diff /tmp/xx exportfunc.right && rm -f /tmp/xx
+3
View File
@@ -424,6 +424,7 @@ trap_handler (sig)
SIGRETURN (0);
}
itrace("trap_handler: received %d", sig);
if ((sig >= NSIG) ||
(trap_list[sig] == (char *)DEFAULT_SIG) ||
(trap_list[sig] == (char *)IGNORE_SIG))
@@ -857,7 +858,9 @@ run_exit_trap ()
retval = trap_saved_exit_value;
running_trap = 0;
#if defined (ARRAY_VARS)
array_dispose (ps);
#endif
return retval;
}
+4 -2
View File
@@ -380,10 +380,12 @@ initialize_shell_variables (env, privmode)
memcpy (temp_string + namelen + 1, string, string_length + 1);
/* Don't import function names that are invalid identifiers from the
environment, though we still allow them to be defined as shell
variables. */
environment in posix mode, though we still allow them to be defined as
shell variables. */
if (absolute_program (tname) == 0 && (posixly_correct == 0 || legal_identifier (tname)))
parse_and_execute (temp_string, tname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
else
free (temp_string); /* parse_and_execute does this */
if (temp_var = find_function (tname))
{
+2 -2
View File
@@ -1,6 +1,6 @@
/* version.c -- distribution and version numbers. */
/* Copyright (C) 1989-2013 Free Software Foundation, Inc.
/* Copyright (C) 1989-2014 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -43,7 +43,7 @@ const char * const release_status = (char *)0;
#endif
const char * const sccs_version = SCCSVERSION;
const char * const bash_copyright = N_("Copyright (C) 2013 Free Software Foundation, Inc.");
const char * const bash_copyright = N_("Copyright (C) 2014 Free Software Foundation, Inc.");
const char * const bash_license = N_("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
/* If == 31, shell compatible with bash-3.1, == 32 with bash-3.2, and so on */
+2 -2
View File
@@ -1,6 +1,6 @@
/* version.c -- distribution and version numbers. */
/* Copyright (C) 1989-2012 Free Software Foundation, Inc.
/* Copyright (C) 1989-2014 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -43,7 +43,7 @@ const char * const release_status = (char *)0;
#endif
const char * const sccs_version = SCCSVERSION;
const char * const bash_copyright = N_("Copyright (C) 2012 Free Software Foundation, Inc.");
const char * const bash_copyright = N_("Copyright (C) 2014 Free Software Foundation, Inc.");
const char * const bash_license = N_("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
/* If == 31, shell compatible with bash-3.1, == 32 with bash-3.2, and so on */