summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sunshine <sunshine@sunshineco.com>2021-12-13 01:30:56 -0500
committerJunio C Hamano <gitster@pobox.com>2021-12-13 14:15:29 -0800
commit22597af97d67660fb3f0dba538a1f02b1ba94243 (patch)
tree6950a948a7fd5ab9aa11dd5297c5b0143d62f555
parent2d53614210919c2a4eac4a03e9d34da7b9e7ff31 (diff)
chainlint.sed: don't mistake `<< word` in string as here-doc operator
Tighten here-doc recognition to prevent it from being fooled by text which looks like a here-doc operator but happens merely to be the content of a string, such as this real-world case from t7201: echo "<<<<<<< ours" && echo ourside && echo "=======" && echo theirside && echo ">>>>>>> theirs" This problem went unnoticed because chainlint.sed is not a real parser, but rather applies heuristics to pretend to understand shell code. In this case, it saw what it thought was a here-doc operator (`<< ours`), and fell off the end of the test looking for the closing tag "ours" which it never found, thus swallowed the remainder of the test without checking it for &&-chain breakage. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--t/chainlint.sed8
-rw-r--r--t/chainlint/not-heredoc.expect14
-rw-r--r--t/chainlint/not-heredoc.test16
3 files changed, 36 insertions, 2 deletions
diff --git a/t/chainlint.sed b/t/chainlint.sed
index b382746526..2f786f890d 100644
--- a/t/chainlint.sed
+++ b/t/chainlint.sed
@@ -89,6 +89,7 @@
# here-doc -- swallow it to avoid false hits within its body (but keep the
# command to which it was attached)
/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/ {
+ /"[^"]*<<[^"]*"/bnotdoc
s/^\(.*\)<<-*[ ]*[\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</
s/[ ]*<<//
:hered
@@ -100,6 +101,7 @@
s/^<[^>]*>//
s/\n.*$//
}
+:notdoc
# one-liner "(...) &&"
/^[ ]*!*[ ]*(..*)[ ]*&&[ ]*$/boneline
@@ -151,8 +153,10 @@ s/.*\n//
/"[^'"]*'[^'"]*"/!bsqstr
}
:folded
-# here-doc -- swallow it
-/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/bheredoc
+# here-doc -- swallow it (but not "<<" in a string)
+/<<-*[ ]*[\\'"]*[A-Za-z0-9_]/{
+ /"[^"]*<<[^"]*"/!bheredoc
+}
# comment or empty line -- discard since final non-comment, non-empty line
# before closing ")", "done", "elsif", "else", or "fi" will need to be
# re-visited to drop "suspect" marking since final line of those constructs
diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect
new file mode 100644
index 0000000000..2e9bb135fe
--- /dev/null
+++ b/t/chainlint/not-heredoc.expect
@@ -0,0 +1,14 @@
+echo "<<<<<<< ours" &&
+echo ourside &&
+echo "=======" &&
+echo theirside &&
+echo ">>>>>>> theirs" &&
+
+(
+ echo "<<<<<<< ours" &&
+ echo ourside &&
+ echo "=======" &&
+ echo theirside &&
+ echo ">>>>>>> theirs" ?!AMP?!
+ poodle
+) >merged
diff --git a/t/chainlint/not-heredoc.test b/t/chainlint/not-heredoc.test
new file mode 100644
index 0000000000..9aa57346cd
--- /dev/null
+++ b/t/chainlint/not-heredoc.test
@@ -0,0 +1,16 @@
+# LINT: "<< ours" inside string is not here-doc
+echo "<<<<<<< ours" &&
+echo ourside &&
+echo "=======" &&
+echo theirside &&
+echo ">>>>>>> theirs" &&
+
+(
+# LINT: "<< ours" inside string is not here-doc
+ echo "<<<<<<< ours" &&
+ echo ourside &&
+ echo "=======" &&
+ echo theirside &&
+ echo ">>>>>>> theirs"
+ poodle
+) >merged