diff mbox series

t1450: fix quoting of NUL byte when corrupting pack

Message ID 20200801220611.10453-1-martin.agren@gmail.com (mailing list archive)
State Accepted
Commit dc156bc31f6a992599cd5c35af27026c39fcbf77
Headers show
Series t1450: fix quoting of NUL byte when corrupting pack | expand

Commit Message

Martin Ågren Aug. 1, 2020, 10:06 p.m. UTC
We use

  printf '\0'

to generate a NUL byte which we then `dd` into the packfile to ensure
that we modify the first byte of the first object, thereby
(probabilistically) invalidating the checksum. Except the single quotes
we're using are interpreted to match with the ones we enclose the whole
test in. So we actually execute

  printf \0

and end up injecting the ASCII code for "0", 0x30, instead.

The comment right above this `printf` invocation says that "at least one
of [the type bits] is not zero, so setting the first byte to 0 is
sufficient". Substituting "0x30" for "0" in that comment won't do: we'd
need to reason about which bits go where and just what the packfile
looks like that we're modifying in this test.

Let's avoid all of that by actually executing

  printf "\0"

to generate a NUL byte, as intended.

Signed-off-by: Martin Ågren <martin.agren@gmail.com>
---
 If my reading is correct, when we substitute 0x30, the type will be 3
 (blob) and the size will be zero. So there might actually exist
 formally valid packfiles where this byte that we're modifying is
 already zero. What matters in the end is whether we might be using such
 a packfile in this exact test and from what I can tell, no, we won't be
 doing that.

 t/t1450-fsck.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Junio C Hamano Aug. 2, 2020, 12:45 a.m. UTC | #1
Martin Ågren <martin.agren@gmail.com> writes:

> We use
>
>   printf '\0'
>
> to generate a NUL byte which we then `dd` into the packfile to ensure
> that we modify the first byte of the first object, thereby
> (probabilistically) invalidating the checksum. Except the single quotes
> we're using are interpreted to match with the ones we enclose the whole
> test in. So we actually execute
>
>   printf \0
>
> and end up injecting the ASCII code for "0", 0x30, instead.
>
> The comment right above this `printf` invocation says that "at least one
> of [the type bits] is not zero, so setting the first byte to 0 is
> sufficient". Substituting "0x30" for "0" in that comment won't do: we'd
> need to reason about which bits go where and just what the packfile
> looks like that we're modifying in this test.
>
> Let's avoid all of that by actually executing
>
>   printf "\0"
>
> to generate a NUL byte, as intended.

Thanks.  Very well explained.

I wonder if it is an easy way to find similar problems without too
much hand-parsing of the test scripts.  Inside a modern test_expect_*
that begins and ends the test body with a single quote, any line
that has a single quote that is not quoted could be suspect, but
that would probably give us too many false positive.


> Signed-off-by: Martin Ågren <martin.agren@gmail.com>
> ---
>  If my reading is correct, when we substitute 0x30, the type will be 3
>  (blob) and the size will be zero. So there might actually exist
>  formally valid packfiles where this byte that we're modifying is
>  already zero. What matters in the end is whether we might be using such
>  a packfile in this exact test and from what I can tell, no, we won't be
>  doing that.
>
>  t/t1450-fsck.sh | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
> index 344a2aad82..af2a2c4682 100755
> --- a/t/t1450-fsck.sh
> +++ b/t/t1450-fsck.sh
> @@ -714,7 +714,7 @@ test_expect_success 'fsck fails on corrupt packfile' '
>  	# at least one of which is not zero, so setting the first byte to 0 is
>  	# sufficient.)
>  	chmod a+w .git/objects/pack/pack-$pack.pack &&
> -	printf '\0' | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
> +	printf "\0" | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
>  
>  	test_when_finished "rm -f .git/objects/pack/pack-$pack.*" &&
>  	remove_object $hsh &&
Chris Torek Aug. 2, 2020, 1 a.m. UTC | #2
On Sat, Aug 1, 2020 at 3:08 PM Martin Ågren <martin.agren@gmail.com> wrote:
>   printf '\0'
>
> to generate a NUL byte
[but]
> end up injecting the ASCII code for "0", 0x30, instead.

> -       printf '\0' | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
> +       printf "\0" | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&

