Skip to content

Commit 22e3e02

Browse files
sunshinecogitster
authored andcommitted
chainlint: recognize multi-line quoted strings more robustly
chainlint.sed recognizes multi-line quoted strings within subshells: echo "abc def" >out && so it can avoid incorrectly classifying lines internal to the string as breaking the &&-chain. To identify the first line of a multi-line string, it checks if the line contains a single quote. However, this is fragile and can be easily fooled by a line containing multiple strings: echo "xyz" "abc def" >out && Make detection more robust by checking for an odd number of quotes rather than only a single one. (Escaped quotes are not handled, but support may be added later.) The original multi-line string recognizer rather cavalierly threw away all but the final quote, whereas the new one is careful to retain all quotes, so the "expected" output of a couple existing chainlint tests is updated to account for this new behavior. Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d938711 commit 22e3e02

File tree

4 files changed

+43
-13
lines changed

4 files changed

+43
-13
lines changed

t/chainlint.sed

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ s/.*\n//
151151
:slurp
152152
# incomplete line "...\"
153153
/\\$/bincomplete
154-
# multi-line quoted string "...\n..."
155-
/^[^"]*"[^"]*$/bdqstring
156-
# multi-line quoted string '...\n...' (but not contraction in string "it's so")
157-
/^[^']*'[^']*$/{
154+
# multi-line quoted string "...\n..."?
155+
/"/bdqstring
156+
# multi-line quoted string '...\n...'? (but not contraction in string "it's")
157+
/'/{
158158
/"[^'"]*'[^'"]*"/!bsqstring
159159
}
160160
:folded
@@ -250,20 +250,32 @@ N
250250
s/\\\n//
251251
bslurp
252252

253-
# found multi-line double-quoted string "...\n..." -- slurp until end of string
253+
# check for multi-line double-quoted string "...\n..." -- fold to one line
254254
:dqstring
255-
s/"//g
255+
# remove all quote pairs
256+
s/"\([^"]*\)"/@!\1@!/g
257+
# done if no dangling quote
258+
/"/!bdqdone
259+
# otherwise, slurp next line and try again
256260
N
257261
s/\n//
258-
/"/!bdqstring
262+
bdqstring
263+
:dqdone
264+
s/@!/"/g
259265
bfolded
260266

261-
# found multi-line single-quoted string '...\n...' -- slurp until end of string
267+
# check for multi-line single-quoted string '...\n...' -- fold to one line
262268
:sqstring
263-
s/'//g
269+
# remove all quote pairs
270+
s/'\([^']*\)'/@!\1@!/g
271+
# done if no dangling quote
272+
/'/!bsqdone
273+
# otherwise, slurp next line and try again
264274
N
265275
s/\n//
266-
/'/!bsqstring
276+
bsqstring
277+
:sqdone
278+
s/@!/'/g
267279
bfolded
268280

269281
# found here-doc -- swallow it to avoid false hits within its body (but keep
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
(
2-
?!AMP?! cat && echo multi-line string"
2+
?!AMP?! cat && echo "multi-line string"
33
bap
44
>)

t/chainlint/multi-line-string.expect

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
(
2-
x=line 1 line 2 line 3" &&
3-
?!AMP?! y=line 1 line2'
2+
x="line 1 line 2 line 3" &&
3+
?!AMP?! y='line 1 line2'
44
foobar
55
>) &&
66
(
77
echo "there's nothing to see here" &&
88
exit
9+
>) &&
10+
(
11+
echo "xyz" "abc def ghi" &&
12+
echo 'xyz' 'abc def ghi' &&
13+
echo 'xyz' "abc def ghi" &&
14+
barfoo
915
>)

t/chainlint/multi-line-string.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,16 @@
1212
# LINT: starting multi-line single-quoted string
1313
echo "there's nothing to see here" &&
1414
exit
15+
) &&
16+
(
17+
echo "xyz" "abc
18+
def
19+
ghi" &&
20+
echo 'xyz' 'abc
21+
def
22+
ghi' &&
23+
echo 'xyz' "abc
24+
def
25+
ghi" &&
26+
barfoo
1527
)

0 commit comments

Comments
 (0)