On 12/6/14 6:24 PM, Stephane Chazelas wrote: > Hiya, > > this is potentially dangerous: > > If $a was previously used as an array (or hash), then: > > declare a=$external_input
So what you're saying is that blindly using external input can sometimes have negative consequences? > (or: > declare -r a=$external_input > for instance (or -l...)... but not: > readonly a=$external_input > (or export) > ) > > becomes a code injection vulnerability: > > $ b='($(uname>&2))' bash -c 'a=(); declare -r a=$b' > Linux > > That could be an issue in scripts that are meant to be sourced > or functions that call other functions before using "declare". > That's aggravated by the fact that the issue doesn't show up > unless $external_input starts with (. At some point, you have to put some burden of responsibility onto the script writer. > > If not changed, that behaviour may be worth documented. declare's behavior is already documented: "Arrays are assigned to using compound assignments of the form name=(value1 ... valuen), where each value is of the form [subscript]=string." ... "This syntax is also accepted by the declare builtin." > ksh behaviour that only accepts "(" when litteral and unquoted > (or zsh that doesn't accept it at all) is a bit saner IMO. declare is a builtin, not a reserved word. At the point when it is invoked, its arguments have already been expanded. The question is how much argument-mangling you want to do, and how much is worth it. > > In ksh: > > $ typeset -a a="(2)"; echo "$a" > (2) In ksh, typeset is essentially a reserved word. Doing a trace on that command is illustrative; it appears that ksh performs the assignment before setting the variable's attributes, which means it can more closely emulate assignment statement behavior. I'm not sure how faithfully that reflects what ksh is doing internally. > > There also seems to be a minor bug there in bash: > > $ b='($(uname))' bash -c 'declare -a a; declare a="$b"; printf "<%s>\n" "$a" > "${a[0]}"' > <> > <Linux> > $ b='($(uname))' bash -c 'a=(); declare a=$b; printf "<%s>\n" "$a" "${a[0]}"' > <Linux> > <Linux> > > (I'd expect the same result for both). You don't say what version of bash you're using, but I get the same results for both commands back to bash-4.0 (when I quit testing). > It may be worth recommending people do a "unset var" before > doing a "declare [-<option>] var" unless they do intend to retain the > previous value and/or type Sure, that's good programming practice. It should be recommended in a bash programming guide -- and there are several excellent ones. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRU c...@case.edu http://cnswww.cns.cwru.edu/~chet/