In sh/bash, this should make no difference, and that's what I get here.
Am I missing something?

$ printf '\0' | hexdump
0000000 0000
0000001
$ printf "\0" | hexdump
0000000 0000
0000001

Chris
Chris Torek Aug. 2, 2020, 1:02 a.m. UTC | #3
Oh, wait, I am indeed missing something -- the script itself is
all in single quotes, so the single quotes on the line in question
are wrong.  Never mind!

Chris
Martin Ågren Aug. 2, 2020, 2:30 p.m. UTC | #4
On Sun, 2 Aug 2020 at 02:45, Junio C Hamano <gitster@pobox.com> wrote:
>
> I wonder if it is an easy way to find similar problems without too
> much hand-parsing of the test scripts.  Inside a modern test_expect_*
> that begins and ends the test body with a single quote, any line
> that has a single quote that is not quoted could be suspect, but
> that would probably give us too many false positive.

I did some very crude hand-parsing and identified a few spots that
looked needlessly complicated and where I could change or drop the
quoting so that the code we see is the code we also execute. Patch
below.

Some of those sites made me go "what is actually going on here?" which
would be an argument for simplifying them. Others are more "maybe we
should avoid those quote marks, but the test is obviously correct
anyway".

So I didn't spot any other bugs (like the 0x30/NUL thing in my original
patch), which is good, but also makes me not very motivated to invest in
more advanced parsing.

Martin

-- >8 --
Subject: [PATCH] t: don't spuriously close & open quotes

If we write something like

test_expect_success 'sed a little' '
  sed -e 's/hi/lo/' in >out
'

the human readers do not see what the shell eventually sees:

  sed -e s/hi/lo/ in >out

In this example, this makes no real difference. But this can be confusing
and can make the reader wonder whether we actually rely on that whole
"close the quote, do some stuff, then start quoting again" and what is
actually going on. It could potentially also be a bug in the test.

Change several such single quotes to use double quotes instead or, in a
few cases, drop them altogether. These were identified using some crude
grepping. We're not fixing any test bugs here, but we're hopefully
making these tests slightly easier to grok and to maintain.

