Re: [RFC] shell: local x=$1 may need to quote the RHS
- From
- Konstantin Khomoutov <kostix@bswap.ru>
- Date
- Jan 25, 2022, 09:24 UTC
- Message-ID
- <20220125092419.cgtfw32nk2niazfk@carbon>
- In-Reply-To
- <xmqqsftc3nd6.fsf@gitster.g>
On Mon, Jan 24, 2022 at 12:11:33PM -0800, Junio C Hamano wrote:
Show 24 quoted lines
> Even though this message ends with a patch that could be applied to
> your tree, it is not for application at all. It is to demonstrate a
> potential problem in the code in our tree.
>
> While I was playing with the "Linux development environment (beta)"
> on one of my Chromebooks, I say its default /bin/sh (which is Dash
> 0.5.10) mishandled this construct:
>
> func () {
> local x=$1
> clobber x and nothing else and feel safe
> message="I expect this to be visible by the caller"
> }
>
> func "a message"
> use "$message"
>
> It assigned 'a' to $x in the function, DECLARED the varilable
> $message as local to the function, hence the caller after func
> returned did not see what I intended to see in $message.
>
> The breakage is subtle; unless you have a character in $1 that would
> not make a valid variable name, you won't get any error message yet
> the program would behave in an unexpected way.Sorry, I might have not followed the entire thread, but assignment in `local` is a bashism, and dash can only handle the declaration part with `local`, not assignment; hence the safe code should read
local x x="$1"
To cite the dash manual page:
| Variables may be declared to be local to a function by using a local | command. This should appear as the first statement of a function, and the | syntax is | | local [variable | -] ... | | Local is implemented as a builtin command. | | When a variable is made local, it inherits the initial value and exported | and readonly flags from the variable with the same name in the surrounding | scope, if there is one. Otherwise, the vari‐ able is initially unset. The | shell uses dynamic scoping, so that if you make the variable x lo‐ cal to | function f, which then calls function g, references to the variable x made | inside g will refer to the variable x declared inside f, not to the global | variable named x. | | The only special parameter that can be made local is “-”. Making “-” local | any shell options that are changed via the set command inside the function | to be restored to their original values | when the function returns.