]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
check for delimiter_depth being 0 before popping off the stack (reset_parser resets...
authorChet Ramey <chet.ramey@case.edu>
Wed, 30 Apr 2025 20:19:08 +0000 (16:19 -0400)
committerChet Ramey <chet.ramey@case.edu>
Wed, 30 Apr 2025 20:19:08 +0000 (16:19 -0400)
CWRU/CWRU.chlog
parse.y
tests/read.right
tests/read1.sub

index 2f3f1e134cdbc4e9048475371490ff81e3e03376..a96c3dc462cbcd342588cc0ad760589b5cecd397 100644 (file)
@@ -11151,3 +11151,38 @@ builtins/read.def
          only push the delimiter back if we read that character ourselves
          (i > 1).
          Report from Greg Wooledge <greg@wooledge.org>
+
+                                  4/23
+                                  ----
+parse.y
+       - pop_delimiter: only decrement delimiter_depth if it's > 0, since
+         reset_parser() may have set it to 0 after the matching call to
+         push_delimiter
+         Report from Grisha Levit <grishalevit@gmail.com> based on a report
+         from Александр Ушаков <aushakov@astralinux.ru>
+
+                                  4/25
+                                  ----
+parse.y
+       - read_a_line: if the shell is interactive, and not reading from a
+         string, check whether a previous call to shell_getc has set
+         EOF_Reached and return EOF in this case, after resetting the
+         current token to '\n'. This makes EOFs that are not the first
+         character on the line `sticky' instead of just token delimiters.
+         From https://savannah.gnu.org/bugs/?67045
+       - history_delimiting_chars: if it looks like we just finished a
+         subshell, and the line we're adding begins with an operator that
+         can't follow a semicolon, return a newline
+         From https://savannah.gnu.org/patch/?10517
+
+                                  4/28
+                                  ----
+parse.y
+       - parse_arith_command: if the character after the first right paren
+         isn't a right paren, making the construct a nested subshell, push
+         that character back and return the subshell command as the current
+         token string, which we push onto the pushed string list. Reading
+         one character more can cause synchronization problems with backslash
+         newline, among other things.
+         From https://savannah.gnu.org/patch/?10517
+
diff --git a/parse.y b/parse.y
index dd1903190174f75ba113ba810c9d2017c4f20221..4e64464af77a6023c8bbd196a286b88a161f3874 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2214,7 +2214,15 @@ read_a_line (int remove_quoted_newline)
       QUIT;
 
       /* If we're reading the here-document from an alias, use shell_getc */
-      c = heredoc_string ? shell_getc (0) : yy_getc ();
+      if (interactive && EOF_Reached && heredoc_string == 0)
+       {
+         c = EOF;
+         EOF_Reached = 0;
+         if (current_token == yacc_EOF)
+           current_token = '\n';               /* reset state */
+       }
+      else
+       c = heredoc_string ? shell_getc (0) : yy_getc ();
 
       /* Ignore null bytes in input. */
       if (c == 0)
@@ -2451,7 +2459,10 @@ static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
     } \
   while (0)
 
-#define pop_delimiter(ds)      ds.delimiter_depth--
+/* The parsing or expansion code may have called reset_parser() between the
+   time push_delimiter was called and this call to pop_delimiter, which resets
+   delimiter_depth to 0, so we check. */
+#define pop_delimiter(ds) do { if (ds.delimiter_depth > 0) ds.delimiter_depth--; } while (0)
 
 /* Return the next shell input character.  This always reads characters
    from shell_input_line; when that line is exhausted, it is time to
@@ -4983,11 +4994,12 @@ parse_arith_cmd (char **ep, int adddq)
     }
   else                         /* nested subshell */
     {
+      shell_ungetc (c);
+
       tokstr[0] = '(';
       strncpy (tokstr + 1, ttok, ttoklen - 1);
       tokstr[ttoklen] = ')';
-      tokstr[ttoklen+1] = c;
-      tokstr[ttoklen+2] = '\0';
+      tokstr[ttoklen+1] = '\0';
     }
 
   *ep = tokstr;
@@ -5990,6 +6002,10 @@ static const int no_semi_successors[] = {
   0
 };
 
+static const int no_semi_predecessors[] = {
+'&', '|', ';', 0
+};
+
 /* If we are not within a delimited expression, try to be smart
    about which separators can be semi-colons and which must be
    newlines.  Returns the string that should be added into the
@@ -5999,6 +6015,7 @@ char *
 history_delimiting_chars (const char *line)
 {
   static int last_was_heredoc = 0;     /* was the last entry the start of a here document? */
+  const char *lp;
   register int i;
 
   if ((parser_state & PST_HEREDOC) == 0)
@@ -6045,6 +6062,9 @@ history_delimiting_chars (const char *line)
   if (parser_state & PST_COMPASSIGN)
     return (" ");
 
+  for (lp = line; *lp && shellblank(*lp); lp++)
+    ;
+
   /* First, handle some special cases. */
   /*(*/
   /* If we just read `()', assume it's a function definition, and don't
@@ -6061,7 +6081,15 @@ history_delimiting_chars (const char *line)
       else if (parser_state & PST_CASESTMT)    /* case statement pattern */
        return " ";
       else
-       return "; ";                            /* (...) subshell */
+       {
+         /* (...) subshell. Make sure this line doesn't start with an
+            operator that cannot be preceded by a semicolon. If it can't
+            (basically the command terminators), return a newline. */
+         for (i = 0; no_semi_predecessors[i]; i++)
+           if (*lp == no_semi_predecessors[i])
+             return "\n";
+         return "; ";
+       }
     }
   else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
     return " ";                /* function def using `function name' without `()' */
index 5c65816313cc32c30f16835beb3f647226d04b6b..277a02b65fecd945d19e535edfb5f1b4b4033ae3 100644 (file)
@@ -52,11 +52,6 @@ a = abc
 <$'spring\375'>
 <summer>
 <automn>
-<winter>
-<$'spring\375'>
-<$'\277summer'>
-<$'\277'>
-<automn>
 timeout 1: ok
 unset or null 1
 timeout 2: ok
index 916e22cff8696eba155c8b1aa4300c8af5a65915..d5fb8b855e510c1b29826013b25dc3ee356121f3 100644 (file)
@@ -44,14 +44,16 @@ printf '%b\0' winter spring 'summer\0200apple\0200banana\0200cherry' automn |
 printf '%b\200' winter 'spring\0375' summer automn |
   while IFS= read -rd $'\200' season; do LC_ALL=C printf "<%q>\n" "$season"; done
 
-: ${TMPDIR:=/tmp}
-INFILE=$TMPDIR/read-in-$$
-printf '%b\243' winter 'spring\0375' '\0277summer' '\0277' automn > $INFILE
-
-LANG=zh_HK.big5hkscs
-while IFS= read -rd $'\243' season; do
-       LC_ALL=C printf "<%q>\n" "$season"
-done < $INFILE
+# this test is encoding-dependent, and varies from system to system
+#: ${TMPDIR:=/tmp}
+#INFILE=$TMPDIR/read-in-$$
+#printf '%b\243' winter 'spring\0375' '\0277summer' '\0277' automn > $INFILE
+#
+#LANG=zh_HK.big5hkscs
+#while IFS= read -rd $'\243' season; do
+#      LC_ALL=C printf "<%q>\n" "$season"
+#done < $INFILE
+#
+#rm -f $INFILE
 
-rm -f $INFILE
 exit 0