(There are legitimate use cases for closing a quote and opening a new
one, e.g., both '\'' and '"'"' can be used to produce a literal single
quote. I'm not touching any of those here.)

In t9401, tuck the redirecting ">" to the filename while we're touching
those lines.

Signed-off-by: Martin Ågren <martin.agren@gmail.com>
---
 t/t1400-update-ref.sh           |  2 +-
 t/t3501-revert-cherry-pick.sh   |  4 ++--
 t/t3507-cherry-pick-conflict.sh |  4 ++--
 t/t4005-diff-rename-2.sh        |  4 ++--
 t/t4034-diff-words.sh           |  2 +-
 t/t4104-apply-boundary.sh       | 24 ++++++++++++------------
 t/t4150-am.sh                   |  8 ++++----
 t/t4200-rerere.sh               |  2 +-
 t/t5302-pack-index.sh           |  2 +-
 t/t5510-fetch.sh                |  4 ++--
 t/t5553-set-upstream.sh         |  6 +++---
 t/t6026-merge-attr.sh           |  4 ++--
 t/t7001-mv.sh                   |  2 +-
 t/t7600-merge.sh                |  6 +++---
 t/t9001-send-email.sh           | 10 +++++-----
 t/t9100-git-svn-basic.sh        |  2 +-
 t/t9401-git-cvsserver-crlf.sh   |  8 ++++----
 t/t9402-git-cvsserver-refs.sh   |  2 +-
 18 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 27171f8261..d0d36750bc 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -324,7 +324,7 @@ test_expect_success "create $m (logged by config)" '
 test_expect_success "update $m (logged by config)" '
 	test_config core.logAllRefUpdates true &&
 	GIT_COMMITTER_DATE="2005-05-26 23:33" \
-	git update-ref HEAD'" $B $A "'-m "Switch" &&
+	git update-ref HEAD $B $A -m "Switch" &&
 	test $B = $(git show-ref -s --verify $m)
 '
 test_expect_success "set $m (logged by config)" '
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 7c1da21df1..3669dfb1be 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -47,7 +47,7 @@ test_expect_success 'cherry-pick --nonsense' '
 	git diff --exit-code HEAD &&
 	test_must_fail git cherry-pick --nonsense 2>msg &&
 	git diff --exit-code HEAD "$pos" &&
-	test_i18ngrep '[Uu]sage:' msg
+	test_i18ngrep "[Uu]sage:" msg
 '
 
 test_expect_success 'revert --nonsense' '
@@ -56,7 +56,7 @@ test_expect_success 'revert --nonsense' '
 	git diff --exit-code HEAD &&
 	test_must_fail git revert --nonsense 2>msg &&
 	git diff --exit-code HEAD "$pos" &&
-	test_i18ngrep '[Uu]sage:' msg
+	test_i18ngrep "[Uu]sage:" msg
 '
 
 test_expect_success 'cherry-pick after renaming branch' '
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 752bc43487..f107622a9e 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -512,7 +512,7 @@ test_expect_success 'commit after failed cherry-pick adds -s at the right place'
 	Signed-off-by: C O Mitter <committer@example.com>
 	# Conflicts:
 	EOF
-	grep -e "^# Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
+	grep -e "^# Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
 	test_cmp expect actual &&
 
 	cat <<-\EOF >expected &&
@@ -541,7 +541,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' '
 	Signed-off-by: C O Mitter <committer@example.com>
 	Conflicts:
 	EOF
-	grep -e "^Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
+	grep -e "^Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
 	test_cmp expect actual
 '
 
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index f542d2929d..d18a80493c 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -14,8 +14,8 @@ test_expect_success 'setup reference tree' '
 	git update-index --add COPYING rezrov &&
 	tree=$(git write-tree) &&
 	echo $tree &&
-	sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
-	sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
+	sed -e "s/HOWEVER/However/" <COPYING >COPYING.1 &&
+	sed -e "s/GPL/G.P.L/g" <COPYING >COPYING.2 &&
 	origoid=$(git hash-object COPYING) &&
 	oid1=$(git hash-object COPYING.1) &&
 	oid2=$(git hash-object COPYING.2)
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index fb145aa173..0c8fb39ced 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -102,7 +102,7 @@ test_expect_success 'word diff with runs of whitespace' '
 '
 
 test_expect_success '--word-diff=porcelain' '
-	sed 's/#.*$//' >expect <<-EOF &&
+	sed "s/#.*$//" >expect <<-EOF &&
 		diff --git a/pre b/post
 		index $pre..$post 100644
 		--- a/pre
diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index 32e3b0ee0b..19f08d9ccd 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -11,7 +11,7 @@ test_description='git apply boundary tests
 L="c d e f g h i j k l m n o p q r s t u v w x"
 
 test_expect_success setup '
-	for i in b '"$L"' y
+	for i in b $L y
 	do
 		echo $i
 	done >victim &&
@@ -19,7 +19,7 @@ test_expect_success setup '
 	git update-index --add victim &&
 
 	# add to the head
-	for i in a b '"$L"' y
+	for i in a b $L y
 	do
 		echo $i
 	done >victim &&
@@ -28,7 +28,7 @@ test_expect_success setup '
 	git diff --unified=0 >add-a-patch.without &&
 
 	# insert at line two
-	for i in b a '"$L"' y
+	for i in b a $L y
 	do
 		echo $i
 	done >victim &&
@@ -37,7 +37,7 @@ test_expect_success setup '
 	git diff --unified=0 >insert-a-patch.without &&
 
 	# modify at the head
-	for i in a '"$L"' y
+	for i in a $L y
 	do
 		echo $i
 	done >victim &&
@@ -46,7 +46,7 @@ test_expect_success setup '
 	git diff --unified=0 >mod-a-patch.without &&
 
 	# remove from the head
-	for i in '"$L"' y
+	for i in $L y
 	do
 		echo $i
 	done >victim &&
@@ -55,7 +55,7 @@ test_expect_success setup '
 	git diff --unified=0 >del-a-patch.without &&
 
 	# add to the tail
-	for i in b '"$L"' y z
+	for i in b $L y z
 	do
 		echo $i
 	done >victim &&
@@ -64,7 +64,7 @@ test_expect_success setup '
 	git diff --unified=0 >add-z-patch.without &&
 
 	# modify at the tail
-	for i in b '"$L"' z
+	for i in b $L z
 	do
 		echo $i
 	done >victim &&
@@ -73,7 +73,7 @@ test_expect_success setup '
 	git diff --unified=0 >mod-z-patch.without &&
 
 	# remove from the tail
-	for i in b '"$L"'
+	for i in b $L
 	do
 		echo $i
 	done >victim &&
@@ -95,8 +95,8 @@ do
 		test_expect_success "apply $kind-patch $with context" '
 			cat original >victim &&
 			git update-index victim &&
-			git apply --index '"$u$kind-patch.$with"' &&
-			test_cmp '"$kind"'-expect victim
+			git apply --index $u$kind-patch.$with &&
+			test_cmp $kind-expect victim
 		'
 	done
 done
@@ -110,8 +110,8 @@ do
 	test_expect_success "apply non-git $kind-patch without context" '
 		cat original >victim &&
 		git update-index victim &&
-		git apply --unidiff-zero --index '"$kind-ng.without"' &&
-		test_cmp '"$kind"'-expect victim
+		git apply --unidiff-zero --index $kind-ng.without &&
+		test_cmp $kind-expect victim
 	'
 done
 
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index bda4586a79..855ed11b32 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -989,7 +989,7 @@ test_expect_success 'am -s unexpected trailer block' '
 	Signed-off-by: J C H <j@c.h>
 	EOF
 	git commit -F msg &&
-	git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" >original &&
 	git format-patch --stdout -1 >patch &&
 
 	git reset --hard HEAD^ &&
@@ -998,7 +998,7 @@ test_expect_success 'am -s unexpected trailer block' '
 		cat original &&
 		echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 	) >expect &&
