From: Chet Ramey Date: Thu, 14 Aug 2025 14:27:52 +0000 (-0400) Subject: fix issue with break in nofork comsub when expanding for command word list; add error... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3160c0b89ce4f3934e791de94f9370b6cfc26ae5;p=thirdparty%2Fbash.git fix issue with break in nofork comsub when expanding for command word list; add error message if the value of a nameref variable expands to an invalid variable name --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 2a546dae..fc2b78c5 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -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 + + 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 diff --git a/builtins/declare.def b/builtins/declare.def index 8f7f4834..30645808 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -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) diff --git a/config.h.in b/config.h.in index 1367eaaa..38578baf 100644 --- a/config.h.in +++ b/config.h.in @@ -294,7 +294,7 @@ #undef HAVE_ALLOCA_H /* Define if major/minor/makedev is defined in */ -#undef MAJOR_IN_MAKEDEV +#undef MAJOR_IN_MKDEV /* Define if major/minor/makedev is defined in */ #undef MAJOR_IN_SYSMACROS diff --git a/execute_cmd.c b/execute_cmd.c index 55e52b3e..94214841 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -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 c98330a5..3be17a85 100644 --- 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; } diff --git a/tests/comsub2.right b/tests/comsub2.right index e9427012..87359788 100644 --- a/tests/comsub2.right +++ b/tests/comsub2.right @@ -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 diff --git a/tests/comsub23.sub b/tests/comsub23.sub index 2edda3bf..5c90d513 100644 --- a/tests/comsub23.sub +++ b/tests/comsub23.sub @@ -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 diff --git a/variables.h b/variables.h index e939e596..f098cce1 100644 --- a/variables.h +++ b/variables.h @@ -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)))