mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 10:20:49 +02:00
add more overflow handling for printf builtin; start incorporating C23 stdckdint ; rework PRIdMAX replacements
This commit is contained in:
@@ -70,6 +70,7 @@ support/bashbug.sh
|
||||
lsignames.h
|
||||
pathnames.h
|
||||
signames.h
|
||||
stdckdint.h
|
||||
version.h
|
||||
syntax.c
|
||||
stamp-h
|
||||
|
||||
@@ -8807,3 +8807,47 @@ jobs.c
|
||||
received the signal, too) as notified, since we don't report on it
|
||||
in the JDEAD case if the signal is trapped
|
||||
|
||||
3/13
|
||||
----
|
||||
builtins/printf.def
|
||||
- PF: print an error message if printf returns an error or leaves
|
||||
ferror(stdout) true
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
3/14
|
||||
----
|
||||
builtins/printf.def
|
||||
- getint: now takes an int argument and returns it if the conversion
|
||||
overflows an int; changed callers in printf_builtin
|
||||
- getint: consolidate checks for overflow. This changes the behavior
|
||||
if the argument overflows an intmax_t: it returns a field width of
|
||||
0 (the overflow result) instead of -1, which changes how printf
|
||||
behaves. This is consistent with the behavior when the argument
|
||||
overflows an int
|
||||
- printf_builtin: change check for overflow of [LONG_MIN..LONG_MAX]
|
||||
for %d/%i to be explicit instead of relying on integer overflow of p
|
||||
- printstr,printwidestr: print message if field width or precision
|
||||
overflow, since we don't call printf
|
||||
- printstr,printwidestr: set field width and precision on integer
|
||||
overflow the way we do in printf_builtin
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
bashtypes.h
|
||||
- PRIdMAX: move redefinition here after including inttypes.h
|
||||
|
||||
builtins/printf.def,examples/loadables/seq.c,examples/loadables/getconf.h
|
||||
- remove PRIdMAX redefinitions, since it's now fixed in bashtypes.h
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
3/15
|
||||
----
|
||||
include/stdckdint.in.h,include/intprops-internal.h
|
||||
- new files, from gnulib
|
||||
|
||||
configure.ac
|
||||
- stdckdint.h: create in the build directory if the system doesn't
|
||||
provide one by copying ${srcdir}/include/stdckdint.in.h; make
|
||||
sure we don't create a new one every time, changing the timestamp
|
||||
|
||||
Makefile.in
|
||||
- CREATED_HEADERS: add stdckdint.h
|
||||
|
||||
@@ -219,6 +219,7 @@ include/ansi_stdlib.h f
|
||||
include/chartypes.h f
|
||||
include/filecntl.h f
|
||||
include/gettext.h f
|
||||
include/intprops-internal.h f
|
||||
include/maxpath.h f
|
||||
include/memalloc.h f
|
||||
include/ocache.h f
|
||||
@@ -233,6 +234,7 @@ include/shmbutil.h f
|
||||
include/shtty.h f
|
||||
include/stat-time.h f
|
||||
include/stdc.h f
|
||||
include/stdckdint.in.h f
|
||||
include/systimes.h f
|
||||
include/timer.h f
|
||||
include/typemax.h f
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# Makefile for bash-5.3, version 5.3
|
||||
# Makefile for bash-5.3, version 5.4
|
||||
#
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
|
||||
@@ -593,7 +593,7 @@ CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
|
||||
examples/loadables/perl/Makefile support/Makefile \
|
||||
lib/intl/Makefile po/Makefile po/Makefile.in
|
||||
CREATED_HEADERS = signames.h config.h pathnames.h version.h y.tab.h \
|
||||
${DEFDIR}/builtext.h
|
||||
${DEFDIR}/builtext.h stdckdint.h
|
||||
|
||||
OTHER_DOCS = $(srcdir)/CHANGES $(srcdir)/COMPAT $(srcdir)/NEWS $(srcdir)/POSIX \
|
||||
$(srcdir)/RBASH $(srcdir)/README
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@ dnl Bash specific tests
|
||||
dnl
|
||||
dnl Some derived from PDKSH 5.1.3 autoconf tests
|
||||
dnl
|
||||
dnl Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
dnl Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
dnl
|
||||
|
||||
dnl
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* bashhist.c -- bash interface to the GNU history library. */
|
||||
|
||||
/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+13
-1
@@ -1,6 +1,6 @@
|
||||
/* bashtypes.h -- Bash system types. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2009,2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -35,6 +35,18 @@
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* Fix PRIdMAX on systems where it's broken. */
|
||||
#ifdef PRI_MACROS_BROKEN
|
||||
# undef PRIdMAX
|
||||
#endif
|
||||
#ifndef PRIdMAX
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
+77
-55
@@ -89,18 +89,6 @@ $END
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if defined (PRI_MACROS_BROKEN)
|
||||
# undef PRIdMAX
|
||||
#endif
|
||||
|
||||
#if !defined (PRIdMAX)
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
@@ -154,7 +142,7 @@ extern int errno;
|
||||
char b[2]; \
|
||||
tw++; \
|
||||
b[0] = c; b[1] = '\0'; \
|
||||
if (vflag) \
|
||||
if (vflag) \
|
||||
vbadd (b, 1); \
|
||||
else \
|
||||
putchar (c); \
|
||||
@@ -178,8 +166,7 @@ extern int errno;
|
||||
if (nw < 0 || (vflag == 0 && ferror (stdout))) \
|
||||
{ \
|
||||
QUIT; \
|
||||
if (vflag) \
|
||||
builtin_error ("%s", strerror (errno)); \
|
||||
builtin_error ("%s", strerror (errno)); \
|
||||
PRETURN (EXECUTION_FAILURE); \
|
||||
} \
|
||||
tw += nw; \
|
||||
@@ -203,7 +190,8 @@ extern int asprintf (char **, const char *, ...) __attribute__((__format__ (prin
|
||||
extern int vsnprintf (char *, size_t, const char *, va_list) __attribute__((__format__ (printf, 3, 0)));
|
||||
#endif
|
||||
|
||||
static void printf_erange (char *);
|
||||
static inline void printf_erange (char *);
|
||||
static inline void report_erange (char *, char *);
|
||||
static int printstr (char *, char *, int, int, int);
|
||||
static int tescape (char *, char *, int *, int *);
|
||||
static char *bexpand (char *, int, int *, int *);
|
||||
@@ -212,7 +200,7 @@ static int vbprintf (const char *, ...) __attribute__((__format__ (printf, 1, 2)
|
||||
static char *mklong (char *, char *, size_t);
|
||||
static int getchr (void);
|
||||
static char *getstr (void);
|
||||
static int getint (void);
|
||||
static int getint (int);
|
||||
static intmax_t getintmax (void);
|
||||
static uintmax_t getuintmax (void);
|
||||
|
||||
@@ -260,11 +248,21 @@ static inline int
|
||||
decodeprec (char *ps)
|
||||
{
|
||||
intmax_t mpr;
|
||||
int pr;
|
||||
char *s;
|
||||
|
||||
s = ps; /* error checking */
|
||||
mpr = *ps++ - '0';
|
||||
while (DIGIT (*ps))
|
||||
mpr = (mpr * 10) + (*ps++ - '0');
|
||||
return (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
|
||||
if (mpr < 0 || mpr > INT_MAX)
|
||||
{
|
||||
#if 0
|
||||
report_erange (s, ps);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return (pr = mpr);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -419,10 +417,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;
|
||||
/* Handle field with overflow by ignoring fieldwidth for now.
|
||||
getint() prints a message. */
|
||||
fieldwidth = getint (0);
|
||||
}
|
||||
else
|
||||
while (DIGIT (*fmt))
|
||||
@@ -436,11 +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;
|
||||
/* Handle precision overflow by ignoring precision for now.
|
||||
getint() prints a message.
|
||||
"A negative precision is treated as if it were missing." */
|
||||
precision = getint (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -712,8 +708,8 @@ printf_builtin (WORD_LIST *list)
|
||||
long p;
|
||||
intmax_t pp;
|
||||
|
||||
p = pp = getintmax ();
|
||||
if (p != pp)
|
||||
pp = getintmax ();
|
||||
if (pp < LONG_MIN || pp > LONG_MAX)
|
||||
{
|
||||
f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
|
||||
PF (f, pp);
|
||||
@@ -724,6 +720,7 @@ printf_builtin (WORD_LIST *list)
|
||||
in "long". This also works around some long
|
||||
long and/or intmax_t library bugs in the common
|
||||
case, e.g. glibc 2.2 x86. */
|
||||
p = pp;
|
||||
f = mklong (start, "l", 1);
|
||||
PF (f, p);
|
||||
}
|
||||
@@ -811,13 +808,24 @@ printf_builtin (WORD_LIST *list)
|
||||
PRETURN (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
printf_erange (char *s)
|
||||
{
|
||||
builtin_error (_("%s: %s"), s, strerror(ERANGE));
|
||||
conversion_error = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
report_erange (char *s, char *e)
|
||||
{
|
||||
unsigned char sc;
|
||||
|
||||
sc = *e;
|
||||
*e = 0;
|
||||
printf_erange (s);
|
||||
*e = sc;
|
||||
}
|
||||
|
||||
/* We duplicate a lot of what printf(3) does here. */
|
||||
/* FMT: format
|
||||
STRING: expanded string argument
|
||||
@@ -830,9 +838,7 @@ printf_erange (char *s)
|
||||
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;
|
||||
@@ -872,11 +878,18 @@ 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? */
|
||||
fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
|
||||
/* Error if fieldwidth > INT_MAX here */
|
||||
if (mfw < 0 || mfw > INT_MAX)
|
||||
{
|
||||
report_erange (s, fmt);
|
||||
fw = 0;
|
||||
}
|
||||
else
|
||||
fw = mfw;
|
||||
}
|
||||
|
||||
/* get precision, if present. doesn't handle negative precisions */
|
||||
@@ -890,11 +903,18 @@ 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? */
|
||||
pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
|
||||
/* Error if precision > INT_MAX here */
|
||||
if (mpr < 0 || mpr > INT_MAX)
|
||||
{
|
||||
report_erange (s, fmt);
|
||||
pr = -1;
|
||||
}
|
||||
else
|
||||
pr = mpr;
|
||||
if (pr < precision && precision < INT_MAX)
|
||||
pr = precision; /* XXX */
|
||||
}
|
||||
@@ -940,9 +960,7 @@ printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
|
||||
static int
|
||||
printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int precision)
|
||||
{
|
||||
#if 0
|
||||
char *s;
|
||||
#endif
|
||||
char *string;
|
||||
int padlen, nc, ljust, i;
|
||||
int fw, pr; /* fieldwidth and precision */
|
||||
@@ -986,8 +1004,14 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
|
||||
mfw = *fmt++ - '0';
|
||||
while (DIGIT (*fmt))
|
||||
mfw = (mfw * 10) + (*fmt++ - '0');
|
||||
/* Error if fieldwidth > INT_MAX here? */
|
||||
fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
|
||||
/* Error if fieldwidth > INT_MAX here */
|
||||
if (mfw < 0 || mfw > INT_MAX)
|
||||
{
|
||||
report_erange (s, fmt);
|
||||
fw = 0;
|
||||
}
|
||||
else
|
||||
fw = mfw;
|
||||
}
|
||||
|
||||
/* get precision, if present. doesn't handle negative precisions */
|
||||
@@ -1004,8 +1028,14 @@ printwidestr (char *fmt, wchar_t *wstring, size_t len, int fieldwidth, int preci
|
||||
mpr = *fmt++ - '0';
|
||||
while (DIGIT (*fmt))
|
||||
mpr = (mpr * 10) + (*fmt++ - '0');
|
||||
/* Error if precision > INT_MAX here? */
|
||||
pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
|
||||
/* Error if precision > INT_MAX here */
|
||||
if (mpr < 0 || mpr > INT_MAX)
|
||||
{
|
||||
report_erange (s, fmt);
|
||||
pr = -1;
|
||||
}
|
||||
else
|
||||
pr = mpr;
|
||||
if (pr < precision && precision < INT_MAX)
|
||||
pr = precision; /* XXX */
|
||||
}
|
||||
@@ -1358,10 +1388,11 @@ getstr (void)
|
||||
/* 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)
|
||||
getint (int overflow_retval)
|
||||
{
|
||||
intmax_t ret;
|
||||
char *ep;
|
||||
int overflow;
|
||||
|
||||
if (garglist == 0)
|
||||
return (0);
|
||||
@@ -1371,27 +1402,18 @@ getint (void)
|
||||
|
||||
errno = 0;
|
||||
ret = strtoimax (garglist->word->word, &ep, 0);
|
||||
overflow = (errno == ERANGE) || (ret < INT_MIN || ret > INT_MAX);
|
||||
|
||||
if (*ep)
|
||||
{
|
||||
sh_invalidnum (garglist->word->word);
|
||||
conversion_error = 1;
|
||||
}
|
||||
else if (errno == ERANGE)
|
||||
else if (overflow)
|
||||
printf_erange (garglist->word->word);
|
||||
else if (ret > INT_MAX)
|
||||
{
|
||||
printf_erange (garglist->word->word);
|
||||
ret = INT_MAX;
|
||||
}
|
||||
else if (ret < INT_MIN)
|
||||
{
|
||||
printf_erange (garglist->word->word);
|
||||
ret = INT_MIN;
|
||||
}
|
||||
|
||||
garglist = garglist->next;
|
||||
return ((int)ret);
|
||||
return (overflow ? overflow_retval : (int)ret);
|
||||
}
|
||||
|
||||
static intmax_t
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* config-top.h - various user-settable options not under the control of autoconf. */
|
||||
|
||||
/* Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.ac for Bash 5.3, version 5.061.
|
||||
# From configure.ac for Bash 5.3, version 5.062.
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for bash 5.3-devel.
|
||||
#
|
||||
@@ -14533,6 +14533,12 @@ if test "x$ac_cv_header_strings_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STRINGS_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "stdckdint.h" "ac_cv_header_stdckdint_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_stdckdint_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STDCKDINT_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "regex.h" "ac_cv_header_regex_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_regex_h" = xyes
|
||||
@@ -22381,6 +22387,14 @@ ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefi
|
||||
ac_config_commands="$ac_config_commands stamp-h"
|
||||
|
||||
|
||||
if test "$ac_cv_header_stdckdint_h" = yes; then
|
||||
rm -f stdckdint.h
|
||||
elif cmp ${srcdir}/include/stdckdint.in.h stdckdint.h 2>/dev/null; then
|
||||
:
|
||||
else
|
||||
cp ${srcdir}/include/stdckdint.in.h stdckdint.h
|
||||
fi
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests run on this system so they can be shared between configure
|
||||
|
||||
+10
-1
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AC_REVISION([for Bash 5.3, version 5.061])dnl
|
||||
AC_REVISION([for Bash 5.3, version 5.062])dnl
|
||||
|
||||
define(bashvers, 5.3)
|
||||
define(relstatus, devel)
|
||||
@@ -788,6 +788,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 \
|
||||
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 \
|
||||
sys/mman.h sys/param.h sys/random.h sys/socket.h sys/stat.h \
|
||||
@@ -1352,4 +1353,12 @@ AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile \
|
||||
dnl Makefile uses this timestamp file to record whether config.h is up to date.
|
||||
AC_CONFIG_COMMANDS([stamp-h], [echo timestamp > stamp-h])
|
||||
|
||||
if test "$ac_cv_header_stdckdint_h" = yes; then
|
||||
rm -f stdckdint.h
|
||||
elif cmp ${srcdir}/include/stdckdint.in.h stdckdint.h 2>/dev/null; then
|
||||
:
|
||||
else
|
||||
cp ${srcdir}/include/stdckdint.in.h stdckdint.h
|
||||
fi
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -125,12 +125,4 @@
|
||||
# define WORD_BIT (sizeof (int) * CHAR_BIT)
|
||||
#endif
|
||||
|
||||
#if !defined (PRIdMAX)
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _GETCONF_H */
|
||||
|
||||
@@ -35,18 +35,6 @@
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined (PRI_MACROS_BROKEN)
|
||||
# undef PRIdMAX
|
||||
#endif
|
||||
|
||||
#if !defined (PRIdMAX)
|
||||
# if HAVE_LONG_LONG
|
||||
# define PRIdMAX "lld"
|
||||
# else
|
||||
# define PRIdMAX "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
|
||||
typedef long double floatmax_t;
|
||||
# define FLOATMAX_CONV "L"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* execute_cmd.h - functions from execute_cmd.c. */
|
||||
|
||||
/* Copyright (C) 1993-2017,2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2017,2022-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
/* intprops-internal.h -- properties of integer types not visible to users
|
||||
|
||||
Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GL_INTPROPS_INTERNAL_H
|
||||
#define _GL_INTPROPS_INTERNAL_H
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* Pacify GCC 13.2 in some calls to _GL_EXPR_SIGNED. */
|
||||
#if defined __GNUC__ && 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
#endif
|
||||
|
||||
/* Return a value with the common real type of E and V and the value of V.
|
||||
Do not evaluate E. */
|
||||
#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
|
||||
|
||||
/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
|
||||
<https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
|
||||
#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
|
||||
|
||||
/* The extra casts in the following macros work around compiler bugs,
|
||||
e.g., in Cray C 5.0.3.0. */
|
||||
|
||||
/* True if the real type T is signed. */
|
||||
#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* Return 1 if the real expression E, after promotion, has a
|
||||
signed or floating type. Do not evaluate E. */
|
||||
#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
|
||||
|
||||
|
||||
/* Minimum and maximum values for integer types and expressions. */
|
||||
|
||||
/* The width in bits of the integer type or expression T.
|
||||
Do not evaluate T. T must not be a bit-field expression.
|
||||
Padding bits are not supported; this is checked at compile-time below. */
|
||||
#define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
|
||||
|
||||
/* The maximum and minimum values for the type of the expression E,
|
||||
after integer promotion. E is not evaluated. */
|
||||
#define _GL_INT_MINIMUM(e) \
|
||||
(_GL_EXPR_SIGNED (e) \
|
||||
? ~ _GL_SIGNED_INT_MAXIMUM (e) \
|
||||
: _GL_INT_CONVERT (e, 0))
|
||||
#define _GL_INT_MAXIMUM(e) \
|
||||
(_GL_EXPR_SIGNED (e) \
|
||||
? _GL_SIGNED_INT_MAXIMUM (e) \
|
||||
: _GL_INT_NEGATE_CONVERT (e, 1))
|
||||
#define _GL_SIGNED_INT_MAXIMUM(e) \
|
||||
(((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)
|
||||
|
||||
/* Work around OpenVMS incompatibility with C99. */
|
||||
#if !defined LLONG_MAX && defined __INT64_MAX
|
||||
# define LLONG_MAX __INT64_MAX
|
||||
# define LLONG_MIN __INT64_MIN
|
||||
#endif
|
||||
|
||||
/* This include file assumes that signed types are two's complement without
|
||||
padding bits; the above macros have undefined behavior otherwise.
|
||||
If this is a problem for you, please let us know how to fix it for your host.
|
||||
This assumption is tested by the intprops-tests module. */
|
||||
|
||||
/* Does the __typeof__ keyword work? This could be done by
|
||||
'configure', but for now it's easier to do it by hand. */
|
||||
#if (2 <= __GNUC__ \
|
||||
|| (4 <= __clang_major__) \
|
||||
|| (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
|
||||
|| (0x5110 <= __SUNPRO_C && !__STDC__))
|
||||
# define _GL_HAVE___TYPEOF__ 1
|
||||
#else
|
||||
# define _GL_HAVE___TYPEOF__ 0
|
||||
#endif
|
||||
|
||||
/* Return 1 if the integer type or expression T might be signed. Return 0
|
||||
if it is definitely unsigned. T must not be a bit-field expression.
|
||||
This macro does not evaluate its argument, and expands to an
|
||||
integer constant expression. */
|
||||
#if _GL_HAVE___TYPEOF__
|
||||
# define _GL_SIGNED_TYPE_OR_EXPR(t) _GL_TYPE_SIGNED (__typeof__ (t))
|
||||
#else
|
||||
# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
|
||||
#endif
|
||||
|
||||
/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
|
||||
A should not have side effects, and A's type should be an
|
||||
integer with minimum value MIN and maximum MAX. */
|
||||
#define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \
|
||||
((min) < 0 ? (a) < - (max) : 0 < (a))
|
||||
|
||||
/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
|
||||
(A, B, P) work when P is non-null. */
|
||||
#ifdef __EDG__
|
||||
/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned
|
||||
<https://bugs.gnu.org/53256>. */
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
|
||||
#elif defined __has_builtin
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
|
||||
/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
|
||||
see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
|
||||
#elif 7 <= __GNUC__
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
|
||||
#else
|
||||
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
|
||||
#endif
|
||||
|
||||
/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */
|
||||
#if defined __clang_major__ && __clang_major__ < 14
|
||||
/* Work around Clang bug <https://bugs.llvm.org/show_bug.cgi?id=16404>. */
|
||||
# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0
|
||||
#else
|
||||
# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW
|
||||
#endif
|
||||
|
||||
/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
|
||||
__builtin_sub_overflow_p and __builtin_mul_overflow_p. */
|
||||
#ifdef __EDG__
|
||||
/* In EDG-based compilers like ICC 2021.3 and earlier,
|
||||
__builtin_add_overflow_p etc. are not treated as integral constant
|
||||
expressions even when all arguments are. */
|
||||
# define _GL_HAS_BUILTIN_OVERFLOW_P 0
|
||||
#elif defined __has_builtin
|
||||
# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
|
||||
#else
|
||||
# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
|
||||
#endif
|
||||
|
||||
#if (!defined _GL_STDCKDINT_H && 202311 <= __STDC_VERSION__ \
|
||||
&& ! (_GL_HAS_BUILTIN_ADD_OVERFLOW && _GL_HAS_BUILTIN_MUL_OVERFLOW))
|
||||
# include <stdckdint.h>
|
||||
#endif
|
||||
|
||||
/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
|
||||
Return 1 if the result overflows. Arguments should not have side
|
||||
effects and A, B and *R can be of any integer type other than char,
|
||||
bool, a bit-precise integer type, or an enumeration type. */
|
||||
#if _GL_HAS_BUILTIN_ADD_OVERFLOW
|
||||
# define _GL_INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r)
|
||||
# define _GL_INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r)
|
||||
#elif defined ckd_add && defined ckd_sub && !defined _GL_STDCKDINT_H
|
||||
# define _GL_INT_ADD_WRAPV(a, b, r) ckd_add (r, + (a), + (b))
|
||||
# define _GL_INT_SUBTRACT_WRAPV(a, b, r) ckd_sub (r, + (a), + (b))
|
||||
#else
|
||||
# define _GL_INT_ADD_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)
|
||||
# define _GL_INT_SUBTRACT_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
|
||||
#endif
|
||||
#if _GL_HAS_BUILTIN_MUL_OVERFLOW
|
||||
# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
|
||||
|| (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \
|
||||
&& !defined __EDG__)
|
||||
# define _GL_INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
|
||||
# else
|
||||
/* Work around GCC bug 91450. */
|
||||
# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \
|
||||
((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && _GL_EXPR_SIGNED (a) && _GL_EXPR_SIGNED (b) \
|
||||
&& _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \
|
||||
? ((void) __builtin_mul_overflow (a, b, r), 1) \
|
||||
: __builtin_mul_overflow (a, b, r))
|
||||
# endif
|
||||
#elif defined ckd_mul && !defined _GL_STDCKDINT_H
|
||||
# define _GL_INT_MULTIPLY_WRAPV(a, b, r) ckd_mul (r, + (a), + (b))
|
||||
#else
|
||||
# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \
|
||||
_GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW)
|
||||
#endif
|
||||
|
||||
/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
|
||||
https://llvm.org/bugs/show_bug.cgi?id=25390
|
||||
For now, assume all versions of GCC-like compilers generate bogus
|
||||
warnings for _Generic. This matters only for compilers that
|
||||
lack relevant builtins. */
|
||||
#if __GNUC__ || defined __clang__
|
||||
# define _GL__GENERIC_BOGUS 1
|
||||
#else
|
||||
# define _GL__GENERIC_BOGUS 0
|
||||
#endif
|
||||
|
||||
/* Store the low-order bits of A <op> B into *R, where OP specifies
|
||||
the operation and OVERFLOW the overflow predicate. Return 1 if the
|
||||
result overflows. Arguments should not have side effects,
|
||||
and A, B and *R can be of any integer type other than char, bool, a
|
||||
bit-precise integer type, or an enumeration type. */
|
||||
#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
|
||||
# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
|
||||
(_Generic \
|
||||
(*(r), \
|
||||
signed char: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
signed char, SCHAR_MIN, SCHAR_MAX), \
|
||||
unsigned char: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned char, 0, UCHAR_MAX), \
|
||||
short int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
short int, SHRT_MIN, SHRT_MAX), \
|
||||
unsigned short int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned short int, 0, USHRT_MAX), \
|
||||
int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
int, INT_MIN, INT_MAX), \
|
||||
unsigned int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned int, 0, UINT_MAX), \
|
||||
long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX), \
|
||||
unsigned long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX), \
|
||||
long long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
long long int, LLONG_MIN, LLONG_MAX), \
|
||||
unsigned long long int: \
|
||||
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
unsigned long long int, 0, ULLONG_MAX)))
|
||||
#else
|
||||
/* Store the low-order bits of A <op> B into *R, where OP specifies
|
||||
the operation and OVERFLOW the overflow predicate. If *R is
|
||||
signed, its type is ST with bounds SMIN..SMAX; otherwise its type
|
||||
is UT with bounds U..UMAX. ST and UT are narrower than int.
|
||||
Return 1 if the result overflows. Arguments should not have side
|
||||
effects, and A, B and *R can be of any integer type other than
|
||||
char, bool, a bit-precise integer type, or an enumeration type. */
|
||||
# if _GL_HAVE___TYPEOF__
|
||||
# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
|
||||
(_GL_TYPE_SIGNED (__typeof__ (*(r))) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax))
|
||||
# else
|
||||
# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
|
||||
(overflow (a, b, smin, smax) \
|
||||
? (overflow (a, b, 0, umax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \
|
||||
: (overflow (a, b, 0, umax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0)))
|
||||
# endif
|
||||
|
||||
# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
|
||||
(sizeof *(r) == sizeof (signed char) \
|
||||
? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
|
||||
signed char, SCHAR_MIN, SCHAR_MAX, \
|
||||
unsigned char, UCHAR_MAX) \
|
||||
: sizeof *(r) == sizeof (short int) \
|
||||
? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
|
||||
short int, SHRT_MIN, SHRT_MAX, \
|
||||
unsigned short int, USHRT_MAX) \
|
||||
: sizeof *(r) == sizeof (int) \
|
||||
? (_GL_EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
int, INT_MIN, INT_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
|
||||
unsigned int, 0, UINT_MAX)) \
|
||||
: _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
|
||||
# ifdef LLONG_MAX
|
||||
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
|
||||
(sizeof *(r) == sizeof (long int) \
|
||||
? (_GL_EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX)) \
|
||||
: (_GL_EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
long long int, LLONG_MIN, LLONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
|
||||
unsigned long long int, 0, ULLONG_MAX)))
|
||||
# else
|
||||
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
|
||||
(_GL_EXPR_SIGNED (*(r)) \
|
||||
? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
long int, LONG_MIN, LONG_MAX) \
|
||||
: _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
|
||||
unsigned long int, 0, ULONG_MAX))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Store the low-order bits of A <op> B into *R, where the operation
|
||||
is given by OP. Use the unsigned type UT for calculation to avoid
|
||||
overflow problems. *R's type is T, with extrema TMIN and TMAX.
|
||||
T can be any signed integer type other than char, bool, a
|
||||
bit-precise integer type, or an enumeration type.
|
||||
Return 1 if the result overflows. */
|
||||
#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
|
||||
(overflow (a, b, tmin, tmax) \
|
||||
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
|
||||
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
|
||||
|
||||
/* Return 1 if the integer expressions A - B and -A would overflow,
|
||||
respectively. Arguments should not have side effects,
|
||||
and can be any signed integer type other than char, bool, a
|
||||
bit-precise integer type, or an enumeration type.
|
||||
These macros are tuned for their last input argument being a constant. */
|
||||
|
||||
#if _GL_HAS_BUILTIN_OVERFLOW_P
|
||||
# define _GL_INT_NEGATE_OVERFLOW(a) \
|
||||
__builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0)
|
||||
#else
|
||||
# define _GL_INT_NEGATE_OVERFLOW(a) \
|
||||
_GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
|
||||
#endif
|
||||
|
||||
/* Return the low-order bits of A <op> B, where the operation is given
|
||||
by OP. Use the unsigned type UT for calculation to avoid undefined
|
||||
behavior on signed integer overflow, and convert the result to type T.
|
||||
UT is at least as wide as T and is no narrower than unsigned int,
|
||||
T is two's complement, and there is no padding or trap representations.
|
||||
Assume that converting UT to T yields the low-order bits, as is
|
||||
done in all known two's-complement C compilers. E.g., see:
|
||||
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
|
||||
|
||||
According to the C standard, converting UT to T yields an
|
||||
implementation-defined result or signal for values outside T's
|
||||
range. However, code that works around this theoretical problem
|
||||
runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
|
||||
https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
|
||||
As the compiler bug is real, don't try to work around the
|
||||
theoretical problem. */
|
||||
|
||||
#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
|
||||
((t) ((ut) (a) op (ut) (b)))
|
||||
|
||||
/* Return true if the numeric values A + B, A - B, A * B fall outside
|
||||
the range TMIN..TMAX. Arguments should not have side effects
|
||||
and can be any integer type other than char, bool,
|
||||
a bit-precise integer type, or an enumeration type.
|
||||
TMIN should be signed and nonpositive.
|
||||
TMAX should be positive, and should be signed unless TMIN is zero. */
|
||||
#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
((b) < 0 \
|
||||
? (((tmin) \
|
||||
? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
|
||||
&& (a) < (tmin) - (b)) \
|
||||
: (a) <= -1 - (b)) \
|
||||
|| ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
|
||||
: (a) < 0 \
|
||||
? (((tmin) \
|
||||
? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
|
||||
&& (b) < (tmin) - (a)) \
|
||||
: (b) <= -1 - (a)) \
|
||||
|| ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \
|
||||
&& (tmax) < (a) + (b))) \
|
||||
: (tmax) < (b) || (tmax) - (b) < (a))
|
||||
#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
(((a) < 0) == ((b) < 0) \
|
||||
? ((a) < (b) \
|
||||
? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
|
||||
: (tmax) < (a) - (b)) \
|
||||
: (a) < 0 \
|
||||
? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
|
||||
|| (a) - (tmin) < (b)) \
|
||||
: ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
|
||||
&& _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
|
||||
&& (tmax) <= -1 - (b)) \
|
||||
|| (tmax) + (b) < (a)))
|
||||
#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \
|
||||
((b) < 0 \
|
||||
? ((a) < 0 \
|
||||
? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
|
||||
? (a) < (tmax) / (b) \
|
||||
: ((_GL_INT_NEGATE_OVERFLOW (b) \
|
||||
? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \
|
||||
: (tmax) / -(b)) \
|
||||
<= -1 - (a))) \
|
||||
: _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
|
||||
? (_GL_EXPR_SIGNED (a) \
|
||||
? 0 < (a) + (tmin) \
|
||||
: 0 < (a) && -1 - (tmin) < (a) - 1) \
|
||||
: (tmin) / (b) < (a)) \
|
||||
: (b) == 0 \
|
||||
? 0 \
|
||||
: ((a) < 0 \
|
||||
? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
|
||||
? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
|
||||
: (tmin) / (a) < (b)) \
|
||||
: (tmax) / (b) < (a)))
|
||||
|
||||
#endif /* _GL_INTPROPS_INTERNAL_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
/* stdckdint.h -- checked integer arithmetic
|
||||
|
||||
Copyright 2022-2024 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GL_STDCKDINT_H
|
||||
#define _GL_STDCKDINT_H
|
||||
|
||||
#include "intprops-internal.h"
|
||||
|
||||
/* Store into *R the low-order bits of A + B, A - B, A * B, respectively.
|
||||
Return 1 if the result overflows, 0 otherwise.
|
||||
A, B, and *R can have any integer type other than char, bool, a
|
||||
bit-precise integer type, or an enumeration type.
|
||||
|
||||
These are like the standard macros introduced in C23, except that
|
||||
arguments should not have side effects. */
|
||||
|
||||
#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r))
|
||||
#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r))
|
||||
#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r))
|
||||
|
||||
#endif /* _GL_STDCKDINT_H */
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* mksyntax.c - construct shell syntax table for fast char attribute lookup.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2000-2009,2012,2022-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2000-2009,2012,2022-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* sig.c - interface for shell signal handlers and signal initialization. */
|
||||
|
||||
/* Copyright (C) 1994-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* stringlib.c - Miscellaneous string functions. */
|
||||
|
||||
/* Copyright (C) 1996-2009,2022-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2009,2022-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+3
-2
@@ -377,11 +377,11 @@ 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=[ ]
|
||||
VAR=[]
|
||||
./printf7.sub: line 37: printf: 9223372036854775825: Result too large
|
||||
VAR=[X]
|
||||
./printf7.sub: line 43: printf: 21474836470: Result too large
|
||||
@@ -401,4 +401,5 @@ VAR=[]
|
||||
./printf7.sub: line 61: printf: 9223372036854775825: Result too large
|
||||
VAR=[X]
|
||||
XY
|
||||
./printf7.sub: line 71: printf: 9223372036854775825: Result too large
|
||||
XY
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* variables.c -- Functions for hacking shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* variables.h -- data structures for shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user