]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
add stdbool.h detection and replacement for bool; use ckd_mul/ckd_add/ckd_sub where...
authorChet Ramey <chet.ramey@case.edu>
Mon, 18 Mar 2024 15:45:39 +0000 (11:45 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 18 Mar 2024 15:45:39 +0000 (11:45 -0400)
15 files changed:
CWRU/CWRU.chlog
MANIFEST
bashansi.h
braces.c
builtins/printf.def
config.h.in
configure
configure.ac
doc/bash.info
doc/bashref.info
doc/bashref.texi
externs.h
lib/sh/stringvec.c
m4/c-bool.m4 [new file with mode: 0644]
stringlib.c

index 7ba8ea53917d7475f2ea56c885c74778cc179337..c5e0c78a03ba3c50a2f08ed876ac434d12d48595 100644 (file)
@@ -8851,3 +8851,48 @@ configure.ac
 
 Makefile.in
        - CREATED_HEADERS: add stdckdint.h
+
+stringlib.c,externs.h
+       - substring: now takes size_t arguments for START and END
+
+lib/sh/stringvec.c
+       - strvec_create,strvec_mcreate,strvec_resize,strvec_mresize: use
+         ckd_mul to avoid size_t overflow
+       - strvec_len,strvec_flush: use size_t variable as array index
+         From a report by Paul Eggert <eggert@cs.ucla.edu>
+
+bashansi.h
+       - stdbool.h: include if we have it, typedef bool as unsigned char if
+         we don't and HAVE_C_BOOL isn't defined
+
+
+m4/c-bool.m4
+       - autoconf check for `bool' from gnulib
+
+configure.ac
+       - include m4/c-bool.m4, call gl_C_BOOL; don't explicitly check for
+         stdbool.h using AC_CHECK_HEADERS any more
+
+config.h.in
+       - HAVE_C_BOOL: define
+
+                                  3/16
+                                  ----
+
+builtins/printf.def
+       - decodeprec: now decodeint, takes new arguments: a char ** that is
+         the string to parse and update, an argument saying whether or not
+         to print an error message on overflow, and an argument that should
+         be the return value on overflow; use ckd_* macros to check overflow
+       - printstr, printwidestr: use a different mechanism to check overflow;
+         call decodeint to get precision and field width
+
+braces.c
+       - include stdckdint.h for the ckd_* overflow checking macros
+       - mkseq: the width argument is now size_t
+       - mkseq: perform overflow detection using the ckd_* macros
+       - mkseq: perform zero-padding directly instead of using asprintf; the
+         sprintf family has trouble when width > INT_MAX
+       - expand_seqterm: use size_t instead of int for length and width
+         variables
+         From a report by Paul Eggert <eggert@cs.ucla.edu>
index b9aff039eea93e5f48cb9cc68af846aa6bf818bb..c1f079eedfe3ccecbc783f71dc709942bb8ecfdb 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -530,6 +530,7 @@ m4/strtoimax.m4             f
 m4/stat-time.m4                f
 m4/timespec.m4         f
 m4/bison.m4            f
+m4/c-bool.m4           f
 m4/codeset.m4          f
 m4/extern-inline.m4    f
 m4/fcntl-o.m4          f
index dd2a544cd073288f2619decde285c092c61df51a..4feaadfb3f1b407b3fc138d609b23b5e46f88faf 100644 (file)
@@ -1,6 +1,6 @@
 /* bashansi.h -- Typically included information required by picky compilers. */
 
-/* Copyright (C) 1993-2021 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #  include "ansi_stdlib.h"
 #endif /* !HAVE_STDLIB_H */
 
+/* Prefer stdbool.h if we have it, maybe have to rethink this later */
+#if defined (HAVE_STDBOOL_H)
+#  include <stdbool.h>
+#else
+#  ifndef HAVE_C_BOOL
+#    undef bool
+typedef unsigned char bool;
+#  endif
+#endif
+
 #endif /* !_BASHANSI_H_ */
index 17d280734b6b0e66cdab0c067f7738a58a2a5139..444807a71eb3ac4b3d13c59245c7bfab7f9395e3 100644 (file)
--- a/braces.c
+++ b/braces.c
@@ -32,6 +32,7 @@
 #endif
 
 #include <errno.h>
+#include <stdckdint.h>
 
 #include "bashansi.h"
 #include "bashintl.h"
@@ -77,7 +78,7 @@ static const int brace_arg_separator = ',';
 static int brace_gobbler (char *, size_t, int *, int);
 static char **expand_amble (char *, size_t, int);
 static char **expand_seqterm (char *, size_t);
-static char **mkseq (intmax_t, intmax_t, intmax_t, int, int);
+static char **mkseq (intmax_t, intmax_t, intmax_t, int, size_t);
 static char **array_concat (char **, char **);
 
 #if 0
@@ -349,51 +350,37 @@ expand_amble (char *text, size_t tlen, int flags)
 #define ST_ZINT        3
 
 static char **
-mkseq (intmax_t start, intmax_t end, intmax_t incr, int type, int width)
+mkseq (intmax_t start, intmax_t end, intmax_t incr, int type, size_t width)
 {
-  intmax_t n, prevn;
-  int i, nelem;
+  intmax_t prevn, n, abs_incr;
+  size_t nelem, i;
   char **result, *t;
+  char lbuf[INT_BUFSIZE_BOUND (uintmax_t)];
 
   if (incr == 0)
     incr = 1;
 
-  if (start > end && incr > 0)
-    incr = -incr;
-  else if (start < end && incr < 0)
-    {
-      if (incr == INTMAX_MIN)          /* Don't use -INTMAX_MIN */
-       return ((char **)NULL);
-      incr = -incr;
-    }
-
-  /* Check that end-start will not overflow INTMAX_MIN, INTMAX_MAX.  The +3
-     and -2, not strictly necessary, are there because of the way the number
-     of elements and value passed to strvec_create() are calculated below. */
-  if (SUBOVERFLOW (end, start, INTMAX_MIN+3, INTMAX_MAX-2))
+  abs_incr = incr;
+  if (incr < 0 && ckd_sub (&abs_incr, 0, incr))
     return ((char **)NULL);
 
-  prevn = sh_imaxabs (end - start);
-  /* Need to check this way in case INT_MAX == INTMAX_MAX */
-  if (INT_MAX == INTMAX_MAX && (ADDOVERFLOW (prevn, 2, INT_MIN, INT_MAX)))
+  /* Make sure incr agrees with start and end */
+  if ((start < end) == (incr < 0) && ckd_sub (&incr, 0, incr))
     return ((char **)NULL);
-  /* Make sure the assignment to nelem below doesn't end up <= 0 due to
-     intmax_t overflow */
-  else if (ADDOVERFLOW ((prevn/sh_imaxabs(incr)), 1, INTMAX_MIN, INTMAX_MAX))
+
+  /* prevn = sh_imaxabs (end - start); */
+  if (start < end ? ckd_sub (&prevn, end, start) : ckd_sub (&prevn, start, end))
     return ((char **)NULL);
 
-  /* XXX - TOFIX: potentially allocating a lot of extra memory if
-     imaxabs(incr) != 1 */
-  /* Instead of a simple nelem = prevn + 1, something like:
-       nelem = (prevn / imaxabs(incr)) + 1;
-     would work */
-  if ((prevn / sh_imaxabs (incr)) > INT_MAX - 3)       /* check int overflow */
+  /* nelem = floor (abs ((end - start) / incr)) plus 1 for first element plus
+     trailing null. Account for trailing null up here for overflow check */
+  if (ckd_add (&nelem, prevn / abs_incr, 2))
     return ((char **)NULL);
-  nelem = (prevn / sh_imaxabs(incr)) + 1;
-  result = strvec_mcreate (nelem + 1);
+
+  result = strvec_mcreate (nelem);
   if (result == 0)
     {
-      internal_error (_("brace expansion: failed to allocate memory for %u elements"), (unsigned int)nelem);
+      internal_error (_("brace expansion: failed to allocate memory for %s elements"), uinttostr (nelem - 1, lbuf, sizeof (lbuf)));
       return ((char **)NULL);
     }
 
@@ -415,9 +402,23 @@ mkseq (intmax_t start, intmax_t end, intmax_t incr, int type, int width)
        result[i++] = t = itos (n);
       else if (type == ST_ZINT)
        {
-         int len, arg;
-         arg = n;
-         len = asprintf (&t, "%0*d", width, arg);
+         size_t tlen;
+
+         t = itos (n);
+         tlen = strlen (t);
+         if (tlen < width)     /* zero-pad the result directly to avoid sprintf */
+           {
+             char *t0;
+             t0 = t;
+             t = realloc (t, width + 1);
+             if (t == 0)
+               free (t0);
+             else
+               {
+                 memmove (t + (width - tlen), t, tlen + 1);
+                 memset (t + (n < 0), '0', width - tlen);
+               }
+           }
          result[i++] = t;
        }
       else
@@ -433,23 +434,19 @@ mkseq (intmax_t start, intmax_t end, intmax_t incr, int type, int width)
       /* We failed to allocate memory for this number, so we bail. */
       if (t == 0)
        {
-         char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
+         char *p;
 
          /* Easier to do this than mess around with various intmax_t printf
             formats (%ld? %lld? %jd?) and PRIdMAX. */
-         p = inttostr (n, lbuf, sizeof (lbuf));
+         p = uinttostr (n, lbuf, sizeof (lbuf));
          internal_error (_("brace expansion: failed to allocate memory for `%s'"), p);
          strvec_dispose (result);
          return ((char **)NULL);
        }
 
-      /* Handle overflow and underflow of n+incr */
-      if (ADDOVERFLOW (n, incr, INTMAX_MIN, INTMAX_MAX))
-        break;
-
       n += incr;
 
-      if ((incr < 0 && n < end) || (incr > 0 && n > end))
+      if (i == nelem - 1)
        break;
     }
   while (1);
@@ -462,7 +459,8 @@ static char **
 expand_seqterm (char *text, size_t tlen)
 {
   char *t, *lhs, *rhs;
-  int lhs_t, rhs_t, lhs_l, rhs_l, width;
+  int lhs_t, rhs_t;
+  size_t lhs_l, rhs_l, width;
   intmax_t lhs_v, rhs_v, incr;
   intmax_t tl, tr;
   char **result, *ep, *oep;
index d43068739a0414dfe554a21151144d2727d0fa09..2327bd5d62f2fbaf75781b2f3976280fc448186f 100644 (file)
@@ -70,6 +70,7 @@ $END
 
 #include <stdarg.h>
 
+#include <stdckdint.h>
 #include <stdio.h>
 #include <chartypes.h>
 
@@ -245,24 +246,29 @@ static char *conv_buf;
 static size_t conv_bufsize;
 
 static inline int
-decodeprec (char *ps)
+decodeint (char **str, int diagnose, int overflow_return)
 {
-  intmax_t mpr;
-  int pr;
-  char *s;
+  int pr, v;
+  char *ps;
+
+  ps = *str;
+  pr = *ps++ - '0';
+  v = 0;
 
-  s = ps;              /* error checking */
-  mpr = *ps++ - '0';
-  while (DIGIT (*ps))
-    mpr = (mpr * 10) + (*ps++ - '0');
-  if (mpr < 0 || mpr > INT_MAX)
+  /* use C23 macros to check overflow */
+  for (; DIGIT (*ps); ps++)
     {
-#if 0
-      report_erange (s, ps);
-#endif
+      v |= ckd_mul (&pr, pr, 10);
+      v |= ckd_add (&pr, pr, *ps - '0');
+    }
+  if (v && diagnose)
+    {
+      report_erange (*str, ps);
       return -1;
-    }    
-  return (pr = mpr);
+    }
+
+  *str = ps;
+  return (v ? overflow_return : pr);
 }
 
 int
@@ -668,7 +674,11 @@ printf_builtin (WORD_LIST *list)
                if (convch == 'Q' && (have_precision || precstart))
                  {
                    if (precstart)
-                     precision = decodeprec (precstart);
+                     {
+                       char *prec;
+                       prec = precstart;
+                       precision = decodeint (&prec, 0, -1);
+                     }
                    slen = strlen (p);
                    /* printf precision works in bytes. */
                    if (precision >= 0 && precision < slen)
@@ -838,10 +848,11 @@ report_erange (char *s, char *e)
 static int
 printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
 {
+#if 0
   char *s;
+#endif
   int padlen, nc, ljust, i;
   int fw, pr;                  /* fieldwidth and precision */
-  intmax_t mfw, mpr;
 
   if (string == 0)
     string = "";
@@ -854,8 +865,6 @@ printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
 
   ljust = fw = 0;
   pr = -1;
-  mfw = 0;
-  mpr = -1;
 
   /* skip flags */
   while (strchr (SKIP1, *fmt))
@@ -877,20 +886,7 @@ printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
        }
     }
   else if (DIGIT (*fmt))
-    {
-      s = fmt;
-      mfw = *fmt++ - '0';
-      while (DIGIT (*fmt))
-       mfw = (mfw * 10) + (*fmt++ - '0');
-      /* Error if fieldwidth > INT_MAX here */
-      if (mfw < 0 || mfw > INT_MAX)
-       {
-         report_erange (s, fmt);
-         fw = 0;
-       }
-      else
-       fw = mfw;
-    }
+    fw = decodeint (&fmt, 1, 0);
 
   /* get precision, if present. doesn't handle negative precisions */
   if (*fmt == '.')
