Hello,

please consider the following code:

bash -c '
  a() {
    local X=2
    declare -p X
    b
  }
  b() {
    local X=3
    unset -v X
    echo "${X-unset}"
    printenv X || echo Not in env
  }
  X=1
  a'

That gives:

declare -- X="2"
unset
Not in env

as expected.

Now call the same command with X=0 in the environment, and you
get:

declare -x -- X="2"
unset
2

That is, "unset" confirms it was successfully unset. However,
printenv still received a X=2 in its environment as if X was
still set and exported, revealing the value of the local
variable of the parent scope (which inherited the export
attribute)

If changed to:

X=0 bash -c '
  a() {
    local +x X=2
    declare -p X
    b
  }
  b() {
    local X=3
    unset -v X
    echo "${X-unset}"
    printenv X || echo Not in env
  }
  X=1
  a'

That gives:

declare -- X="2"
unset
1

This time it's the value of the variable two levels up the stack
that is leaked to the environment (while parameter expansions
still confirm the variable is unset).

Reproduced with 5.2.21(1)-release and current git HEAD. Setting
the localvar_unset option doesn't seem to change the behaviour.

In all of the above, I'd expect printenv not to find that
variable that has just been unset.

The doc states:

> The ‘unset’ builtin also acts using the same dynamic scope: if
> a variable is local to the current scope, ‘unset’ unsets it;
> otherwise the unset will refer to the variable found in any
> calling scope as described above.  If a variable at the
> current local scope is unset, it remains so (appearing as
> unset) until it is reset in that scope or until the function
> returns.  Once the function returns, any instance of the
> variable at a previous scope becomes visible.

But says nothing about variables from upper scopes still being
kept in the environment.

In the Environment section:

> The environment inherited by any executed command consists of
> the shell's initial environment, whose values may be modified
> in the shell, less any pairs removed by the ‘unset’ and
> ‘export -n’ commands, plus any additions via the ‘export’ and
> ‘declare -x’ commands.

-- 
Stephane

Reply via email to