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: Sun, 14 Dec 2014 14:39:29 -0500
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.2.0

On 12/7/14 5:36 AM, Stephane Chazelas wrote:

> In this case, it's not about sanitizing external input, at least
> as far as the $external_input variable is concerned.

In a way, it is.  It's understanding the context in which external
input is going to be used.  However, I think that you're right, and
that the rules concerning assignment statements as arguments to
what the bash documentation refers to as `declaration commands' should
be closer to what they are for standalone assignment statements.

> 
> When a script writer writes:
> 
>    declare -l a="$external_input"
> 
> he's entitled to expect $a to contain the lower case version of
> $external_input whatever $external_input contain.
> 
> If $external_input happens to contain "($(echo FOO))", I'd
> expect $a to contain "($(echo foo))", not "foo" just because
> $external_input happens to follow a specific pattern.

So the question is under which conditions assignment statements can be
considered as such when they are arguments to declare.  The situation
is complicated by the fact that declare is a builtin, so one round of
word expansion is performed before declare sees the arguments.  Bash
does do some analysis of the arguments to declaration builtins so it can
inhibit word splitting and filename generation, and it has internal
provisions to pass additional information to the builtin, so I'm sure I
can implement whatever conditions are appropriate.

> Where the script writer may be to blame is for running "declare"
> when that "a" variable was previous declared as an array (though
> that could have been done by code he invoked from 3rd party
> libraries), or not anticipating that his code would be invoked
> in contexts where that "a" variable may have been declared as an
> array.

It's true.  I agree that it's better to decide what the appropriate
rules are and document them.

> 
> But even then, he can be excused not to imagine that
> 
>    declare -l a="$external_input"
> 
> could ever run an arbitrary commands.

Maybe.  That's actually a straightforward consequence of a standard set
of rules: declare is a builtin, and so its arguments are run through the
usual word expansions before declare sees them (including quote removal);
declare accepts the usual name=word assignment syntax, including compound
assignment; and assigning to associative arrays involves running subscripts
through a defined set of expansions.

The question we're really considering is how much further to move
declaration commands away from the semantics of other builtins, at least
when using the compound assignment syntax.


> And even if he intended to declare "a" as an array beforehand,
> he could reasonably expect
> 
>    declare -l a="$external_input"
> 
> to do the same as
> 
>    declare -l a; a="$external_input"
> 
> That is, the same as a[0]="$external_input".

And we get to the fundamental issue.  Is it appropriate to require
arguments to declaration commands to be valid assignment statements when
the parser sees them, instead of when the builtin sees them, at least
when using the compound assignment syntax.

I'm ok with tightening the rules and saying that it is, but it's not
backwards compatible and changes the behavior of things like

declare -a foo='(1 2 3)'

which I imagine plenty of people have used and has been a supported way
to do compound assignment for many years.

> ~$ bash --version
> GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
> Copyright (C) 2013 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> 
> This is free software; you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.
> ~$ b='($(uname))' bash --norc -c 'declare -a a; declare a="$b"; printf 
> "<%s>\n" "$a" "${a[0]}"'
> <>
> <Linux>
> 
> (on Linux Mint amd64).

$ ./bash --version
GNU bash, version 4.3.30(15)-release (x86_64-apple-darwin13.1.0)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ b='($(uname))' ./bash --norc -c 'declare -a a; declare a="$b"; printf
"<%s>\n" "$a" "${a[0]}"'
<Darwin>
<Darwin>

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]