[Top][All Lists]

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

Re: segfault w/ localvar_inherit and associative array insert

From: Grisha Levit
Subject: Re: segfault w/ localvar_inherit and associative array insert
Date: Sun, 29 Jul 2018 22:26:00 -0400

Though my motivation in reporting this was to point out the segfault, I'm a
bit confused by why compound assignment should be an error here.

> Bash is consistent in defaulting to indexed array variables when you don't
> specify -A and assign a value using the compound assignment syntax.

Since localvar_inherit is new behavior anyway, I'm not sure why the above must
be the controlling default. I think a less surprising-to-the-user default
might be "when this option is set, Bash consistently inherits the
previous-scope variable's value/attributes before performing any new
value/attribute modifications".

In the alternative, it seems that Bash should be consistent in also
defaulting to indexed arrays in the case of `array[subscript]' assignments
with no -A specified?

i.e. if the following should be an error:

    $ declare -A A; f() { local A=([Y]=Y); declare -p A; }; f
    Segmentation fault: 11

should the following produce a local indexed array/an error as well (instead
of the associative array assignment it currently does)?

    $ declare -A A; f() { local A[Y]=Y; declare -p A; }; f
    declare -A A=([Y]="Y" )


> So you create a local indexed array variable, and when you attempt to
> inherit the value from a global associative array before performing any
> specified assignment, you should either ignore the inherited value or
> throw an error.

I feel like this doesn't seem very apparent from the documentation (though
it's not strictly contradictory, the step where we first check the RHS to see
if it is a compound array assignment seems surprising):

    If set, local variables inherit the value and attributes of a variable
    of the same name that exists at a previous scope *before any new value
    is assigned*.


There's also an issue that only a value of a matching type is inherited and
the usual scalar-to-array[0] conversion is not performed. I'm not sure if
this is intentional but I do want to point it out as potentially surprising:

    $ unset a s; a=(X) s=X
    $ shopt -s localvar_inherit

    $ f() { local -a a s; declare -p a s; }; f
    declare -a a=([0]="X")
    declare -a s=()

    $ f() { local a+=(Y) s+=(Y); declare -p a s; }; f
    declare -a a=([0]="X" [1]="Y")
    declare -a s=([0]="Y")

    $ f() { local -a a+=Y s+=Y; declare -p a s; }; f
    declare -a a=([0]="XY")
    declare -a s=([0]="Y")


Maybe I'm missing the intended use of the option but based on the description
in the man page, I guess I'm expecting `declare var' with localvar_inherit to
be roughly the same as `eval $(declare -p var 2>/dev/null); declare var'
without it (except for namerefs). Is there maybe a use case for the
differences in behavior?

As a side note: I wonder if this functionality, regardless or edge case
handling, would be more useful as an option supplied to `declare' and so
applied explicitly so specific variables, rather than a global shell option.

reply via email to

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