@@ -903,20 +899,11 @@ printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
        }
       else if (DIGIT (*fmt))
        {
-         s = fmt;
-         mpr = *fmt++ - '0';
-         while (DIGIT (*fmt))
-           mpr = (mpr * 10) + (*fmt++ - '0');
-         /* Error if precision > INT_MAX here */
-         if (mpr < 0 || mpr > INT_MAX)
-           {
-             report_erange (s, fmt);
-             pr = -1;
-           }
-         else
-           pr = mpr;
+         pr = decodeint (&fmt, 1, -1);
+         /* pr < precision means we adjusted precision in printf_builtin
+            for the quoted string length (%Q), so we use the adjusted value */
          if (pr < precision && precision < INT_MAX)
-           pr = precision;             /* XXX */
+           pr = precision;
        }
       else
        pr = 0;         /* "a null digit string is treated as zero" */
@@ -964,7 +951,6 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
   char *string;
   int padlen, nc, ljust, i;
   int fw, pr;                  /* fieldwidth and precision */
-  intmax_t mfw, mpr;
 
   if (wstring == 0)
     wstring = L"";
@@ -977,8 +963,6 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
 
   ljust = fw = 0;
   pr = -1;
-  mfw = 0;
-  mpr = -1;
 
   /* skip flags */
   while (strchr (SKIP1, *fmt))
@@ -1000,19 +984,7 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
        }
     }
   else if (DIGIT (*fmt))
-    {
-      mfw = *fmt++ - '0';
-      while (DIGIT (*fmt))
-       mfw = (mfw * 10) + (*fmt++ - '0');
-      /* Error if fieldwidth > INT_MAX here */
-      if (mfw < 0 || mfw > INT_MAX)
-       {
-         report_erange (s, fmt);
-         fw = 0; 
-       }
-      else
-       fw = mfw;
-    }
+    fw = decodeint (&fmt, 1, 0);
 
   /* get precision, if present. doesn't handle negative precisions */
   if (*fmt == '.')
@@ -1025,19 +997,11 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
        }
       else if (DIGIT (*fmt))
        {
-         mpr = *fmt++ - '0';
-         while (DIGIT (*fmt))
-           mpr = (mpr * 10) + (*fmt++ - '0');
-         /* Error if precision > INT_MAX here */
-         if (mpr < 0 || mpr > INT_MAX)
-           {
-             report_erange (s, fmt);
-             pr = -1;
-            }
-          else
-            pr = mpr;
+         pr = decodeint (&fmt, 1, -1);
+         /* pr < precision means we adjusted precision in printf_builtin
+            for the quoted string length (%Q), so we use the adjusted value */
          if (pr < precision && precision < INT_MAX)
-           pr = precision;             /* XXX */
+           pr = precision;
        }
       else
        pr = 0;         /* "a null digit string is treated as zero" */