-	git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
 	test_cmp expect actual &&
 
 	cat >msg <<-\EOF &&
@@ -1009,7 +1009,7 @@ test_expect_success 'am -s unexpected trailer block' '
 	EOF
 	git reset HEAD^ &&
 	git commit -F msg file &&
-	git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" >original &&
 	git format-patch --stdout -1 >patch &&
 
 	git reset --hard HEAD^ &&
@@ -1020,7 +1020,7 @@ test_expect_success 'am -s unexpected trailer block' '
 		echo &&
 		echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 	) >expect &&
-	git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
 	test_cmp expect actual
 '
 
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 831d424c47..f99385c191 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -364,7 +364,7 @@ test_expect_success 'set up an unresolved merge' '
 	git reset --hard &&
 	git checkout version2 &&
 	fifth=$(git rev-parse fifth) &&
-	echo "$fifth		branch 'fifth' of ." |
+	echo "$fifth		branch fifth of ." |
 	git fmt-merge-msg >msg &&
 	ancestor=$(git merge-base version2 fifth) &&
 	test_must_fail git merge-recursive "$ancestor" -- HEAD fifth &&
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 8981c9b90e..d1a6a3c37a 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -15,7 +15,7 @@ test_expect_success 'setup' '
 	i=1 &&
 	while test $i -le 100
 	do
-		iii=$(printf '%03i' $i)
+		iii=$(printf "%03i" $i)
 		test-tool genrandom "bar" 200 > wide_delta_$iii &&
 		test-tool genrandom "baz $iii" 50 >> wide_delta_$iii &&
 		test-tool genrandom "foo"$i 100 > deep_delta_$iii &&
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 7456c567cd..6a6a760f5f 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -213,7 +213,7 @@ test_expect_success 'fetch tags when there is no tags' '
 test_expect_success 'fetch following tags' '
 
 	cd "$D" &&
-	git tag -a -m 'annotated' anno HEAD &&
+	git tag -a -m "annotated" anno HEAD &&
 	git tag light HEAD &&
 
 	mkdir four &&
@@ -331,7 +331,7 @@ test_expect_success 'bundle does not prerequisite objects' '
 test_expect_success 'bundle should be able to create a full history' '
 
 	cd "$D" &&
-	git tag -a -m '1.0' v1.0 master &&
+	git tag -a -m "1.0" v1.0 master &&
 	git bundle create bundle4 v1.0
 
 '
