Subject: [RFC] shell: local x=$1 may need to quote the RHS

From: Junio C Hamano <[email-masked]>
Date: Mon, 24 Jan 2022 12:11:33 -0800

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.

In other words, all of these hits are suspect and may misbehave with
such a shell.

    $ git grep -e '^[	 ]*local.* [a-z0-9_]*=\$' t
    t/lib-parallel-checkout.sh:	local expected_workers=$1 &&
    t/t0000-basic.sh:	local x=$1
    t/t4011-diff-symlink.sh:	local oid=$(printf "%s" "$1" | git hash-object --stdin) &&
    t/t4011-diff-symlink.sh:	local oid=$(git hash-object "$1") &&
    t/t4210-log-i18n.sh:	local engine=$1
    t/t4210-log-i18n.sh:	local pattern=$1
    t/test-lib-functions.sh:	local basename=${1#??}
    t/test-lib-functions.sh:	local var=$1 port
    t/test-lib-functions.sh:	local expr=$(printf '"%s",' "$@")
    t/test-lib-functions.sh:	local expr=$(printf '"%s".*' "$@")

Outside t/, I didn't find anything that may be run with dash and
can be fed problematic input, so as far as I can tell, it is a
problem that only affects the current set of tests.

Signed-off-by: Junio C Hamano <[email-masked]>
---

 t/t0000-basic.sh | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git c/t/t0000-basic.sh w/t/t0000-basic.sh
index b007f0efef..915eb2384f 100755
--- c/t/t0000-basic.sh
+++ w/t/t0000-basic.sh
@@ -45,6 +45,19 @@ test_expect_success 'verify that the running shell supports "local"' '
 	test_cmp expected2 actual2
 '
 
+try_local_unquoted () {
+	local x=$1
+	y="newvalue"
+}
+
+test_expect_success 'verify that "local x=$1" do not quoting' '
+	y=oldvalue &&
+	echo "newvalue" >expect &&
+	try_local_unquoted "x y" &&
+	echo "$y" >actual &&
+	test_cmp expect actual
+'
+
 ################################################################
 # git init has been done in an empty repository.
 # make sure it is empty.