index c9411fa58c44eec7030176ea715b02f9ba3c169c..cee53587d95b7c8e4412fb3fc99ac70ad13c4cd9 100644 (file)
 /* The number of bytes in a `wchar_t', if supported */
 #undef SIZEOF_WCHAR_T
 
+#undef HAVE_C_BOOL
+
 /* System paths */
 
 #define DEFAULT_MAIL_DIRECTORY "/usr/spool/mail"
index 26df275df12ecb4451761d6df4d86d0912502695..6f6c0150ac4afb64186e5e77483896da9de87035 100755 (executable)
--- a/configure
+++ b/configure
@@ -2988,6 +2988,7 @@ as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
 as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
 as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
 as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
+as_fn_append ac_header_c_list " stdbool.h stdbool_h HAVE_STDBOOL_H"
 gt_needs="$gt_needs need-ngettext"
 as_fn_append ac_header_c_list " sys/param.h sys_param_h HAVE_SYS_PARAM_H"
 as_fn_append ac_func_c_list " getpagesize HAVE_GETPAGESIZE"
@@ -7111,6 +7112,12 @@ fi
 
 
 
+# Check for bool that conforms to C2023.
+
+
+
+
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
 printf %s "checking for an ANSI C-conforming const... " >&6; }
 if test ${ac_cv_c_const+y}
@@ -7668,6 +7675,43 @@ printf "%s\n" "$ac_cv_c_restrict" >&6; }
 
 
 
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bool, true, false" >&5
+printf %s "checking for bool, true, false... " >&6; }
+if test ${gl_cv_c_bool+y}
+then :
+  printf %s "(cached) " >&6
+else $as_nop
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #if true == false
+           #error "true == false"
+          #endif
+          extern bool b;
+          bool b = true == false;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  gl_cv_c_bool=yes
+else $as_nop
+  gl_cv_c_bool=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gl_cv_c_bool" >&5
+printf "%s\n" "$gl_cv_c_bool" >&6; }
+  if test "$gl_cv_c_bool" = yes; then
+
+printf "%s\n" "#define HAVE_C_BOOL 1" >>confdefs.h
+
+  fi
+
+
+
+
+
+
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
 printf %s "checking for a race-free mkdir -p... " >&6; }
 if test -z "$MKDIR_P"; then
@@ -9068,8 +9112,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
         LIBS=$save_LIBS
         test $gl_pthread_api = yes && break
       done
-      echo "$as_me:9071: gl_pthread_api=$gl_pthread_api" >&5
-      echo "$as_me:9072: LIBPTHREAD=$LIBPTHREAD" >&5
+      echo "$as_me:9115: gl_pthread_api=$gl_pthread_api" >&5
+      echo "$as_me:9116: LIBPTHREAD=$LIBPTHREAD" >&5
 
       gl_pthread_in_glibc=no
       # On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9095,7 +9139,7 @@ rm -rf conftest*
 
           ;;
       esac
-      echo "$as_me:9098: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+      echo "$as_me:9142: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
 
       # Test for libpthread by looking for pthread_kill. (Not pthread_self,
       # since it is defined as a macro on OSF/1.)
@@ -9249,7 +9293,7 @@ fi
 
         fi
       fi
-      echo "$as_me:9252: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+      echo "$as_me:9296: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
     fi
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
 printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -9477,8 +9521,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
         LIBS=$save_LIBS
         test $gl_pthread_api = yes && break
       done
-      echo "$as_me:9480: gl_pthread_api=$gl_pthread_api" >&5
-      echo "$as_me:9481: LIBPTHREAD=$LIBPTHREAD" >&5
+      echo "$as_me:9524: gl_pthread_api=$gl_pthread_api" >&5
+      echo "$as_me:9525: LIBPTHREAD=$LIBPTHREAD" >&5
 
       gl_pthread_in_glibc=no
       # On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9504,7 +9548,7 @@ rm -rf conftest*
 
           ;;
       esac
