hush: fix handling of empty heredoc EOF marker
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 29 Jul 2017 18:43:26 +0000 (20:43 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 29 Jul 2017 18:43:26 +0000 (20:43 +0200)
function                                             old     new   delta
parse_stream                                        2609    2634     +25

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash_test/ash-heredoc/heredoc_empty2.right [new file with mode: 0644]
shell/ash_test/ash-heredoc/heredoc_empty2.tests [new file with mode: 0755]
shell/hush.c
shell/hush_test/hush-heredoc/heredoc_empty2.right [new file with mode: 0644]
shell/hush_test/hush-heredoc/heredoc_empty2.tests [new file with mode: 0755]

diff --git a/shell/ash_test/ash-heredoc/heredoc_empty2.right b/shell/ash_test/ash-heredoc/heredoc_empty2.right
new file mode 100644 (file)
index 0000000..e32c6ea
--- /dev/null
@@ -0,0 +1,4 @@
+OK1
+Ok:0
+OK2
+Ok:0
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty2.tests b/shell/ash_test/ash-heredoc/heredoc_empty2.tests
new file mode 100755 (executable)
index 0000000..20fc35f
--- /dev/null
@@ -0,0 +1,14 @@
+unset a
+
+# Heredoc with empty delimiter
+cat <<- ""
+       OK1
+
+echo Ok:$?
+
+# Heredoc with empty delimiter
+cat <<- ""
+       OK2
+       
+
+echo Ok:$?
index d0225edb91a6be4853ec15fa3a4788cfcd1c39ca..0fae809b3e06b5b78f8d26e659005a929ca30a3e 100644 (file)
@@ -4001,24 +4001,34 @@ static char *fetch_till_str(o_string *as_string,
                ch = i_getch(input);
                if (ch != EOF)
                        nommu_addchr(as_string, ch);
-               if ((ch == '\n' || ch == EOF)
-                && ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\')
-               ) {
-                       if (strcmp(heredoc.data + past_EOL, word) == 0) {
-                               heredoc.data[past_EOL] = '\0';
-                               debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
-                               return heredoc.data;
-                       }
-                       while (ch == '\n') {
-                               o_addchr(&heredoc, ch);
-                               prev = ch;
+               if (ch == '\n' || ch == EOF) {
+ check_heredoc_end:
+                       if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
+                               if (strcmp(heredoc.data + past_EOL, word) == 0) {
+                                       heredoc.data[past_EOL] = '\0';
+                                       debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
+                                       return heredoc.data;
+                               }
+                               if (ch == '\n') {
+                                       /* This is a new line.
+                                        * Remember position and backslash-escaping status.
+                                        */
+                                       o_addchr(&heredoc, ch);
+                                       prev = ch;
  jump_in:
-                               past_EOL = heredoc.length;
-                               do {
-                                       ch = i_getch(input);
-                                       if (ch != EOF)
-                                               nommu_addchr(as_string, ch);
-                               } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
+                                       past_EOL = heredoc.length;
+                                       /* Get 1st char of next line, possibly skipping leading tabs */
+                                       do {
+                                               ch = i_getch(input);
+                                               if (ch != EOF)
+                                                       nommu_addchr(as_string, ch);
+                                       } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
+                                       /* If this immediately ended the line,
+                                        * go back to end-of-line checks.
+                                        */
+                                       if (ch == '\n')
+                                               goto check_heredoc_end;
+                               }
                        }
                }
                if (ch == EOF) {
diff --git a/shell/hush_test/hush-heredoc/heredoc_empty2.right b/shell/hush_test/hush-heredoc/heredoc_empty2.right
new file mode 100644 (file)
index 0000000..e32c6ea
--- /dev/null
@@ -0,0 +1,4 @@
+OK1
+Ok:0
+OK2
+Ok:0
diff --git a/shell/hush_test/hush-heredoc/heredoc_empty2.tests b/shell/hush_test/hush-heredoc/heredoc_empty2.tests
new file mode 100755 (executable)
index 0000000..20fc35f
--- /dev/null
@@ -0,0 +1,14 @@
+unset a
+
+# Heredoc with empty delimiter
+cat <<- ""
+       OK1
+
+echo Ok:$?
+
+# Heredoc with empty delimiter
+cat <<- ""
+       OK2
+       
+
+echo Ok:$?