]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
small change to brace expansion to inhibit some error messages; changes to printf...
authorChet Ramey <chet.ramey@case.edu>
Mon, 23 Oct 2023 13:50:02 +0000 (09:50 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 23 Oct 2023 13:50:02 +0000 (09:50 -0400)
19 files changed:
CWRU/CWRU.chlog
MANIFEST
braces.c
builtins/printf.def
parse.y
tests/array.right
tests/array.tests
tests/braces.right
tests/braces.tests
tests/exp.right
tests/exp1.sub
tests/printf.right
tests/printf.tests
tests/printf6.sub
tests/printf7.sub [new file with mode: 0644]
tests/read.right
tests/read.tests
tests/run-braces
variables.c

index a9f2dfe49a5e5b8c22e1072a2805fa304bba7bf7..686c4c126dd3fbbdf5466380bb66039c3e93e589 100644 (file)
@@ -7864,3 +7864,49 @@ builtins/read.def
        - read_builtin: return EX_MISCERROR (2) if there is an error trying
          to assign to one of the variables. This is what the newest POSIX
          draft specifies.
+
+variables.c
+       - dispose_variable_value: do the right thing for att_nofree vars
+       - makunbound: call dispose_variable_value instead of using inline code
+
+braces.c
+       - brace_gobbler: make sure to set no_longjmp_on_fatal_error around
+         calls to extract_dollar_brace_string
+
+                                  10/17
+                                  -----
+braces.c
+       - brace_gobbler: set SX_NOLONGJMP|SX_NOERROR in the flags passed
+         to extract_command_subst; make sure no_longjmp_on_fatal_error
+         is set before that call
+       - brace_gobbler: revert 10/13 change to use extract_dollar_brace_string
+
+                                  10/20
+                                  -----
+parse.y
+
+       - xparse_dolparen,parse_string_to_command: if SX_NOERROR is set in
+         FLAGS, add PST_NOERROR to parser_state. Not much effect yet.
+       - parse_matched_pair: if PST_NOERROR is set in parser_state, don't
+         print an error message if we hit EOF, just return an error. A start
+         at using PST_NOERROR to suppress error messages, not just duplicate
+         ones. We'll see how this goes before adding more
+
+builtins/printf.def
+       - decodeprec: decode the precision into an intmax_t; clamp the return
+         value at INT_MAX
+       - printf_builtin: update to posix interp 1647 (even though it's about
+         fprintf(3)) and output a NUL byte if %lc is supplied a null argument.
+       - printf_builtin: fix case where %Q is supplied with a precision in
+         the format string
+       - printf_builtin: fix case where %Q is supplied with a precision
+         greater than INT_MAX
+       - getwidestr,getwidechar: handle case where there is no argument
+         supplied; return NULL or NUL
+       - convwidestr: allow a precedence of 0 for %ls
+       - getint: don't call getintmax any more, just use the same code style
+         inline; getintmax will consume an extra argument on an error
+         Report and patches from Grisha Levit <grishalevit@gmail.com>
+       - printf_builtin: handle field width and precision overflow from
+         getint() by ignoring the argument (fieldwidth = 0, precision = -1)
+
index 4c738ccea27045436a72e1757deaeac1bb986eb9..3fb5147af5a18240d194890a3fc31636b6717055 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1405,6 +1405,8 @@ tests/printf2.sub f
 tests/printf3.sub      f
 tests/printf4.sub      f
 tests/printf5.sub      f
+tests/printf6.sub      f
+tests/printf7.sub      f
 tests/procsub.tests    f
 tests/procsub.right    f
 tests/procsub1.sub     f
index 3d096db75d68a8316eab977669cc32b6598e94fc..fbc9b6f19adabb38f5607bf32b2a7bca36fa8e97 100644 (file)
--- a/braces.c
+++ b/braces.c
@@ -619,9 +619,30 @@ brace_gobbler (char *text, size_t tlen, int *indx, int satisfy)
       /* If compiling for the shell, treat ${...} like \{...} */
       if (c == '$' && text[i+1] == '{' && quoted != '\'')              /* } */
        {
+#if 0
+         /* If we want to inhibit brace expansion during parameter expansions,
+            we need to skip over parameter expansions here. This is easier
+            than teaching brace expansion about the idiosyncracies of shell
+            word expansion. */
+         int o, f;
+         o = no_longjmp_on_fatal_error;
+         no_longjmp_on_fatal_error = 1;
+         f = (quoted == '"') ? Q_DOUBLE_QUOTES : 0;
          si = i + 2;
-         t = extract_dollar_brace_string (text, &si, 0, SX_NOALLOC);
+         t = extract_dollar_brace_string (text, &si, f, SX_NOALLOC|SX_NOLONGJMP|SX_COMPLETE|SX_NOERROR);
          i = si + 1;
+         no_longjmp_on_fatal_error = o;
+         if (i > tlen)
+           {
+             i = tlen;
+             break;
+           }
+#else
+         pass_next = 1;
+         i++;
+         if (quoted == 0)
+           level++;
+#endif
          continue;
        }
 #endif
@@ -654,10 +675,24 @@ brace_gobbler (char *text, size_t tlen, int *indx, int satisfy)
       /* Pass new-style command and process substitutions through unchanged. */
       if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(')                      /* ) */
        {
+         int o;
+
 comsub:
+         o = no_longjmp_on_fatal_error;
+         no_longjmp_on_fatal_error = 1;
          si = i + 2;
-         t = extract_command_subst (text, &si, SX_NOALLOC);
+#if 0
+         t = extract_command_subst (text, &si, SX_NOALLOC|SX_NOLONGJMP|SX_NOERROR|SX_COMPLETE);
+#else
+         t = extract_command_subst (text, &si, SX_NOALLOC|SX_NOLONGJMP|SX_NOERROR);
+#endif
          i = si + 1;
+         no_longjmp_on_fatal_error = o;
+         if (i > tlen)
+           {
+             i = tlen;
+             break;
+           }
          continue;
        }
 #endif
index ae6c75c58e9183edc828eaa929f964d36f0b794d..abff9c647855eacf6e773a2958fe13bbb4018e8e 100644 (file)
@@ -252,12 +252,12 @@ static size_t conv_bufsize;
 static inline int
 decodeprec (char *ps)
 {
-  int mpr;
+  intmax_t mpr;
 
   mpr = *ps++ - '0';
   while (DIGIT (*ps))
     mpr = (mpr * 10) + (*ps++ - '0');
-  return mpr;
+  return (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
 }
 
 int
@@ -416,6 +416,9 @@ printf_builtin (WORD_LIST *list)
              fmt++;
              have_fieldwidth = 1;
              fieldwidth = getint ();
+             /* Handle field with overflow by ignoring it. */
+             if (fieldwidth == INT_MAX || fieldwidth == INT_MIN)
+                 fieldwidth = 0;
            }
          else
            while (DIGIT (*fmt))
@@ -430,6 +433,10 @@ printf_builtin (WORD_LIST *list)
                  fmt++;
                  have_precision = 1;
                  precision = getint ();
+                 /* Handle precision overflow by ignoring it. "A negative
+                    precision is treated as if it were missing." */
+                 if (precision == INT_MAX || precision == INT_MIN)
+                   precision = -1;
                }
              else
                {
@@ -490,7 +497,12 @@ printf_builtin (WORD_LIST *list)
                    ws[0] = wc;
                    ws[1] = L'\0';
 
-                   r = printwidestr (start, ws, 1, fieldwidth, precision);
+                   /* If %lc is supplied a null argument, posix interp 1647
+                      says it should produce a single null byte. */
+                   if (wc == L'\0')
+                     r = printstr (start, "", 1, fieldwidth, precision);
+                   else
+                     r = printwidestr (start, ws, 1, fieldwidth, precision);
                    if (r < 0)
                      PRETURN (EXECUTION_FAILURE);
                    break;
@@ -514,7 +526,7 @@ printf_builtin (WORD_LIST *list)
 
                    wp = getwidestr (&slen);
                    r = printwidestr (start, wp, slen, fieldwidth, precision);
-                   free (wp);
+                   FREE (wp);
                    if (r < 0)
                      PRETURN (EXECUTION_FAILURE);
                    break;
@@ -647,20 +659,19 @@ printf_builtin (WORD_LIST *list)
            case 'Q':
              {
                char *p, *xp;
-               int r, mpr;
+               int r;
                size_t slen;
 
                r = 0;
                p = getstr ();
                /* Decode precision and apply it to the unquoted string. */
-               if (convch == 'Q' && precstart)
+               if (convch == 'Q' && (have_precision || precstart))
                  {
-                   mpr = decodeprec (precstart);
-                   /* Error if precision > INT_MAX here? */
-                   precision = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
+                   if (precstart)
+                     precision = decodeprec (precstart);
                    slen = strlen (p);
                    /* printf precision works in bytes. */
-                   if (precision < slen)
+                   if (precision >= 0 && precision < slen)
                      p[precision] = '\0';
                  }
                if (p && *p == 0)       /* XXX - getstr never returns null */
@@ -1336,17 +1347,31 @@ getstr (void)
   return ret;
 }
 
+/* Don't call getintmax here because it may consume an argument on error, and
+   we call this to get field width/precision arguments. */
 static int
 getint (void)
 {
   intmax_t ret;
-
-  ret = getintmax ();
+  char *ep;
 
   if (garglist == 0)
-    return ret;
+    return (0);
+
+  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
+    return asciicode ();
+
+  errno = 0;
+  ret = strtoimax (garglist->word->word, &ep, 0);
 
-  if (ret > INT_MAX)
+  if (*ep)
+    {
+      sh_invalidnum (garglist->word->word);
+      conversion_error = 1;
+    }
+  else if (errno == ERANGE)
+    printf_erange (garglist->word->word);
+  else if (ret > INT_MAX)
     {
       printf_erange (garglist->word->word);
       ret = INT_MAX;
@@ -1357,6 +1382,7 @@ getint (void)
       ret = INT_MIN;
     }
 
+  garglist = garglist->next;
   return ((int)ret);
 }
 
@@ -1519,6 +1545,13 @@ getwidestr (size_t *lenp)
   size_t slen, mblength;
   DECLARE_MBSTATE;
 
+  if (garglist == 0)
+    {
+      if (lenp)
+       *lenp = 0;
+      return NULL;
+    }
+
   mbs = garglist->word->word;
   slen = strlen (mbs);
   ws = (wchar_t *)xmalloc ((slen + 1) * sizeof (wchar_t));
@@ -1547,6 +1580,9 @@ getwidechar (void)
   size_t slen, mblength;
   DECLARE_MBSTATE;
 
+  if (garglist == 0)
+    return L'\0';
+
   wc = 0;
   mblength = mbrtowc (&wc, garglist->word->word, locale_mb_cur_max, &state);
   if (MB_INVALIDCH (mblength))
@@ -1571,7 +1607,7 @@ convwidestr (wchar_t *ws, int prec)
 
   ts = (const wchar_t *)ws;
 
-  if (prec > 0)
+  if (prec >= 0)
     {
       rsize = prec * MB_CUR_MAX;
       ret = (char *)xmalloc (rsize + 1);
diff --git a/parse.y b/parse.y
index dd35ea768ec0fe12fa7fb16060ead60bebd367b2..0c8dc3f516c048fd0a286ff80ca689a953163f80 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -3793,7 +3793,8 @@ parse_matched_pair (int qc, int open, int close, size_t *lenp, int flags)
       if (ch == EOF)
        {
          free (ret);
-         parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
+         if ((parser_state & PST_NOERROR) == 0)
+           parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
          EOF_Reached = 1;      /* XXX */
          parser_state |= PST_NOERROR;  /* avoid redundant error message */
          return (&matched_pair_error);
@@ -4602,7 +4603,7 @@ xparse_dolparen (const char *base, char *string, size_t *indp, int flags)
   /*(*/
   parser_state |= PST_CMDSUBST|PST_EOFTOKEN;   /* allow instant ')' */ /*{(*/
   closer = shell_eof_token = funsub ? '}' : ')';
-  if (flags & SX_COMPLETE)
+  if (flags & (SX_COMPLETE|SX_NOERROR))
     parser_state |= PST_NOERROR;
   if (funsub)
     parser_state |= PST_FUNSUBST;
@@ -4733,7 +4734,7 @@ parse_string_to_command (char *string, int flags)
 #if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
   pushed_string_list = (STRING_SAVER *)NULL;
 #endif
-  if (flags & SX_COMPLETE)
+  if (flags & (SX_COMPLETE|SX_NOERROR))
     parser_state |= PST_NOERROR;
 
   parser_state |= PST_STRING;
index fb08a5c1e48d13b4930ee7d0df20b35d5d02860c..346557a1838e9191914481bbb7d09d4428cc4566 100644 (file)
@@ -210,6 +210,7 @@ e
 b  c
 $0
 declare -a A=([0]="X=a" [1]="b")
+2 3 4 5 6
 FIN1:0
 FIN2:0
 FIN3:0
index bd2ee5660a8e9e3c7c4ddda82f96f7eaeec98a61..b6d6c9cc69f67ee7560af94cbdc7e9cf0538109c 100644 (file)
@@ -407,6 +407,10 @@ Z='a b'
 A=( X=$Z )
 declare -p A
 
+# combine with brace expansion
+letters=( {0..9} )
+echo "${letters["{2..6}"]}"
+
 # tests for assigning to noassign array variables
 BASH_ARGC=(xxx) ; echo FIN1:$?
 BASH_ARGC=foio ; echo FIN2:$?
index 75be33e81af7a6fd432b57039d7e781c932d5a77..7bcbc38802126eea5c2726a16d325520cea282ce 100644 (file)
@@ -22,6 +22,11 @@ foobar foobaz
 bazx bazy
 vx vy
 bazx bazy
+4
+4
+./braces.tests: command substitution: line 59: unexpected EOF while looking for matching `)'
+4
+4
 1 2 3 4 5 6 7 8 9 10
 0..10 braces
 0 1 2 3 4 5 6 7 8 9 10 braces
index 56a08166ad05bdf1319bf74b5424eab6df2dfa4b..e1920f29a9c8b317a68a535749712f429048b7d0 100644 (file)
@@ -49,6 +49,17 @@ echo ${var}{x,y}
 
 unset var varx vary
 
+# make sure ${ is parsed as a word expansion, since it may contain other
+# expansions
+a=4
+echo "${a#'$('\'}"
+echo "${a-'$('\'}"
+echo "${a+'$('\'}"
+
+echo "${a#aaaa'$(aaaa'aaa)aaa\'}"
+echo "${a#aaaa'$(aaaa)'aaaa\'}"
+unset -v a
+
 # new sequence brace operators
 echo {1..10}
 
index 6ec11598a69d15dec36630671cf8903bf11cb219..bc2dae5e57719c753f0e5d973aa464cd639f1b45 100644 (file)
@@ -166,6 +166,20 @@ argv[2] = <^?>
 argv[1] = <^A^?>
 argv[1] = <^A^?^A^?>
 argv[1] = <^A^A^?>
+argv[1] = <\^A>
+argv[1] = <^A>
+argv[1] = <\^A>
+argv[1] = <\^A>
+argv[1] = <^A>
+argv[1] = <^A>
+argv[1] = <^A^A>
+argv[1] = <^A^A>
+argv[1] = <\^A>
+argv[1] = <\^A>
+argv[1] = <\^A^?>
+argv[1] = <\^A^?>
+argv[1] = <^\^A ^\^?>
+argv[1] = <^A ^_>
 0.net
 0.net0
 
index 3dbe3d90f8cdb688c9f6fed32937797c7bebe5db..234705e9e4bafe62e79f29ea5fcabe70653cab30 100644 (file)
@@ -32,3 +32,23 @@ recho $FOO
 recho '\ 1\7f'
 recho '\ 1\7f\ 1\7f'
 recho '\ 1\ 1\7f'
+
+# tests of backslash-escaped CTLESC
+
+recho "${_+\\ 1}"
+recho ${_+\\ 1}
+recho "${_+\\\ 1}"
+recho ${_+\\\ 1}
+recho "${_+\ 1}"
+recho ${_+\ 1}
+recho "${_+\ 1\ 1}"
+recho ${_+\ 1\ 1}
+
+recho $'\\\1'
+recho "\\\ 1"
+
+recho "\\\ 1\7f"
+recho \\\ 1\7f
+
+recho $'\c\\\001 \c\\\177'
+recho $'\c\ 1 \c\7f'
index cf6f77e1cf9e39896a961d54a49e63831f9ac068..29f46f1820b4d78880b4c0c337cc78c45af8c88b 100644 (file)
@@ -21,6 +21,8 @@ this\&that
 echo a\\;ls
 echo a\'\;ls
 echo 'a'\''b'\;ls
+\*
+\*
 1 2 3 4 5 
 onestring 0 0 0
 onestring 0 0 0.00
@@ -38,7 +40,7 @@ A7
 --\"abcd\"--
 --\'abcd\'--
 --a\x--
-./printf.tests: line 112: printf: missing hex digit for \x
+./printf.tests: line 115: printf: missing hex digit for \x
 --\x--
 ----
 ----
@@ -99,12 +101,12 @@ A7
 26
 26
 26
-./printf.tests: line 236: printf: `%10': missing format character
-./printf.tests: line 237: printf: `M': invalid format character
-ab./printf.tests: line 240: printf: `y': invalid format character
-./printf.tests: line 243: printf: GNU: invalid number
+./printf.tests: line 239: printf: `%10': missing format character
+./printf.tests: line 240: printf: `M': invalid format character
+ab./printf.tests: line 243: printf: `y': invalid format character
+./printf.tests: line 246: printf: GNU: invalid number
 0
-./printf.tests: line 244: printf: GNU: invalid number
+./printf.tests: line 247: printf: GNU: invalid number
 0
 -
 (foo )(bar )
@@ -157,9 +159,15 @@ b
 xx
 xx
 <   ><   >
-./printf.tests: line 348: printf: 9223372036854775825: Result too large
+0
+^@
+0
+0.00
+''
+''
+./printf.tests: line 364: printf: 9223372036854775825: Result too large
 9223372036854775807
-./printf.tests: line 349: printf: -9223372036854775815: Result too large
+./printf.tests: line 365: printf: -9223372036854775815: Result too large
 -9223372036854775808
        one
 one\ctwo
@@ -330,6 +338,10 @@ hello  --
 hello --
 123 --
 6 --
+0000000 000                                                            
+0000001
+0000000 000                                                            
+0000001
 0000000 340 262 207 340 262 263 340 262 277 340 262 225 340 263 206 340
 0000010 262 227 340 262 263 340 263 201 012                            
 0000019
@@ -355,3 +367,38 @@ hello --
 0000007
 0000000 340 262 207 040 040 040 055 055 055 012                        
 000000a
+[][]
+./printf7.sub: line 19: printf: 21474836470: Result too large
+[]
+./printf7.sub: line 20: printf: 21474836470: Result too large
+[X]
+./printf7.sub: line 22: printf: 21474836470: Result too large
+VAR=[]
+./printf7.sub: line 25: printf: 21474836470: Result too large
+VAR=[X]
+./printf7.sub: line 31: printf: 9223372036854775825: Result too large
+[ ]
+./printf7.sub: line 32: printf: 9223372036854775825: Result too large
+[X]
+./printf7.sub: line 34: printf: 9223372036854775825: Result too large
+VAR=[ ]
+./printf7.sub: line 37: printf: 9223372036854775825: Result too large
+VAR=[X]
+./printf7.sub: line 43: printf: 21474836470: Result too large
+[]
+./printf7.sub: line 44: printf: 21474836470: Result too large
+[X]
+./printf7.sub: line 46: printf: 21474836470: Result too large
+VAR=[]
+./printf7.sub: line 49: printf: 21474836470: Result too large
+VAR=[X]
+./printf7.sub: line 55: printf: 9223372036854775825: Result too large
+[]
+./printf7.sub: line 56: printf: 9223372036854775825: Result too large
+[X]
+./printf7.sub: line 58: printf: 9223372036854775825: Result too large
+VAR=[]
+./printf7.sub: line 61: printf: 9223372036854775825: Result too large
+VAR=[X]
+XY
+XY
index f334f8b1e0ad0c9b759ca3db63f1130b2dba1bd2..af03960a8aaa0d6f2863c9f1669ecaa3186598e0 100644 (file)
@@ -77,6 +77,9 @@ printf 'echo %.2Q%Q\n' "$S" "$T"      # note the difference
 # a different way to do it
 printf 'echo %.*s%q\n' ${#S1} "$S1" "$T"
 
+printf '%.1Q\n' '**'
+printf '%.*Q\n' 1 '**'
+
 # make sure the format string is reused to use up arguments
 printf "%d " 1 2 3 4 5; printf "\n"
 
@@ -341,6 +344,19 @@ printf -v var "%b" @(hugo); echo "x${var}x"
 # make sure that missing arguments are always handled like the empty string
 printf "<%3s><%3b>\n"
 
+# other format specifiers with missing arguments
+# 0
+printf '%d\n'
+# null char
+printf '%c\n'
+
+printf '%x\n'
+printf '%4.2f\n'
+
+printf '%b'
+printf '%q\n'
+printf '%Q\n'
+
 # let's test some out-of-range integer errors for POSIX-specified behavior
 TOOBIG=9223372036854775825
 TOOSMALL=-9223372036854775815
@@ -348,8 +364,6 @@ TOOSMALL=-9223372036854775815
 printf '%d\n' "$TOOBIG"
 printf '%d\n' "$TOOSMALL"
 
-# invalid variable name
-
 # tests variable assignment with -v
 ${THIS_SH} ./printf1.sub
 ${THIS_SH} ./printf2.sub
@@ -358,3 +372,4 @@ ${THIS_SH} ./printf4.sub
 ${THIS_SH} ./printf5.sub
 # multibyte characters with %ls/%S and %lc/%C
 ${THIS_SH} ./printf6.sub
+${THIS_SH} ./printf7.sub
index 0dc3b28b11ad06aff9c0fd822ba2f1849c404bf3..fbacd4d53003b4c40978b1bafb335e1ce8dd17df 100644 (file)
@@ -1,3 +1,24 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# this should echo nothing
+printf '%ls'
+# this should echo a null byte
+printf '%lc' | hexdump -b
+
+# this should echo a null byte per posix interp 1647
+printf '%lc' '' | hexdump -b
+
 # test %ls and %lc with multibyte characters
 
 V=ಇಳಿಕೆಗಳು
@@ -19,3 +40,6 @@ printf "%C\n" "$V3" | hexdump -b
 
 printf "%4.2lc\n" "$V3" | hexdump -b
 printf "%-4.2lc---\n" "$V3" | hexdump -b
+
+# make sure %ls handles 0 precision the same as %s
+printf '[%.0s][%.0ls]\n' X X
diff --git a/tests/printf7.sub b/tests/printf7.sub
new file mode 100644 (file)
index 0000000..f1aa856
--- /dev/null
@@ -0,0 +1,68 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# tests of integer overflow for field width and precision arguments
+INT_MAX=$(getconf INT_MAX)
+TOOBIG=$(( $INT_MAX * 10 ))
+
+printf '[%*s]\n' "${TOOBIG}"
+printf '[%*s]\n' "${TOOBIG}" X
+
+printf -v VAR '[%*s]' "${TOOBIG}"
+echo VAR="$VAR"
+unset -v VAR
+printf -v VAR '[%*s]' "${TOOBIG}" X
+echo VAR="$VAR"
+unset -v VAR
+
+TOOBIG=9223372036854775825
+
+printf '[%*s]\n' "${TOOBIG}"
+printf '[%*s]\n' "${TOOBIG}" X
+
+printf -v VAR '[%*s]' "${TOOBIG}"
+echo VAR="$VAR"
+unset -v VAR
+printf -v VAR '[%*s]' "${TOOBIG}" X
+echo VAR="$VAR"
+unset -v VAR
+
+TOOBIG=$(( $INT_MAX * 10 ))
+
+printf '[%.*s]\n' "${TOOBIG}"
+printf '[%.*s]\n' "${TOOBIG}" X
+
+printf -v VAR '[%.*s]' "${TOOBIG}"
+echo VAR="$VAR"
+unset -v VAR
+printf -v VAR '[%.*s]' "${TOOBIG}" X
+echo VAR="$VAR"
+unset -v VAR
+
+TOOBIG=9223372036854775825
+
+printf '[%.*s]\n' "${TOOBIG}"
+printf '[%.*s]\n' "${TOOBIG}" X
+
+printf -v VAR '[%.*s]' "${TOOBIG}"
+echo VAR="$VAR"
+unset -v VAR
+printf -v VAR '[%.*s]' "${TOOBIG}" X
+echo VAR="$VAR"
+unset -v VAR
+
+# out of range inline precisions
+
+printf "%.${TOOBIG}s\n" XY
+printf "%.${TOOBIG}Q\n" XY
index 9e0f0c9d4b777709905f396c26fd82b72fba5261..9c7fd33bdad1406f51fbb4b44bddb982b8d7f154 100644 (file)
@@ -31,6 +31,8 @@ argv[1] = < foo>
 argv[1] = <foo>
 argv[1] = <foo>
 argv[1] = < foo>
+./read.tests: line 101: b: readonly variable
+a = a b = c = stat = 2
 a = abcdefg
 xyz
 a = xyz
index 5829df01fc9e2b88ea31d6c47b9d22355f791338..c06cd7a76591cabf057a2ec158663094cf608354 100644 (file)
@@ -96,6 +96,15 @@ echo " foo" | { IFS=$' \t\n' ; read line; recho "$line"; }
 
 echo " foo" | { IFS=$':' ; read line; recho "$line"; }
 
+# this leaves `b' readonly
+readonly b
+read a b c <<EOF
+a b c
+EOF
+
+# the latest POSIX draft says $? should be > 1
+echo a = $a b = $b c = $c stat = $?
+
 # test read -d delim behavior
 ${THIS_SH} ./read1.sub
 
index 554e21839466f60dabb150b096a708e63b054bb5..1045d1f52d7db247bcd1c14cfda4fa9924a1cd4d 100644 (file)
@@ -1,2 +1,2 @@
-${THIS_SH} ./braces.tests > ${BASH_TSTOUT}
+${THIS_SH} ./braces.tests > ${BASH_TSTOUT} 2>&1
 diff ${BASH_TSTOUT} braces.right && rm -f ${BASH_TSTOUT}
index 3b95df0ba4d3fde4f535a2a73ba8832c1307242a..48f67774fb30d1a3a60a56d1ace5c2fa02ed7092 100644 (file)
@@ -3695,7 +3695,9 @@ copy_variable (SHELL_VAR *var)
 static void
 dispose_variable_value (SHELL_VAR *var)
 {
-  if (function_p (var))
+  if (nofree_p (var))
+    var_setvalue (var, (char *)NULL);
+  else if (function_p (var))
     dispose_command (function_cell (var));
 #if defined (ARRAY_VARS)
   else if (array_p (var))
@@ -3930,18 +3932,8 @@ makunbound (const char *name, VAR_CONTEXT *vc)
   if (old_var && local_p (old_var) &&
        (old_var->context == variable_context || (localvar_unset && old_var->context < variable_context)))
     {
-      if (nofree_p (old_var))
-       var_setvalue (old_var, (char *)NULL);
-#if defined (ARRAY_VARS)
-      else if (array_p (old_var))
-       array_dispose (array_cell (old_var));
-      else if (assoc_p (old_var))
-       assoc_dispose (assoc_cell (old_var));
-#endif
-      else if (nameref_p (old_var))
-       FREE (nameref_cell (old_var));
-      else
-       FREE (value_cell (old_var));
+      dispose_variable_value (old_var);
+
 #if 0
       /* Reset the attributes.  Preserve the export attribute if the variable
         came from a temporary environment.  Make sure it stays local, and