bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: declare a="$b" if $a previously set as array


From: Chet Ramey
Subject: Re: declare a="$b" if $a previously set as array
Date: Sat, 06 Dec 2014 20:19:21 -0500
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.2.0

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    chet@case.edu    http://cnswww.cns.cwru.edu/~chet/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]