]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix issue with break in nofork comsub when expanding for command word list; add error...
authorChet Ramey <chet.ramey@case.edu>
Thu, 14 Aug 2025 14:27:52 +0000 (10:27 -0400)
committerChet Ramey <chet.ramey@case.edu>
Thu, 14 Aug 2025 14:27:52 +0000 (10:27 -0400)
CWRU/CWRU.chlog
builtins/declare.def
config.h.in
execute_cmd.c
subst.c
tests/comsub2.right
tests/comsub23.sub
variables.h

index 2a546dae5442de6fee7b6254bedd42134f747acb..fc2b78c5fe93857be50c658102f2a4598b8660fd 100644 (file)
@@ -11563,3 +11563,26 @@ subst.c
          expand_word_leave_quoted: if call_expand_word_internal returns an
          error, return a NULL WORD_LIST *
          Fixes bug with PS1 expansion reported by smart.outfit080@8shield.net
+
+config.h.in
+       - MAJOR_IN_MKDEV: fix typo
+
+                                   8/8
+                                   ---
+execute_cmd.c
+       - CHECK_BREAK_AND_CONTINUE: macro to encapsulate common code for
+         testing `breaking' and `continuing' while in loops
+       - execute_for_command,execute_arith_for_command,execute_select_command,
+         execute_while_or_until: replace common code with CHECK_BREAK_AND_CONTINUE
+       - execute_for_command,execute_select_command: add call to
+         CHECK_BREAK_AND_CONTINUE after binding variable, in case it contains
+         a nofork comsub that executes break or continue
+         Report from Oğuz <oguzismailuysal@gmail.com>
+
+                                  8/11
+                                  ----
+builtins/declare.def
+       - declare_internal: if the value of an assignment statement expands to
+         an invalid value for a nameref variable, but the original value is
+         valid, add an error message for the assignment error
+         Report from Oğuz <oguzismailuysal@gmail.com>
index 8f7f483439093e68b4c17117c5c5ce5ec7aebc4b..306458080810b6ac6636e68297ba1ae4110af040 100644 (file)
@@ -1032,6 +1032,9 @@ restart_new_var_name:
            {
              if (valid_nameref_value (value, 1) == 0)
                sh_invalidid (value);
+             /* what else can cause this to fail? */
+             else if (flags_on & att_integer)
+               builtin_error ("%s: expands to invalid variable name for name reference", value);
              assign_error++;
              /* XXX - unset this variable? or leave it as normal var? */
              if (created_var)
index 1367eaaa799f5d3c4e14562357a7b06efc69950c..38578baf664a2d4b1b4a3ac5d2b7f8f804a25302 100644 (file)
 #undef HAVE_ALLOCA_H
 
 /* Define if major/minor/makedev is defined in <sys/mkdev.h> */
-#undef MAJOR_IN_MAKEDEV
+#undef MAJOR_IN_MKDEV
 
 /* Define if major/minor/makedev is defined in <sys/sysmacros.h> */
 #undef MAJOR_IN_SYSMACROS
index 55e52b3e8c9769afc8dcea5f96120dfd0064e118..9421484141bcb137c09e54a5bd4fb2387d02dd74 100644 (file)
@@ -320,6 +320,21 @@ do { \
     } \
 } while (0)
 
+/* Common code to check whether `break' or `continue' was executed. */
+#define CHECK_BREAK_AND_CONTINUE() \
+      if (breaking) \
+       { \
+         breaking--; \
+         break; \
+       } \
+      if (continuing) \
+       { \
+         continuing--; \
+         if (continuing) \
+           break; \
+       } \
+      do { } while (0)
+
 /* A sort of function nesting level counter */
 int funcnest = 0;
 int funcnest_max = 0;
@@ -3079,6 +3094,8 @@ execute_for_command (FOR_COM *for_command)
       else
        v = bind_variable (identifier, list->word->word, 0);
 
+      CHECK_BREAK_AND_CONTINUE();
+
       if (v == 0 || ASSIGN_DISALLOWED (v, 0))
        {
          line_number = save_line_number;
@@ -3105,18 +3122,7 @@ execute_for_command (FOR_COM *for_command)
       REAP ();
       QUIT;
 
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
+      CHECK_BREAK_AND_CONTINUE();
     }
 
   loop_level--; interrupt_execution--; retain_fifos--;
@@ -3249,17 +3255,7 @@ execute_arith_for_command (ARITH_FOR_COM *arith_for_command)
       /* If the step or test expressions execute `break' or `continue' in a
         nofork command substitution or by some other means, break the loop
         here. */
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
+      CHECK_BREAK_AND_CONTINUE();
 
       if (expok == 0)
        break;
