Thanks konsolebox and Eduardo, glad to see I'm not the only one seeing an issue in that.
A few additions inline: 2014-12-09 10:51:51 +0800, konsolebox: [...] > (But I think those who used to recommend using declare as a general tool > for assigning values remotely over evil eval would love it since > it makes assignments like `declare -g "$var=$something"` possible > which naturally should have been illegal.) [...] BTW, it's worth noting (and maybe documenting) that word splitting and filename generation are performed in: declare -g $var=$something (or declare ''var=$something or declare f\oo=$bar...) So it must be indeed: declare -g "$var=$something" > Anyhow, this problem would only happen if a variable in a specific > scope (and only in that scope) has already been set previously as an > array and it doesn't always happen if you write your scripts well. > > > It may be worth recommending people do a "unset var" before > > doing a "declare [-<option>] var" > > I actually find it better to mention that on a simple assignment like > declare var=$something, var's type doesn't change if it has already been > declared previously as an array. Strictly speaking, "if it has already been declared" *or assigned* (as in a[0]=x or a=()) "previously as an array" *in the current scope*, otherwise, the variable is declared as a scalar (but see below for more complications), : $ bash -c 'f() { declare a=1; declare -p a; }; a=(); f' declare -- a="1" However, if "a" was exported or readonly even in an outer scope before, it's still exported or readonly (that doesn't seem to be the case for any of the other variable attributes): $ a=3 bash -c 'f() { declare a=1; declare -p a; }; a=(); f' declare -x a="1" $ a=3 bash -c 'f() { declare a=1; declare -p a; }; declare -r a=2; f' bash: line 0: declare: a: readonly variable declare -rx a="2" What that means is the "local" or "declare" is not a complete solution to your scoping problem. You still need to resolve to name spaces. See the eternal discussion between ksh and bash about dynamic vs static scope for local variables as well. ksh: $ a=3 ksh -c 'function f { typeset a=1; echo "$a"; env | grep "^a"; }; typeset -r a=2; f' 1 ("a" in the function is not exported but the original "a" was removed from the environment, not sure it's a lot better, but it's probably as good as we can reasonably get without major change of design). $ a=0 ksh -c 'function f { typeset a=1; g; h; echo "f: $a"; }; function g { a=2; }; function h { typeset a=3; };f' f: 1 "f" doesn't have to worry about alien functions changing its local variables under its feet. [...] > Shared functions otoh should be responsible of making sure that their > work variables are placed as local. This is also a common > practice. [...] That doesn't apply if you want to use a function library written in "sh" (the POSIX "sh" language doesn't have local scope except via subshells). Then again, that library should use its own namespace. So, if good practice is followed all over the board, then that issue is very unlikely to be hit. Then again, I see no compelling reason not to fix it. Again, the issue is aggravated by the fact that it's hard to detect (your scripts will still work but will have a hidden vulnerability). -- Stephane