diff --git a/t/t5553-set-upstream.sh b/t/t5553-set-upstream.sh
index 81975ad8f9..7622981cbf 100755
--- a/t/t5553-set-upstream.sh
+++ b/t/t5553-set-upstream.sh
@@ -81,7 +81,7 @@ test_expect_success 'fetch --set-upstream http://nosuchdomain.example.com fails
 
 test_expect_success 'fetch --set-upstream with valid URL sets upstream to URL' '
 	clear_config other other2 &&
-	url="file://'"$PWD"'" &&
+	url="file://$PWD" &&
 	git fetch --set-upstream "$url" &&
 	check_config master "$url" HEAD &&
 	check_config_missing other &&
@@ -158,7 +158,7 @@ test_expect_success 'pull --set-upstream upstream with more than one branch does
 test_expect_success 'pull --set-upstream with valid URL sets upstream to URL' '
 	clear_config master other other2 &&
 	git checkout master &&
-	url="file://'"$PWD"'" &&
+	url="file://$PWD" &&
 	git pull --set-upstream "$url" &&
 	check_config master "$url" HEAD &&
 	check_config_missing other &&
@@ -168,7 +168,7 @@ test_expect_success 'pull --set-upstream with valid URL sets upstream to URL' '
 test_expect_success 'pull --set-upstream with valid URL and branch sets branch' '
 	clear_config master other other2 &&
 	git checkout master &&
-	url="file://'"$PWD"'" &&
+	url="file://$PWD" &&
 	git pull --set-upstream "$url" master &&
 	check_config master "$url" refs/heads/master &&
 	check_config_missing other &&
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index 5900358ce9..76a55f838c 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -122,7 +122,7 @@ test_expect_success 'custom merge backend' '
 	o=$(git unpack-file master^:text) &&
 	a=$(git unpack-file side^:text) &&
 	b=$(git unpack-file master:text) &&
-	sh -c "./custom-merge $o $a $b 0 'text'" &&
+	sh -c "./custom-merge $o $a $b 0 text" &&
 	sed -e 1,3d $a >check-2 &&
 	cmp check-1 check-2 &&
 	rm -f $o $a $b
@@ -149,7 +149,7 @@ test_expect_success 'custom merge backend' '
 	o=$(git unpack-file master^:text) &&
 	a=$(git unpack-file anchor:text) &&
 	b=$(git unpack-file master:text) &&
-	sh -c "./custom-merge $o $a $b 0 'text'" &&
+	sh -c "./custom-merge $o $a $b 0 text" &&
 	sed -e 1,3d $a >check-2 &&
 	cmp check-1 check-2 &&
 	sed -e 1,3d -e 4q $a >check-3 &&
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index c978b6dee4..63d5f41a12 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -177,7 +177,7 @@ test_expect_success "Sergey Vlasov's test case" '
 	date >ab.c &&
 	date >ab/d &&
 	git add ab.c ab &&
-	git commit -m 'initial' &&
+	git commit -m "initial" &&
 	git mv ab a
 '
 
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 1d45f9a4ed..dffcf053db 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -246,7 +246,7 @@ test_expect_success 'merge --squash c3 with c7' '
 	#	file
 	EOF
 	git cat-file commit HEAD >raw &&
-	sed -e '1,/^$/d' raw >actual &&
+	sed -e "1,/^$/d" raw >actual &&
 	test_cmp expect actual
 '
 
@@ -268,7 +268,7 @@ test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
 	#	file
 	EOF
 	git cat-file commit HEAD >raw &&
-	sed -e '1,/^$/d' raw >actual &&
+	sed -e "1,/^$/d" raw >actual &&
 	test_i18ncmp expect actual
 '
 
@@ -292,7 +292,7 @@ test_expect_success 'merge c3 with c7 with --squash commit.cleanup = scissors' '
 	#	file
 	EOF
 	git cat-file commit HEAD >raw &&
-	sed -e '1,/^$/d' raw >actual &&
+	sed -e "1,/^$/d" raw >actual &&
 	test_i18ncmp expect actual
 '
 
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index ec261085ec..3d68570450 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1551,7 +1551,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=quoted-printab
 		--smtp-server="$(pwd)/fake.sendmail" \
 		email-using-8bit \
 		2>errors >out &&