@@ -3274,18 +3270,7 @@ execute_arith_for_command (ARITH_FOR_COM *arith_for_command)
       QUIT;
 
       /* Handle any `break' or `continue' commands executed by the body. */
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
+      CHECK_BREAK_AND_CONTINUE();
 
       /* Evaluate the step expression. */
       line_number = arith_lineno;
@@ -3601,23 +3586,14 @@ execute_select_command (SELECT_COM *select_command)
 
       stupidly_hack_special_variables (identifier);
 
+      CHECK_BREAK_AND_CONTINUE();
+
       retval = execute_command (select_command->action);
 
       REAP ();
       QUIT;
 
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
+      CHECK_BREAK_AND_CONTINUE();
 
 #if defined (KSH_COMPATIBLE_SELECT)
       show_menu = 0;
@@ -3837,18 +3813,7 @@ execute_while_or_until (WHILE_COM *while_command, int type)
 
       REAP ();
 
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
+      CHECK_BREAK_AND_CONTINUE();
     }
   loop_level--; interrupt_execution--;
 
diff --git a/subst.c b/subst.c
index c98330a565489140e518986db1bcffe9e05b7421..3be17a85974bf52739653fcb0664ce2473d095be 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -7514,8 +7514,13 @@ array_length_reference (const char *s)
 
   /* If unbound variables should generate an error, report one and return
      failure. */
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+  if ((var == 0 || invisible_p (var)) && unbound_vars_is_error)
+#else
   if ((var == 0 || invisible_p (var) || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
+#endif
     {
+unbound_array_error:
       set_exit_status (EXECUTION_FAILURE);
 #if 1
       /* If the array isn't subscripted with `@' or `*', it's an error. */
@@ -7536,6 +7541,11 @@ array_length_reference (const char *s)
   /* We support a couple of expansions for variables that are not arrays.
      We'll return the length of the value for v[0], and 1 for v[@] or
      v[*].  Return 0 for everything else. */
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+  /* If the variable is set, but not an array or assoc variable, nounset is
+     enabled, and the subscript is not one of @, *, or 0, it is an error
+     treated the same as in previous versions. */
+#endif
 
   array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
   h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
@@ -7546,6 +7556,10 @@ array_length_reference (const char *s)
        return (h ? assoc_num_elements (h) : 0);
       else if (array_p (var))
        return (array ? array_num_elements (array) : 0);
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+      else if (unbound_vars_is_error && var_isset (var) == 0)
+       goto unbound_array_error;       /* still non-fatal error */
+#endif
       else
        return (var_isset (var) ? 1 : 0);
     }
@@ -7585,6 +7599,11 @@ array_length_reference (const char *s)
        }
       if (array_p (var))
        t = array_reference (array, ind);
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+      /* if nounset is enabled, scalar variables may only be indexed with 0 */
+      else if (unbound_vars_is_error && (var_isset (var) == 0 || ind != 0))
+       goto unbound_array_error;       /* still fatal error */
+#endif
       else
        t = (ind == 0) ? value_cell (var) : (char *)NULL;
     }
index e942701237c6586592607f9f608f76a948c4014a..8735978862531eb92134cab230283d692350f3ae 100644 (file)
@@ -99,6 +99,11 @@ funsub
 in here-documents
 after all they work here
 and work here
+after for
+uname
+after arith for
+1) a[${ break;}]
+#? after select
 a b c == 1 2 3
  == 1 2 3
 before return
index 2edda3bfa0751ffb6e1cb8ea9bf879624107f09d..5c90d513a2a028264fec340a4ea7b524ad1f1829 100644 (file)
@@ -77,3 +77,21 @@ exec 4<&-
 
 echo after all they ${word-$(echo work here)}
 echo and ${word-${ echo work here; }}
+
+unset x
+
+set -- 'a[${ break;}]'
+declare -in x
+
+for x do :; done
+echo after for
+
+true; for (( ; $? == 0; ${ ! break;} )); do echo uname; done
+echo after arith for
+
+declare -i z
+select z in 'a[${ break;}]'
+do
+       echo $z
+done <<<1
+echo after select
index e939e596a5bf8f2c0e022929a131e598dd1baf9e..f098cce178bb9b1c1de0a9fbee386bf36785bb9b 100644 (file)
@@ -144,6 +144,11 @@ typedef struct _vlist {
 
 #define attmask_scope  0x0f00000
 
+/* Internal attributes used for variable state management. */
+#define att_assigning  0x1000000
+
+#define attmask_state  0xf000000
+
 #define exported_p(var)                ((((var)->attributes) & (att_exported)))
 #define readonly_p(var)                ((((var)->attributes) & (att_readonly)))
 #define array_p(var)           ((((var)->attributes) & (att_array)))