git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Junio C Hamano <gitster@pobox.com>
Date
Jan 24, 2022, 20:11 UTC
Message-ID
<xmqqsftc3nd6.fsf@gitster.g>

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 <gitster@pobox.com>
---
 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.
Next: Konstantin Khomoutov
Message 1 of 9 in “[RFC] shell: local x=$1 may need to quote the RHS”
  1. Junio C HamanoJan 24, 2022
  2. Konstantin KhomoutovJan 25, 2022
  3. Junio C HamanoJan 25, 2022
  4. Taylor BlauJan 25, 2022
  5. Junio C HamanoJan 26, 2022
  6. Konstantin KhomoutovJan 26, 2022
  7. SZEDER GáborJan 26, 2022
  8. Taylor BlauJan 26, 2022
  9. Junio C HamanoJan 27, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.