dash variable expansion error using local, readonly, and export

Bug #139097 reported by Ian! D. Allen on 2007-09-12
18
This bug affects 3 people
Affects Status Importance Assigned to Milestone
dash (Ubuntu)
Low
Unassigned

Bug Description

<pre>
Binary package hint: dash

[Edited May 2010]
True for all dash up to at least May 2010.

Bug in variable expansion (incorrect word-splitting) using an assignment
with "local", "readonly", or "export in dash:

$ x='1 2 3'
$ y=$x # this works fine
$ echo "$y"
1 2 3

$ local y=$x # this fails due to dash bug
local: 2: bad variable name
$ echo "$y"
1

$ readonly y=$x # this fails due to dash bug
readonly: 2: bad variable name

$ export y=$x # this fails due to dash bug
export: 2: bad variable name

The same use of assignment using "local", "readonly" and "export" all work
fine in bash:

bash-3.2$ x='1 2 3'
bash-3.2$ y=$x
bash-3.2$ echo "$y"
1 2 3
bash-3.2$ local y=$x
bash: local: can only be used in a function
bash-3.2$ foo () {
> local y=$x
> echo "$y"
> }
bash-3.2$ foo
1 2 3

bash-3.2$ readonly y=$x # works fine

bash-3.2$ export y=$x # works fine

Ian! D. Allen (idallen) on 2007-09-12
description: updated
description: updated
Ian! D. Allen (idallen) wrote :

Hey! The bugs.launchpad.net bug display web page compresses whitespace.
Don't do that. I put the whitespace there to make it more readable.

Bugs should be displayed in fixed-width font with all whitespace preserved.

Matthias Klose (doko) on 2008-02-06
Changed in dash:
importance: Undecided → Low
status: New → Confirmed
Paul Smith (psmith-gnu) wrote :

This is not a bug. "local" is a bash-specific feature which is not defined in the POSIX standard for sh (the POSIX shell).

If you want to run scripts that require bash-specific features, then you should change them to use #!/bin/bash at the top; by using #!/bin/sh you are agreeing that your shell script uses POSIX-compliant features only and will run with a POSIX standard shell.

Cheers!

Ian! D. Allen (idallen) wrote :

An undefined feature would behave like this:

dash$ nosuch y=$x
dash: nosuch: not found

not like this:

dash$ local y=$x
local: 2: bad variable name

The dash shell is attempting to implement "local", and it's broken.
If "local" isn't part of POSIX, and dash is supposed to be POSIX, then
removing "local" completely from dash would be fine. Implementing "local"
incorrectly is not fine. Non-POSIX words should generate "command not
found", not a shell parsing error.

Paul Smith (psmith-gnu) wrote :

You're right; my mistake.

My recommendation is to remove support for "local". Not only does it not work properly, as shown by this bug, but it can cause valid POSIX shell scripts to not behave correctly (for example, if I have a program "local" on my PATH it is ignored by dash--"local" is not a reserved word in POSIX so this should not fail).

See bug #217981

Ian! D. Allen (idallen) wrote :

Still broken in Ubuntu 9.10

dash 0.5.5.1-2ubunt POSIX-compliant shell

$ x='1 2 3'
$ local y=$x
local: 2: 2: bad variable name

Jilles Tjoelker (jilles) wrote :

"local" will not be removed from dash, as it is used too much, even though it is not in POSIX.

The underlying problem is related to a feature in bash which also applies to some POSIX special builtins (export and readonly). This feature is not in POSIX and strictly speaking conflicts with it.

Dash expands your local y=$x to local y=1 2 3, so three parameters for local. It fails because "2" is not a valid variable name. Bash does not perform field splitting and pathname generation on words that look like assignments, if given as argument to certain builtins such as export, readonly and local, so that the command does what you want. You can write local y="$x" to do this in a portable manner. Alternatively, first make the variable local, and then assign the value.

Ian! D. Allen (idallen) wrote :

<pre>
@jilles - I see now that DASH and BASH differ on all assignments preceded
by keywords "local", "export", and "readonly". Both the DASH behaviour
and the BASH behaviour cannot be correct. I think you're trying to
tell me that DASH is working correctly and BASH is broken? I find the
behaviour of BASH more useful and more intuitive, given that it mimics
the non-splitting behaviour of simple variable=$var variable assignments.

So I expand my original bug report to say that all three of the keyword
cases below are broken:

$ x='1 2 3'
$ y=$x # this is how it should work for all three cases below

$ local y=$x
local: 2: 2: bad variable name # should be fixed

$ readonly y=$x
readonly: 3: 2: bad variable name # should be fixed

$ export y=$x
export: 4: 2: bad variable name # should be fixed

My assertion is still that the above DASH behaviour is broken, for all
three uses "local", "export", and "readonly". BASH is correct, and DASH
should be fixed.

summary: - dash 0.5.3-5ubuntu2 variable expansion error using local
+ dash variable expansion error using local, readonly, and export
Ian! D. Allen (idallen) on 2010-05-15
description: updated
John Hupp (john.hupp) wrote :

A comment about Importance: Low.

It seems that this old bug is responsible for breaking the boot process of clients on Linux Terminal Servers (LTSP) running Lubuntu 14.04. See http://bugs.launchpad.net/ubuntu/+source/ltsp/+bug/1330252

Jens Getreu (getreu) wrote :

As dash is used to replace bash for non-interactive shells, dash should reproduce the bash syntax of the `local` keyword as best as it can.

I agree with Dan's comment #7 "the above DASH behaviour is broken, for all three uses "local", "export", and "readonly". BASH is correct, and DASH should be fixed."

The "local" keyword should not change anything to the required syntax of the assignment, e.g.
if `y=$x` works, `local y=$x` must work also!

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers