From: Chet Ramey Date: Mon, 18 Mar 2024 15:45:39 +0000 (-0400) Subject: add stdbool.h detection and replacement for bool; use ckd_mul/ckd_add/ckd_sub where... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b1e7f68032bd90dec1a2968a616b32a469929c78;p=thirdparty%2Fbash.git add stdbool.h detection and replacement for bool; use ckd_mul/ckd_add/ckd_sub where appropriate; update overflow detection in brace expansion and printf builtin --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 7ba8ea53..c5e0c78a 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -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 + +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 diff --git a/MANIFEST b/MANIFEST index b9aff039..c1f079ee 100644 --- 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 diff --git a/bashansi.h b/bashansi.h index dd2a544c..4feaadfb 100644 --- a/bashansi.h +++ b/bashansi.h @@ -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. @@ -35,4 +35,14 @@ # 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 +#else +# ifndef HAVE_C_BOOL +# undef bool +typedef unsigned char bool; +# endif +#endif + #endif /* !_BASHANSI_H_ */ diff --git a/braces.c b/braces.c index 17d28073..444807a7 100644 --- a/braces.c +++ b/braces.c @@ -32,6 +32,7 @@ #endif #include +#include #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; diff --git a/builtins/printf.def b/builtins/printf.def index d4306873..2327bd5d 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -70,6 +70,7 @@ $END #include +#include #include #include @@ -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" */ diff --git a/config.h.in b/config.h.in index c9411fa5..cee53587 100644 --- a/config.h.in +++ b/config.h.in @@ -239,6 +239,8 @@ /* 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" diff --git a/configure b/configure index 26df275d..6f6c0150 100755 --- 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 diff --git a/configure.ac b/configure.ac index cba38970..dd276b68 100644 --- a/configure.ac +++ b/configure.ac @@ -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 \ diff --git a/doc/bash.info b/doc/bash.info index bff351ee..70903605 100644 --- a/doc/bash.info +++ b/doc/bash.info @@ -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 diff --git a/doc/bashref.info b/doc/bashref.info index 2b6e0325..9e471649 100644 --- a/doc/bashref.info +++ b/doc/bashref.info @@ -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 diff --git a/doc/bashref.texi b/doc/bashref.texi index dedfce9e..adfd7346 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -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. diff --git a/externs.h b/externs.h index 6376bf41..b60fb79e 100644 --- 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 *); diff --git a/lib/sh/stringvec.c b/lib/sh/stringvec.c index bf57d688..10ca9da7 100644 --- a/lib/sh/stringvec.c +++ b/lib/sh/stringvec.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include @@ -36,33 +37,41 @@ 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 index 00000000..2718a175 --- /dev/null +++ b/m4/c-bool.m4 @@ -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]) + +]) diff --git a/stringlib.c b/stringlib.c index 0130fdaa..1aa7abe6 100644 --- a/stringlib.c +++ b/stringlib.c @@ -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;