-      echo "$as_me:9507: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+      echo "$as_me:9551: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
 
       # Test for libpthread by looking for pthread_kill. (Not pthread_self,
       # since it is defined as a macro on OSF/1.)
@@ -9658,7 +9702,7 @@ fi
 
         fi
       fi
-      echo "$as_me:9661: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+      echo "$as_me:9705: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
     fi
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
 printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -14491,12 +14535,6 @@ if test "x$ac_cv_header_dlfcn_h" = xyes
 then :
   printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
 
-fi
-ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdbool_h" = xyes
-then :
-  printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h
-
 fi
 ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default"
 if test "x$ac_cv_header_stddef_h" = xyes
index cba38970a6ce8ff4a1ea9fa711b17f22e098b78f..dd276b68e1fff2f851863a0426689a58b80cbfda 100644 (file)
@@ -765,6 +765,8 @@ m4_include([m4/xsize.m4])
 m4_include([m4/glibc21.m4])
 m4_include([m4/host-cpu-c-abi.m4])
 
+m4_include([m4/c-bool.m4])
+
 dnl C compiler characteristics
 AC_C_CONST
 AC_C_INLINE
@@ -775,6 +777,8 @@ AC_C_CHAR_UNSIGNED
 AC_C_VOLATILE
 AC_C_RESTRICT
 
+gl_C_BOOL
+
 dnl initialize GNU gettext
 dnl the use-libtool is a lie, we just use the standard Unix tools
 BASH_GNU_GETTEXT([use-libtool], [need-ngettext], [lib/intl])
@@ -787,7 +791,7 @@ BASH_HEADER_INTTYPES
 
 AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h limits.h string.h \
                 memory.h locale.h termcap.h termio.h termios.h dlfcn.h \
-                stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
+                stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
                 stdckdint.h \
                 regex.h syslog.h ulimit.h)
 AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
index bff351ee52ec03d29313046ebdbb8acb777dd441..70903605e2a3c4e0e2a5fc2bfae04f9cb2088e10 100644 (file)
@@ -484,7 +484,7 @@ current locale.  The ‘gettext’ infrastructure performs the lookup and
 translation, using the ‘LC_MESSAGES’, ‘TEXTDOMAINDIR’, and ‘TEXTDOMAIN’
 shell variables, as explained below.  See the gettext documentation for
 additional details not covered here.  If the current locale is ‘C’ or
-‘POSIX’, if there are no translations available, of if the string is not
+‘POSIX’, if there are no translations available, or if the string is not
 translated, the dollar sign is ignored.  Since this is a form of double
 quoting, the string remains double-quoted by default, whether or not it
 is translated and replaced.  If the ‘noexpand_translation’ option is
index 2b6e0325fd9cb62b4ddf5f2012819bc319307dea..9e471649d7a749ce611464be0c62afa82ce1b665 100644 (file)
@@ -485,7 +485,7 @@ current locale.  The ‘gettext’ infrastructure performs the lookup and
 translation, using the ‘LC_MESSAGES’, ‘TEXTDOMAINDIR’, and ‘TEXTDOMAIN’
 shell variables, as explained below.  See the gettext documentation for
 additional details not covered here.  If the current locale is ‘C’ or
-‘POSIX’, if there are no translations available, of if the string is not
+‘POSIX’, if there are no translations available, or if the string is not
 translated, the dollar sign is ignored.  Since this is a form of double
 quoting, the string remains double-quoted by default, whether or not it
 is translated and replaced.  If the ‘noexpand_translation’ option is
index dedfce9e07c2bf7c6d05636d170c33ea1d260ebd..adfd7346339795cd03cf49c4fdf27d9d339a57f2 100644 (file)
@@ -547,7 +547,7 @@ and @code{TEXTDOMAIN} shell variables, as explained below.
 See the gettext documentation for additional details not covered here.
 If the current locale is @code{C} or @code{POSIX},
 if there are no translations available,
-of if the string is not translated,
+or if the string is not translated,
 the dollar sign is ignored.
 Since this is a form of double quoting, the string remains double-quoted
 by default, whether or not it is translated and replaced.
index 6376bf41e67af5ac07c866e20c9982733556d853..b60fb79e4f75b844e0b92c611f756138e29641c3 100644 (file)
--- a/externs.h
+++ b/externs.h
@@ -164,7 +164,7 @@ extern int find_string_in_alist (char *, STRING_INT_ALIST *, int);
 extern char *find_token_in_alist (int, STRING_INT_ALIST *, int);
 extern int find_index_in_alist (char *, STRING_INT_ALIST *, int);
 
-extern char *substring (const char *, int, int);
+extern char *substring (const char *, size_t, size_t);
 extern char *strsub (const char *, const char *, const char *, int);
 extern char *strcreplace (const char *, int, const char *, int);
 extern void strip_leading (char *);
index bf57d6889f3503dbf2ae905481b5e17a46f824fc..10ca9da7c3467f2a2ef4a3f3ac7f668c5ebe1d3d 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include <bashansi.h>
+#include <stdckdint.h>
 #include <stdio.h>
 #include <chartypes.h>
 
 char **
 strvec_create (size_t n)
 {
-  return ((char **)xmalloc ((n) * sizeof (char *)));
+  size_t nbytes;
+
+  return ckd_mul (&nbytes, n, sizeof (char *)) ? NULL : xmalloc (nbytes);
 }
 
 /* Allocate an array of strings with room for N members. */
 char **
 strvec_mcreate (size_t n)
 {
-  return ((char **)malloc ((n) * sizeof (char *)));
+  size_t nbytes;
+
+  return ckd_mul (&nbytes, n, sizeof (char *)) ? NULL : malloc (nbytes);
 }
 
 char **
 strvec_resize (char **array, size_t nsize)
 {
-  return ((char **)xrealloc (array, nsize * sizeof (char *)));
+  size_t nbytes;
+
+  return ckd_mul (&nbytes, nsize, sizeof (char *)) ? NULL : (char **)xrealloc (array, nbytes);
 }
 
 char **
 strvec_mresize (char **array, size_t nsize)
 {
-  return ((char **)realloc (array, nsize * sizeof (char *)));
+  size_t nbytes;
+
+  return ckd_mul (&nbytes, nsize, sizeof (char *)) ? NULL : (char **)realloc (array, nbytes);
 }
 
 /* Return the length of ARRAY, a NULL terminated array of char *. */
 size_t
 strvec_len (char * const *array)
 {
-  register int i;
+  register size_t i;
 
   for (i = 0; array[i]; i++);
   return (i);
@@ -72,7 +81,7 @@ strvec_len (char * const *array)
 void
 strvec_flush (char **array)
 {
-  register int i;
+  register size_t i;
 
   if (array == 0)
     return;
diff --git a/m4/c-bool.m4 b/m4/c-bool.m4
new file mode 100644 (file)
index 0000000..2718a17
--- /dev/null
@@ -0,0 +1,27 @@
+# Check for bool that conforms to C2023.
+
+dnl Copyright 2022-2024 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_C_BOOL],
+[
+  AC_CACHE_CHECK([for bool, true, false], [gl_cv_c_bool],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([[
+          #if true == false
+           #error "true == false"
+          #endif
+          extern bool b;
+          bool b = true == false;]])],
+       [gl_cv_c_bool=yes],
+       [gl_cv_c_bool=no])])
+  if test "$gl_cv_c_bool" = yes; then
+    AC_DEFINE([HAVE_C_BOOL], [1],
+      [Define to 1 if bool, true and false work as per C2023.])
+  fi
+
+  AC_CHECK_HEADERS_ONCE([stdbool.h])
+
+])
index 0130fdaaefbbbcbf16d42c9de33825193e596854..1aa7abe6c8744967a98d255caecfdd81a303bef6 100644 (file)
@@ -115,9 +115,9 @@ find_index_in_alist (char *string, STRING_INT_ALIST *alist, int flags)
 /* Cons a new string from STRING starting at START and ending at END,
    not including END. */
 char *
-substring (const char *string, int start, int end)
+substring (const char *string, size_t start, size_t end)
 {
-  int len;
+  size_t len;
   char *result;
 
   len = end - start;