-	sed '1,/^$/d' msgtxt1 >actual &&
+	sed "1,/^$/d" msgtxt1 >actual &&
 	test_cmp expected actual
 '
 
@@ -1568,7 +1568,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
 		--smtp-server="$(pwd)/fake.sendmail" \
 		email-using-8bit \
 		2>errors >out &&
-	sed '1,/^$/d' msgtxt1 >actual &&
+	sed "1,/^$/d" msgtxt1 >actual &&
 	test_cmp expected actual
 '
 
@@ -1594,7 +1594,7 @@ test_expect_success $PREREQ 'convert from quoted-printable to base64' '
 		--smtp-server="$(pwd)/fake.sendmail" \
 		email-using-qp \
 		2>errors >out &&
-	sed '1,/^$/d' msgtxt1 >actual &&
+	sed "1,/^$/d" msgtxt1 >actual &&
 	test_cmp expected actual
 '
 
@@ -1624,7 +1624,7 @@ test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=quoted-printabl
 		--smtp-server="$(pwd)/fake.sendmail" \
 		email-using-crlf \
 		2>errors >out &&
-	sed '1,/^$/d' msgtxt1 >actual &&
+	sed "1,/^$/d" msgtxt1 >actual &&
 	test_cmp expected actual
 '
 
@@ -1641,7 +1641,7 @@ test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=base64' '
 		--smtp-server="$(pwd)/fake.sendmail" \
 		email-using-crlf \
 		2>errors >out &&
-	sed '1,/^$/d' msgtxt1 >actual &&
+	sed "1,/^$/d" msgtxt1 >actual &&
 	test_cmp expected actual
 '
 
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 3055943a22..30172664ac 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -69,7 +69,7 @@ test_expect_success "$name" "
 	mv dir/new_file dir/file &&
 	git update-index --remove dir/file &&
 	git update-index --add dir/file/file &&
-	git commit -m '$name' &&
+	git commit -m "$name" &&
 	test_must_fail git svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch
 "
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
index 84787eee9a..c7a0dd84a4 100755
--- a/t/t9401-git-cvsserver-crlf.sh
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -167,10 +167,10 @@ test_expect_success 'adding files' '
 
 test_expect_success 'updating' '
     git pull gitcvs.git &&
-    echo 'hi' > subdir/newfile.bin &&
-    echo 'junk' > subdir/file.h &&
-    echo 'hi' > subdir/newfile.c &&
-    echo 'hello' >> binfile.bin &&
+    echo "hi" >subdir/newfile.bin &&
+    echo "junk" >subdir/file.h &&
+    echo "hi" >subdir/newfile.c &&
+    echo "hello" >>binfile.bin &&
     git add subdir/newfile.bin subdir/file.h subdir/newfile.c binfile.bin &&
     git commit -q -m "Add and change some files" &&
     git push gitcvs.git >/dev/null &&
diff --git a/t/t9402-git-cvsserver-refs.sh b/t/t9402-git-cvsserver-refs.sh
index cf31ace667..6436c91a3c 100755
--- a/t/t9402-git-cvsserver-refs.sh
+++ b/t/t9402-git-cvsserver-refs.sh
@@ -178,7 +178,7 @@ test_expect_success 'setup v1.2 on b1' '
 	mkdir cdir &&
 	echo "cdir/cfile" >cdir/cfile &&
 	git add -A cdir adir t3 t2 &&
-	git commit -q -m 'v1.2' &&
+	git commit -q -m "v1.2" &&
 	git tag v1.2 &&
 	git push --tags gitcvs.git b1:b1
 '
Martin Ågren Aug. 2, 2020, 2:35 p.m. UTC | #5
On Sun, 2 Aug 2020 at 03:02, Chris Torek <chris.torek@gmail.com> wrote:
>
> Oh, wait, I am indeed missing something -- the script itself is
> all in single quotes, so the single quotes on the line in question
> are wrong.  Never mind!

No worries! Thanks for having a look at the patch. Is there anything
that could be done to make this clearer in the commit message? (I find it
quite awkward to discuss quoting: will the reader understand which
quoting is part of my own formatting of the message vs which is part of
the quoting issue I want to get across!?)

Martin
Chris Torek Aug. 2, 2020, 4:20 p.m. UTC | #6
On Sun, Aug 2, 2020 at 7:35 AM Martin Ågren <martin.agren@gmail.com> wrote:
> No worries! Thanks for having a look at the patch. Is there anything
> that could be done to make this clearer in the commit message? (I find it
> quite awkward to discuss quoting: will the reader understand which
> quoting is part of my own formatting of the message vs which is part of
> the quoting issue I want to get across!?)

This is indeed a problem...

Perhaps something along these lines (generic boilerplate
for any single-quote fixes, that should be adjusted for the
actual fix):

    In the test scripts, the recommended style is, e.g.:

        test_expect_success 'name' '
            multi-line test
            goes here
        '

    When using this style, any single quote in the multi-line
    test section is actually closing the lone single quotes
    that surround it.  To avoid confusion, minimize and/or
    eliminate the use of single quotes here.

Chris
Eric Sunshine Aug. 2, 2020, 5:22 p.m. UTC | #7
On Sun, Aug 2, 2020 at 10:30 AM Martin Ågren <martin.agren@gmail.com> wrote:
> Subject: [PATCH] t: don't spuriously close & open quotes
> [...]
> Signed-off-by: Martin Ågren <martin.agren@gmail.com>
> ---
> diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
> @@ -177,7 +177,7 @@ test_expect_success "Sergey Vlasov's test case" '
>         git add ab.c ab &&
> -       git commit -m 'initial' &&
> +       git commit -m "initial" &&
>         git mv ab a
>  '

This was discovered[1] independently a couple weeks ago; glad to see
it was picked up by your grep'ing, as well.

[1]: https://lore.kernel.org/git/CAPig+cQpUu2UO-+jWn1nTaDykWnxwuEitzVB7PnW2SS_b7V8Hg@mail.gmail.com/
Junio C Hamano Aug. 2, 2020, 5:57 p.m. UTC | #8
Chris Torek <chris.torek@gmail.com> writes:

> On Sun, Aug 2, 2020 at 7:35 AM Martin Ågren <martin.agren@gmail.com> wrote:
>> No worries! Thanks for having a look at the patch. Is there anything
>> that could be done to make this clearer in the commit message? (I find it
>> quite awkward to discuss quoting: will the reader understand which
>> quoting is part of my own formatting of the message vs which is part of
>> the quoting issue I want to get across!?)
>
> This is indeed a problem...
>
> Perhaps something along these lines (generic boilerplate
> for any single-quote fixes, that should be adjusted for the
> actual fix):
>
>     In the test scripts, the recommended style is, e.g.:
>
>         test_expect_success 'name' '
>             multi-line test
>             goes here
>         '
>
>     When using this style, any single quote in the multi-line
>     test section is actually closing the lone single quotes
>     that surround it.  To avoid confusion, minimize and/or
>     eliminate the use of single quotes here.

Another thing that falls into the same class and probably be a good
addition to the above "tip" is how $variables are interpolated, i.e.

	test_expect_success 'test name' '
		test-that-references $variable &&
		another-test-that-references "$variable"
	'

are 99% of the time the right way to refer to variable that is
assigned outside the test itself (e.g. the whole four lines shown
above may be in a loop, "for variable in a b c; ... ;done").

	test_expect_success 'test name' '
		test-that-references '$variable' &&
		another-test-that-references '"$variable"'
	'

is most likely a wrong way to write for the first one (i.e. what if
the value in $variable has $IFS whitespace) and "not wrong per-se
but unnecessary" for the second one.

Same applies to $(command) substitution, but it is more important.
"Step out of the quote, evaluate and step back into the quote"
pattern would mean the command is evaluated while formulating the
body of the test, not while running the test, which often is not
what the author intended.

Thanks.
diff mbox series

Patch

diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 344a2aad82..af2a2c4682 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -714,7 +714,7 @@  test_expect_success 'fsck fails on corrupt packfile' '
 	# at least one of which is not zero, so setting the first byte to 0 is
 	# sufficient.)
 	chmod a+w .git/objects/pack/pack-$pack.pack &&
-	printf '\0' | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
+	printf "\0" | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 &&
 
 	test_when_finished "rm -f .git/objects/pack/pack-$pack.*" &&
 	remove_object $hsh &&