]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
minor test suite updates; fix for export string when a variable from a function tempo...
authorChet Ramey <chet.ramey@case.edu>
Tue, 11 Nov 2025 16:36:53 +0000 (11:36 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 11 Nov 2025 16:36:53 +0000 (11:36 -0500)
22 files changed:
CWRU/CWRU.chlog
MANIFEST
builtins/read.def
doc/bash.1
jobs.c
lib/sh/strtrans.c
sig.c
subst.c
tests/README
tests/RUN-ONE-TEST
tests/RUN-TEST-SCRIPT
tests/comsub2.right
tests/comsub2.tests
tests/comsub27.sub [new file with mode: 0644]
tests/errors.right
tests/errors.tests
tests/intl.right
tests/parser.right
tests/posix2syntax.sub
tests/run-all
tests/unicode1.sub
variables.c

index 831cf1c935d8ee861698de678b11ebf81d277157..e9aa8b9e44558855edf1eb2ff1369956475bf4ce 100644 (file)
@@ -12144,3 +12144,50 @@ variables.c
          attribute to variables from the temporary environment when
          `local -n' is executed (for now), return that variable instead of
          creating a new one
+
+                                  10/27
+                                  -----
+tests/unicode1.sub
+       - report total number of failed tests to avoid script failure if some
+         tests are skipped due to non-installed locales
+
+tests/run-all
+       - use tput for colored output strings if available
+         Patches from G. Branden Robinson <g.branden.robinson@gmail.com>
+
+                                  10/28
+                                  -----
+variables.c
+       - make_local_array_variable,make_local_assoc_variable: call
+         INVALIDATE_EXPORTSTR in case this is a variable from the function
+         environment being converted into a local array/assoc variable
+         Report from Grisha Levit <grishalevit@gmail.com>
+
+                                  11/5
+                                  ----
+sig.c
+       - throw_to_top_level: if we get a SIGINT (interrupt_state != 0) in an
+         interactive shell (interactive != 0), call fpurge to throw away
+         any pending output to stdout before undoing any redirections
+         Report from Grisha Levit <grishalevit@gmail.com>
+
+subst.c
+       - skip_to_delim: if we're trying to skip to the close quote in a single-
+         or double-quoted string, decrement the index by 1 before returning
+         it because skip_single_quoted and skip_double_quoted return an
+         index one past the end of the close quote.
+         Report from Grisha Levit <grishalevit@gmail.com>
+
+                                  11/6
+                                  ----
+jobs.c
+       - make_child: only call bgp_delete on a newly-created pid if that
+         process is asynchronous, since that is what will cause it to be
+         put into the bgpids table. This mostly matters for procsubs and
+         asynchronous jobs, but will happen for comsubs in async jobs
+         and coprocs as well.
+         From a report by Kerin Millar <kfm@plushkava.net>
+
+builtins/read.def
+       - read_builtin: POSIX says read must return >1 on a read error, 1
+         is reserved for EOF
index 848c495e5be081c09bed738fadaaafd984424e85..7f965be547496b14769404fdfd152407b3a2108f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1085,6 +1085,7 @@ tests/comsub23.sub        f
 tests/comsub24.sub     f
 tests/comsub25.sub     f
 tests/comsub26.sub     f
+tests/comsub27.sub     f
 tests/comsub-eof.tests f
 tests/comsub-eof0.sub  f
 tests/comsub-eof1.sub  f
index c6ab8b2d0deba48fab32176aa5560f34e4992ba9..88c9be8b7fd84a62326b2118386402d6fa36af2a 100644 (file)
@@ -941,7 +941,7 @@ add_char:
       run_unwind_frame ("read_builtin");
       if (free_ifs)
        free (ifs_chars);
-      return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig);
+      return ((t_errno != EINTR) ? EX_MISCERROR : 128+lastsig);
     }
 
   if (tmsec > 0 || tmusec > 0)
index ab307a865b69119aae12e718785a2257303e389b..b0fa1ef0ac81723ac8a9a285909acecf0c7f6ffa 100644 (file)
@@ -3690,7 +3690,7 @@ or when
 is followed by a character which is not to be
 interpreted as part of its name.
 The \fIparameter\fP is a shell parameter as described above
-\fBPARAMETERS\fP) or an array reference (\fBArrays\fP).
+(\fBPARAMETERS\fP) or an array reference (\fBArrays\fP).
 .PD
 .PP
 If the first character of \fIparameter\fP is an exclamation point (\fB!\fP),
@@ -6939,6 +6939,7 @@ file with a statement of the form
 .PP
 \fBset\fP \fIvariable\-name\fP \fIvalue\fP
 .RE
+.LP
 or using the \fBbind\fP builtin command (see
 .SM
 .B "SHELL BUILTIN COMMANDS"
diff --git a/jobs.c b/jobs.c
index dc59635c35da5181212f2a83bf4a83d9eeae221e..07f8ca7a7625ead72642aeb0aaaf1016144e4a3a 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -2482,9 +2482,11 @@ make_child (char *command, int flags)
         been reused. */
       delete_old_job (pid);
 
-      /* Perform the check for pid reuse unconditionally.  Some systems reuse
-        PIDs before giving a process CHILD_MAX/_SC_CHILD_MAX unique ones. */
-      bgp_delete (pid);                /* new process, discard any saved status */
+      /* Perform the check for background pid reuse unconditionally.
+        Some systems reuse PIDs before giving a process
+        CHILD_MAX/_SC_CHILD_MAX unique ones. */
+      if (async_p)
+       bgp_delete (pid);       /* new background process, discard any saved status */
 
       last_made_pid = pid;
 
index 37addeb8cc32bc74fcb01c8edd92452b357a7062..e3d67b6a3d28e2f28a0bbcc886afe930a5fca3bd 100644 (file)
@@ -55,7 +55,7 @@ ansicstr (const char *string, size_t len, int flags, int *sawc, size_t *rlen)
   const char *s;
   unsigned long v;
   size_t clen;
-  int mb_cur_max;
+  size_t mb_cur_max;
 #if defined (HANDLE_MULTIBYTE)
   wchar_t wc;
 #endif
@@ -82,7 +82,7 @@ ansicstr (const char *string, size_t len, int flags, int *sawc, size_t *rlen)
          /* We read an entire multibyte character at a time if we are in a
             locale where a backslash can possibly appear as part of a
             multibyte character. UTF-8 encodings prohibit this. */
-         if (locale_utf8locale == 0 && mb_cur_max > 0 && is_basic (c) == 0)
+         if (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0)
            {
              clen = mbrtowc (&wc, s - 1, mb_cur_max, 0);
              if (MB_NULLWCH (clen))
diff --git a/sig.c b/sig.c
index 6de132597ce81c5f06615d253805d096a96cb6a8..0662a2497fbbfb636183dd3dc533271dbbd7d695 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -462,6 +462,10 @@ throw_to_top_level (void)
   unlink_fifo_list ();
 #endif /* PROCESS_SUBSTITUTION */
 
+  /* We don't want any more output after a SIGINT. */
+  if (interactive && print_newline)
+    fpurge (stdout);
+
   run_unwind_protects ();
   loop_level = continuing = breaking = funcnest = 0;
   interrupt_execution = retain_fifos = executing_funsub = 0;
diff --git a/subst.c b/subst.c
index 0e804b763abb761bdb2b93a27356cd5825b45513..34754189f71395855485aaf0581c0bdc3ae28856 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -2226,6 +2226,13 @@ skip_to_delim (const char *string, int start, const char *delims, int flags)
        i = skip_single_quoted (string, slen, start, 0);
       else
        i = skip_double_quoted (string, slen, start, completeflag);
+
+      /* skip_single_quoted and skip_double_quoted leave point one character
+        past the end of the quoted string. That doesn't match the semantics
+        we want here, so we back to the quote char and return that index. */
+      if (i > 0)
+       i--;
+
       CQ_RETURN (i);
     }
 
index b023ef60e40023dfc1d946bedded1dcbd43d10c6..c00af3b4e8d8e7797bedb7483b96415a1dc606f1 100644 (file)
@@ -1,3 +1,3 @@
-Type `sh run-all'.
+Run `make tests' from the bash build directory.
 
 Read COPYRIGHT for copyright information.
index 4401d768482dda159c7da76fecb39c6cf29b8c99..f3a23b8f8e88afd74c77ff33c2bab39be54449c0 100755 (executable)
@@ -10,14 +10,18 @@ export TMPDIR
 export BASH_TSTOUT=/tmp/xx
 rm -f ${BASH_TSTOUT}
 
-# keep track of passed and failed tests and report them
 if [ -t 1 ]; then
-        # can't rely on having $'...' or printf understanding \e
-        # bright red background, white foreground text
-        export CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       if type -P tput >/dev/null; then
+               CSTART=$(tput setaf 15 setab 1) CEND=$(tput sgr0)
+       else
+               # can't rely on having $'...' or printf understanding \e
+               # bright red background, white foreground text
+               CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       fi
 else
-        export CSTART= CEND=
+       CSTART= CEND=
 fi
+export CSTART CEND
 export TAB='   '
 
 ${THIS_SH} "$@"
index 5d962abd5d44458bbe2dd8a3e50fb16c09a1c758..fec43b2de9bef774555dcc3a6e6b1c2a7b4f1c8a 100755 (executable)
@@ -11,12 +11,17 @@ export BASH_TSTOUT=/tmp/xx
 rm -f ${BASH_TSTOUT}
 
 if [ -t 1 ]; then
-        # can't rely on having $'...' or printf understanding \e
-        # bright red background, white foreground text
-        export CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       if type -P tput >/dev/null; then
+               CSTART=$(tput setaf 15 setab 1) CEND=$(tput sgr0)
+       else
+               # can't rely on having $'...' or printf understanding \e
+               # bright red background, white foreground text
+               CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       fi
 else
-        export CSTART= CEND=
+       CSTART= CEND=
 fi
+export CSTART CEND
 export TAB='   '
 
 ${THIS_SH} "$@"
index 2352303aa1dba1b3f633276a2a67117f97810890..6e21c5ca852ccbd16ad1a5e1899fd1c722dc5067 100644 (file)
@@ -201,3 +201,26 @@ after: var = inside
 after: 42 var = inside
 var=inside 42
 after: 0 var = inside
+       comsub27.sub
+declare -- x="0"
+declare -- x="a[]"
+declare -- x="a[]"
+declare -- x=""
+declare -- x=""
+a[${ unset x;}]
+declare -i x
+declare -- x=""
+./comsub27.sub: line 36: ${ unset x;}: arithmetic syntax error: operand expected (error token is "${ unset x;}")
+declare -i x
+declare -- SECONDS=""
+declare -i SECONDS="0"
+declare -- x="0"
+declare -a x=([2]="a[]")
+declare -ai a=()
+./comsub27.sub: line 61: b[]: bad array subscript
+./comsub27.sub: line 61: b[]: bad array subscript
+declare -ai a=([0]="1" [1]="0" [2]="3")
+declare -Ai a=([0]="" )
+./comsub27.sub: line 71: b[]: bad array subscript
+./comsub27.sub: line 71: b[]: bad array subscript
+declare -Ai a=([3]="0" [1]="0" )
index 26d822fd85a4f3e685b950dacc7926c1d3099080..38fb61715e25c3fb0ffae97064882e6483dd48b8 100644 (file)
@@ -152,3 +152,4 @@ test_runsub ./comsub23.sub
 test_runsub ./comsub24.sub
 test_runsub ./comsub25.sub
 test_runsub ./comsub26.sub
+test_runsub ./comsub27.sub
diff --git a/tests/comsub27.sub b/tests/comsub27.sub
new file mode 100644 (file)
index 0000000..eddcb96
--- /dev/null
@@ -0,0 +1,73 @@
+declare -i x
+x='a[${ unset x;}]'
+declare -p x
+unset x
+
+declare -a a
+x=a[${ unset x;}]
+declare -p x
+unset x
+
+x=a[${ unset x;}]
+declare -p x
+unset x
+
+x=${ unset x; }
+declare -p x
+unset x
+
+declare -a x
+x[0]=abc
+x=${ unset x; }
+declare -p x
+unset x
+
+declare -i x
+x='a[${ unset x;}]' printenv x
+declare -p x
+unset x
+
+declare -i x
+x=${ unset x;}
+declare -p x
+unset x
+
+declare -i x
+x='${ unset x;}'
+declare -p x
+unset x
+
+( SECONDS=${ unset SECONDS; }
+declare -p SECONDS
+unset SECONDS )
+
+( SECONDS='${ unset SECONDS; }'
+declare -p SECONDS )
+
+declare -i x='a[${ unset x; }]'
+declare -p x
+unset x
+
+declare -ia x=(3 5 7 9)
+declare -n foo='x[2]'
+foo=a[${ unset x; }]
+declare -p x
+unset x
+
+declare -ai a=(1 'b[${ unset a; }]' 3)
+declare -p a
+unset a
+
+declare -ai a=(1 "b[${ unset a; }]" 3)
+declare -p a
+unset a
+
+# uses kvpair-style
+declare -Ai a=(1 'b[${ unset a; }]' 3)
+declare -p a
+unset a
+
+# uses kvpair-style
+declare -Ai a=(1 "b[${ unset a; }]" 3)
+declare -p a
+unset a
index ac56c508e2a459557ebaca786931ff8840c75e86..e7fd363ce564cbc2938d45cd8a56924bf3a58fe7 100644 (file)
@@ -100,45 +100,47 @@ read: usage: read [-Eers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars
 ./errors.tests: line 265: VAR: readonly variable
 ./errors.tests: line 268: read: XX: invalid file descriptor specification
 ./errors.tests: line 269: read: 42: invalid file descriptor: Bad file descriptor
-./errors.tests: line 272: mapfile: XX: invalid file descriptor specification
-./errors.tests: line 273: mapfile: 42: invalid file descriptor: Bad file descriptor
-./errors.tests: line 277: mapfile: empty array variable name
-./errors.tests: line 278: mapfile: `invalid-var': not a valid identifier
-./errors.tests: line 281: readonly: -x: invalid option
+./errors.tests: line 270: read: 0: read error: Bad file descriptor
+2
+./errors.tests: line 273: mapfile: XX: invalid file descriptor specification
+./errors.tests: line 274: mapfile: 42: invalid file descriptor: Bad file descriptor
+./errors.tests: line 278: mapfile: empty array variable name
+./errors.tests: line 279: mapfile: `invalid-var': not a valid identifier
+./errors.tests: line 282: readonly: -x: invalid option
 readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p
-./errors.tests: line 284: eval: -i: invalid option
+./errors.tests: line 285: eval: -i: invalid option
 eval: usage: eval [arg ...]
-./errors.tests: line 285: command: -i: invalid option
+./errors.tests: line 286: command: -i: invalid option
 command: usage: command [-pVv] command [arg ...]
-./errors.tests: line 288: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
 ./errors.tests: line 289: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: line 292: trap: NOSIG: invalid signal specification
-./errors.tests: line 295: trap: -s: invalid option
+./errors.tests: line 290: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
+./errors.tests: line 293: trap: NOSIG: invalid signal specification
+./errors.tests: line 296: trap: -s: invalid option
 trap: usage: trap [-Plp] [[action] signal_spec ...]
-./errors.tests: line 301: return: can only `return' from a function or sourced script
-./errors.tests: line 305: break: 0: loop count out of range
-./errors.tests: line 309: continue: 0: loop count out of range
-./errors.tests: line 314: builtin: -x: invalid option
+./errors.tests: line 302: return: can only `return' from a function or sourced script
+./errors.tests: line 306: break: 0: loop count out of range
+./errors.tests: line 310: continue: 0: loop count out of range
+./errors.tests: line 315: builtin: -x: invalid option
 builtin: usage: builtin [shell-builtin [arg ...]]
-./errors.tests: line 317: builtin: bash: not a shell builtin
-./errors.tests: line 321: bg: no job control
-./errors.tests: line 322: fg: no job control
+./errors.tests: line 318: builtin: bash: not a shell builtin
+./errors.tests: line 322: bg: no job control
+./errors.tests: line 323: fg: no job control
 kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
-./errors.tests: line 326: kill: -s: option requires an argument
-./errors.tests: line 328: kill: S: invalid signal specification
-./errors.tests: line 330: kill: `': not a pid or valid job spec
+./errors.tests: line 327: kill: -s: option requires an argument
+./errors.tests: line 329: kill: S: invalid signal specification
+./errors.tests: line 331: kill: `': not a pid or valid job spec
 kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
-./errors.tests: line 334: kill: SIGBAD: invalid signal specification
-./errors.tests: line 336: kill: BAD: invalid signal specification
-./errors.tests: line 338: kill: `@12': not a pid or valid job spec
-./errors.tests: line 341: unset: BASH_LINENO: cannot unset
-./errors.tests: line 341: unset: BASH_SOURCE: cannot unset
-./errors.tests: line 344: set: trackall: invalid option name
-./errors.tests: line 345: set: -q: invalid option
+./errors.tests: line 335: kill: SIGBAD: invalid signal specification
+./errors.tests: line 337: kill: BAD: invalid signal specification
+./errors.tests: line 339: kill: `@12': not a pid or valid job spec
+./errors.tests: line 342: unset: BASH_LINENO: cannot unset
+./errors.tests: line 342: unset: BASH_SOURCE: cannot unset
+./errors.tests: line 345: set: trackall: invalid option name
+./errors.tests: line 346: set: -q: invalid option
 set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
-./errors.tests: line 346: set: -i: invalid option
+./errors.tests: line 347: set: -i: invalid option
 set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
-./errors.tests: line 350: xx: readonly variable
+./errors.tests: line 351: xx: readonly variable
 1
        errors1.sub
 ./errors1.sub: line 14: .: -i: invalid option
index 45d6994e160588419110aea1bb94df87106d9f11..822feb0d2ae6f226c73b696576dcb11d1a025ca6 100644 (file)
@@ -267,6 +267,7 @@ read VAR < /dev/null
 # invalid file descriptor
 read -u XX < /dev/null
 read -u 42 < /dev/null
+read var <&- ; echo $?
 
 # same with mapfile
 mapfile -u XX A < /dev/null
index 4943cb31036938cc1354e54896e862555e10103b..4d927d6680e8c97a0273dea077faf256e84dc2fc 100644 (file)
@@ -25,7 +25,7 @@ bytematch
 0000000 254 012
 0000002
        unicode1.sub
-Passed all 1770 Unicode tests
+Failed 0 Unicode tests
        unicode2.sub
 0000000 303 277 012
 0000003
index 673c55ce34968c0f24bde403abc859487f3701a3..16a394593c33bb20e3d2aa40d444dfde73101090 100644 (file)
@@ -20,3 +20,5 @@ ok 1
 x
 x
 x
+./posix2syntax.sub: line 103: syntax error near unexpected token `!'
+./posix2syntax.sub: line 103: `( : | ! : | false )'
index e2c2368f04a5700d037a5e5eaeb93e39d31cb3a9..a97371a0bbdae5d574bf8c06e270fb7111472f3f 100644 (file)
@@ -99,3 +99,5 @@ echo $x
 done
 esac
 
+# some shells accept this, but posix does not allow it
+( : | ! : | false )
index 206e69286288c1a1ab24edab0b2691433c7d801a..cf795478391298fb52ad42f3bcb15d307e205482 100644 (file)
@@ -62,9 +62,13 @@ echo Any output from any test, unless otherwise noted, indicates a possible anom
 
 # keep track of passed and failed tests and report them
 if [ -t 1 ]; then
-       # can't rely on having $'...' or printf understanding \e
-       # bright red background, white foreground text
-       CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       if type -P tput >/dev/null; then
+               CSTART=$(tput setaf 15 setab 1) CEND=$(tput sgr0)
+       else
+               # can't rely on having $'...' or printf understanding \e
+               # bright red background, white foreground text
+               CSTART=$(printf '\033[01;101;37m') CEND=$(printf '\033[0m')
+       fi
 else
        CSTART= CEND=
 fi
index feb79d01574a9dea3eecf754f74fa8d2fc4a15ca..91b01040468b2361006ad5654764b97933c5c404 100644 (file)
@@ -105,7 +105,6 @@ if [ -n "$FR_LOCALE" ]; then
        TestCodePage ${FR_LOCALE} fr_FR_ISO_8859_1
 else
        localewarn fr_FR.ISO8859-1
-
 fi
 
 zh_TW_BIG5=(
@@ -604,8 +603,9 @@ C_UTF_8=(
  )
 TestCodePage en_US.UTF-8 C_UTF_8
 
+echo "Failed ${ErrorCnt} Unicode tests"
 if [ ${ErrorCnt} -gt 0 ]; then
-  echo "Failed ${ErrorCnt} of ${TestCnt} Unicode tests"
-else
-  echo "Passed all ${TestCnt} Unicode tests"
+  echo "Passed $(( ${TestCnt} - ${ErrorCnt} )) of ${TestCnt} Unicode tests"
 fi
+
+exit ${ErrorCnt}
index 2d23a0f230a5c3b088c33ff41334ae2c23654eab..5942337277ae8fac987aa2c4c84853df6822c3f0 100644 (file)
@@ -2849,6 +2849,8 @@ make_local_array_variable (const char *name, int flags)
       var_setarray (var, array);
     }
 
+  INVALIDATE_EXPORTSTR (var);
+
 /*itrace("make_local_array_variable: unsetting att_tempvar");*/
   VUNSETATTR (var, att_tempvar);
 
@@ -2912,6 +2914,8 @@ make_local_assoc_variable (const char *name, int flags)
       var_setassoc (var, hash);
     }
 
+  INVALIDATE_EXPORTSTR (var);
+
 /*itrace("make_local_assoc_variable: unsetting att_tempvar");*/
   VUNSETATTR (var, att_tempvar);