Compare commits

...
Author SHA1 Message Date
Adhemerval Zanella 2097879f6e math: Fix UB in ldbl-128ibm setpayload 2025-05-08 10:18:12 -03:00
Adhemerval Zanella d044eb659e math: Fix UB in ldbl-128ibm llroundl 2025-05-08 10:18:12 -03:00
Adhemerval Zanella 623bd741fb math: Fix UB in ldbl-128ibm lrintl 2025-05-08 10:18:09 -03:00
Adhemerval Zanella 673776c7be math: Fix UB in ldbl-128ibm llrintl 2025-05-08 09:34:19 -03:00
Adhemerval Zanella 5ae9c869b0 math: Fix UB in ldbl-128 __ieee754_rem_pio2l
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c:254:27 left shift of 325455441821696 by 23 cannot be represented in type 'long int'
2025-05-08 09:34:17 -03:00
Adhemerval Zanella 00411d0fad math: Fix UB in roundevenf_finite
On powerpc64le tanf tests show:

UBSAN: Undefined behaviour in ../sysdeps/ieee754/flt-32/math_config.h:105:11 passing zero to __builtin_ctz()
2025-05-08 09:34:15 -03:00
Adhemerval Zanella 8e684b1ddc math: Fix UB in ldbl-128ibm ilogb
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c:45:37 left shift of 4611686018427387904 by 1 cannot be represented in type 'long int'
2025-05-08 09:34:10 -03:00
Adhemerval Zanella 98b2b7be53 math: Fix UB in flt-32 rint
UBSAN: Undefined behaviour in ../sysdeps/ieee754/flt-32/s_rintf.c:46:4 left shift of 1 by 31 cannot be represented in type 'int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 0a933c9bf7 math: Fix UB in flt-32 nearbyint
UBSAN: Undefined behaviour in ../sysdeps/ieee754/flt-32/s_nearbyintf.c:53:4 left shift of 1 by 31 cannot be represented in type 'int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella ae54df4654 math: Fix UB on dbl-64 rint
UBSAN: Undefined behaviour in ../sysdeps/ieee754/dbl-64/s_rint.c:53:4 left shift of 1 by 63 cannot be represented in type 'long long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 48557d36a0 math: Fix UB in dbl-64 lrint
UBSAN: Undefined behaviour in ../sysdeps/ieee754/dbl-64/s_lrint.c:99:30 left shift of 1048576 by 11 cannot be represented in type 'long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 5b97637011 math: Fix UB in ldbl-128 setpayload
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_setpayloadl_main.c:47:34 shift exponent 16431 is too large for 64-bit type 'long long unsigned int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella b91a135500 math: Fix UB in flt-32 and dbl-64 significand
On x86_64:

$ math/test-float-significand
testing float (without inline functions)
UBSAN: Undefined behaviour in ./s_significand_template.c:31:45 negation of 2147483648 cannot be represented in type 'int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella d3c633b03d math: Fix UB in ldbl-96 sinl 2025-05-08 09:25:49 -03:00
Adhemerval Zanella 8175ef182f math: Fix UB in ldbl-128 powl
testing _Float128 (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/e_powl.c:439:11 left shift of 4294953849 by 16 cannot be represented in type 'int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella c1ffff3c53 math: Fix UB in ldbl-128 roundl
$ math/test-float128-cospi
testing _Float128 (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_roundl.c:75:30 left shift of 1 by 63 cannot be represented in type 'long long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 9dc7be063e math: Fix UB in __ieee754_rem_pio2l 2025-05-08 09:25:49 -03:00
Adhemerval Zanella ae41adf241 math: Fix UB in ldbl-128 rintl
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_rintl.c:60:4 left shift of 1 by 63 cannot be represented in type 'long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 9f65638ed1 math: Fix UB in ldbl-128 nearbyintl
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_nearbyintl.c:61:4 left shift of 1 by 63 cannot be represented in type 'long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 1d60cac326 math: Fix UB in lroundl
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_lroundl.c:72:32 left shift of 562949953421312 by 14 cannot be represented in type 'long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 712ff06cd6 math: Fix UB in ldbl-128 lrintl
$ math/test-float128-llrint

UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_llrintl.c:83:31 left shift of 281474976710656 by 15 cannot be represented in type 'long long int'
Aborted

UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_lrintl.c:111:30 left shift of 281474976710656 by 15 cannot be represented in type 'long int'
Aborted
2025-05-08 09:25:49 -03:00
Adhemerval Zanella c1540fcdde math: Fix UB in ldbl-128 llrintl
testing _Float128 (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_llrintl.c:83:31 left shift of 281474976710656 by 15 cannot be represented in type 'long long int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 8d83145f7f math: Fix UB on ldbl-128 fmodl 2025-05-08 09:25:49 -03:00
Adhemerval Zanella e5387c9493 math: Fix UB in ldbl-128 llroundl
Building with --enable-ubasn triggers:

$ math/test-float128-llround
testing _Float128 (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_llroundl.c:65:37 left shift of 562949953421312 by 14 cannot be represented in type 'long long int'
Aborted
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 4c3292f634 math: Fix UB in ldbl-96 setayloadl
The code can shift the 1ULL for value larger than 32 depending of
the exponent value.  Building with ubsan triggers:

$ math/test-ldouble-setpayload
testing long double (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/s_setpayloadl_main.c:48:32 shift exponent 16414 is too large for 32-bit type 'unsigned int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella ebaeeb8112 math: Fix UB on ldbl-96 remquol
Building with --enable-ubasn triggers:

$ math/test-ldouble-pow
testing long double (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/s_roundl.c:75:28 left shift of 1 by 31 cannot be represented in type 'int'
2025-05-08 09:25:49 -03:00
Adhemerval Zanella c949920ef6 math: Fix UB on lroundl
Building with --enable-ubasn triggers:

$ math/test-ldouble-pow
testing long double (without inline functions)
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/s_roundl.c:75:28 left shift of 1 by 31 cannot be represented in type 'int'
Aborted
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 51a2a92502 math: Fix UB on llroundl
Building with --enable-ubasn triggers:

UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/s_llroundl.c:70:25 left shift of 4294967296 by 31 cannot be represented in type 'long long int'

The right shift is undefined if value overflow, but code is assuming
an arithmetic shift.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella b7c497474b x86: Fix UB in isnanl
Building with --enable-ubasn triggers:

$ math/test-ldouble-roundeven
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/s_roundl.c:75:28 left shift of 1 by 31 cannot be represented in type 'int'

Also adds the inputs that triggers it on isnan testcase.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 258ea84448 x86: Fix UB in isinfl
Building with --enable-ubasn triggers:

$ math/test-ldouble-isinf
UBSAN: Undefined behaviour in ../sysdeps/x86/fpu/s_isinfl.c:25:8 negation of 2147483648 cannot be represented in type 'int'

Also move the isinfl implementation to sysdeps/x86 and remove the
sysdeps/x86_64 version.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 6deb970376 gmon: Fix UB in sprofil
UBSAN: Undefined behaviour in ../sysdeps/posix/sprofil.c:272:16 variable length array bound evaluates to non-positive value 0

Move the VLA to after the porfile stop condition (where size might
be zero).
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 6465987859 gmon: Fix UB in tst-sprofil.c
UBSAN: Undefined behaviour in tst-sprofil.c:140:6 unsigned integer overflow: 2432902008176640000 + 7812407968270641256 cannot be represened in type 'long int'

Use unsigned types for the fibonacci.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella da2b1f328e string: Remove UB on ffs/ffsll
Building with ubsan on 32 bit architecture, tst-ffs shows:

ffsll(0x4000000000000000) as expected 63
UBSAN: Undefined behaviour in ffsll.c:37:34 negation of 9223372036854775808 cannot be represented in type 'long long int'

Since the idea is to isolate the least significant bit, use unsigned
types.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 9ae7611c80 string: Fix UB on test-strrchr
UBSAN: Undefined behaviour in test-strrchr.c:100:35 unsigned integer overflow: 1804289383 * 846930886 cannot be represened in type 'long int'

Use int64_t operations instead.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 180cbc0cc9 sysvipc: Fix UB on time64 time support
Building with ubsan on 32 bit architecture without 64 bit time_t
as default, it shows:

UBSAN: Undefined behaviour in ../sysdeps/unix/sysv/linux/msgctl.c:180:45 left shift of 3935167480 by 32 cannot be represented in type 'long long int'

Add a new macro, IPC_HILO, to handle this transparently by using
unsigned shifts.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella fed92e28c5 nptl: xfail tst-cleanup2 when building with ubsan
The test explicit uses UB (sprintf (NULL, ...) to triggers a SIGSEGV
from libc and check with the pthread cleanup are correctly called.

With ubsan enable, it triggers:

UBSAN: Undefined behaviour in Xprintf_buffer_write.c:39:7 null pointer passed as argument 1, nonnull attribute declared at unknown:0:0

Which is a memcpy call with NULL argument.
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 967c9fd3eb stdio: Fix test-printf-ldbl-compat.c build with ubsan
On powercp64le with --enable-ubsan the build fails with:

In file included from ../include/bits/stdio2.h:1,
                 from ../libio/stdio.h:967,
                 from ../include/stdio.h:14,
                 from ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:21,
                 from ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ieee128.c:1:
In function ‘vfprintf’,
    inlined from ‘do_test_call_varg’ at ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:56:3:
../libio/bits/stdio2.h:166:10: error: null format string [-Werror=format-overflow=]
  166 |   return __vfprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘vsnprintf’,
    inlined from ‘do_test_call_varg’ at ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:68:3:
../libio/bits/stdio2.h:100:10: error: null format string [-Werror=format-truncation=]
  100 |   return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  101 |                                     __glibc_objsize (__s), __fmt, __ap);
      |                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘fprintf’,
    inlined from ‘do_test_call_rarg.constprop’ at ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:104:3:
../libio/bits/stdio2.h:111:10: error: null format string [-Werror=format-overflow=]
  111 |   return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  112 |                         __va_arg_pack ());
      |                         ~~~~~~~~~~~~~~~~~
In function ‘printf’,
    inlined from ‘do_test_call_rarg.constprop’ at ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:108:3:
../libio/bits/stdio2.h:118:10: error: null format string [-Werror=format-overflow=]
  118 |   return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘snprintf’,
    inlined from ‘do_test_call_rarg.constprop’ at ../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c:112:3:
../libio/bits/stdio2.h:68:10: error: null format string [-Werror=format-truncation=]
   68 |   return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   69 |                                    __glibc_objsize (__s), __fmt,
      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   70 |                                    __va_arg_pack ());
      |                                    ~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
2025-05-08 09:25:49 -03:00
Adhemerval Zanella 319de14379 stdio: Fix test-printf-chk-ldbl-compat build with ubsan
On powercp64le with --enable-ubsan the build fails with:

../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c: In function ‘do_test_call_varg’:
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:60:3: error: null format string [-Werror=format-overflow=]
   60 |   __vfprintf_chk (stream, 1, format, args);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:66:3: error: null format string [-Werror=format-overflow=]
   66 |   __vprintf_chk (1, format, args);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:72:3: error: null format string [-Werror=format-truncation=]
   72 |   __vsnprintf_chk (string, 79, 1, 127, format, args);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c: In function ‘do_test_call_rarg.constprop’:
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:111:3: error: null format string [-Werror=format-overflow=]
  111 |   __fprintf_chk (stdout, 1, format, ld, d);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:115:3: error: null format string [-Werror=format-overflow=]
  115 |   __printf_chk (1, format, ld, d);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c:119:3: error: null format string [-Werror=format-truncation=]
  119 |   __snprintf_chk (string, 79, 1, 127, format, ld, d);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-05-08 09:25:44 -03:00
Adhemerval Zanella 9b3a4a701d stdio-common: Fix UB on stdio-common/vfprintf-process-arg.c
On i686 debug/tst-sprintf-fortify-unchecked triggers:

UBSAN: Undefined behaviour in vfprintf-process-arg.c:41:57 negation of 9223372036854775808 cannot be represented in type 'long long int'
2025-05-08 09:25:44 -03:00
Adhemerval Zanella 612ba930aa nss: Fix tst-nss-hash UB
UBSAN: Undefined behaviour in tst-nss-hash.c:49:8 variable length array bound evaluates to non-positive value 0
2025-05-08 09:25:44 -03:00
Adhemerval Zanella 6a180670f8 nss: Fix UB on test-netdb
The gethostname is defined as not accepting NULL arguments, so
use a minimal size for initial call.
2025-05-08 09:25:44 -03:00
Adhemerval Zanella dc4b8962cb stdlib: Fix tst-makecontext3 UB
UBSAN: Undefined behaviour in tst-makecontext3.c:164:40 left shift of 1794341827 by 1 cannot be represented in type 'int'
2025-05-08 09:25:44 -03:00
Adhemerval Zanella 4b23aedb1b linux: Fix UB on tst-sched-setattr.c
UBSAN: Undefined behaviour in ../sysdeps/unix/sysv/linux/tst-sched_setattr.c:86:5 null pointer passed as argument 2, nonnull attribute declared at unknown:0:0
2025-05-08 09:25:39 -03:00
Adhemerval Zanella e4b9aa70a7 string: Fix UB on tesf-ffs
UBSAN: Undefined behaviour in test-ffs.c:48:3 left shift of 1 by 31 cannot be represented in type 'int'
2025-05-08 09:25:39 -03:00
Adhemerval Zanella 8ee1efc90d stdlib: Fix UB in tst-limits.c
UBSAN: Undefined behaviour in tst-limits.c:14:16 left shift of 1 by 63 cannot be represented in type 'long long int'
2025-05-08 09:25:39 -03:00
Adhemerval Zanella ba3e3ae80b stdlib: Adapt tst-environ to ubsan
The test explicits checks for passing a null argument to a
function with argument nonnull attribute.
2025-05-08 09:25:35 -03:00
Adhemerval Zanella afe9efb47c stdlib: Fix UB on strtod FIX 2025-05-07 14:21:21 -03:00
Adhemerval Zanella a48d71c81f math: Rewrite ldbl-128 isnan
With ubsan, test-float128-cabs triggers:

UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_isnanl.c:29:30 negation of 9223372036854775808 cannot be represented in type 'long int'

Rewrite with simplified version.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 61ad23190e math: Fix UB in float128 atan2
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/e_atan2l.c:68:9 unsigned integer overflow: 9223372036854775808 - 4611404543450677248 cannot be represened in type 'long int'
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 8beaca2512 math: Fix UB in test-canonical-ldbl-96.c
UBSAN: Undefined behaviour in ../sysdeps/ieee754/ldbl-96/test-canonical-ldbl-96.c:97:7 left shift of 1 by 31 cannot be represented in type 'int'
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 5d1b94809c sunrpc: Fix UB on xdr_hyper
ubsan triggers:

UBSAN: Undefined behaviour in xdr.c:262:28 left shift of 18446744073709551615 by 32 cannot be represented in type 'long int'

Fix by using unsigned type cast for left shift.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 766ed38275 string: Fix UB on gneric strncmp
Building with ubsan it triggers:

UBSAN: Undefined behaviour in ../string/strncmp.c:103:12 shift exponent 32 is too large for 32-bit type 'int'

Use an unsigned constant literal for MERGE, since op_t is defined
as unsigned.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 21d50c555f string: Fix UB on index_first/index_last
Building with ubsan the test-strcnmp triggers:

UBSAN: Undefined behaviour in ../sysdeps/generic/string-fzi.h:39:12 passing zero to __builtin_ctz()

Use stdbit.h functions instead of ctl/clz.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 278994710b string: Fix UB on generic strcmp
Building with ubsan it trigger:

UBSAN: Undefined behaviour in ../string/strcmp.c:92:12 shift exponent 32 is too large for 32-bit type 'int'

Use an unsigned constant literal for MERGE, since op_t is defined
as unsigned.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 925d03df27 string: Fix UB on gneric stpcpy
Building with ubsan it trigger:

UBSAN: Undefined behaviour in ../string/stpcpy.c:91:12 shift exponent 56 is too large for 32-bit type 'int'

Use an unsigned constant literal for MERGE, since op_t is defined
as unsigned.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 11aa5935bc stdlib: Fix UB on strtod
With glibc built with ubsan it triggers:

UBSAN: Undefined behaviour in strtod_l.c:1580:8 shift exponent 41 is too large for 32-bit type 'int'

Use the correct constant literal definition based on mp_limb_t size.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella c378eb4388 stdlib: Fix UB on erand48/jrand48
With glibc built with ubsan it triggers:

UBSAN: Undefined behaviour in jrand48_r.c:29:34 left shift of 41612 by 16 cannot be represented in type 'int'
UBSAN: Undefined behaviour in erand48_r.c:39:45 left shift of 3972 by 20 cannot be represented in type 'int'

Fix by casting to uint32_t for the shift operation.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella ea81e7d8c6 stdlib: Fix __libc_message_impl iovec size
The ubsan triggers an array item access error with stdlib/tst-bz20544.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella eadfcdb2b9 locale: Fix UB on VLA allocation
Both level 2 and level 3 sizes can be zero, which triggers a 0-size
VLA.  Reorganize the code to allocate the VLA iff sizes are positive.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella b5a09ebb3f libio: Fix UB __libio_codecvt_length
To avoid a 0 size VLA.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 43ba3b5c3a iconv: Fix UB on iconv/tst-translit-mchar
Building with ubsan, the test triggers:

UBSAN: Undefined behaviour in programs/locfile.c:598:3 null pointer passed as argument 2, nonnull attribute declared at unknown:0:0

The obstack_grow is only define for size > 0.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 63c5414e81 iconv: Fix UB on find_derivation
The cost addition might overflow since the default value is
LONG_INT.  Use wrap addition instead.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 78ddfecdd5 math: Fix UB in setayloadf
The code can shift the 1U for value larger than 31 depending of
the exponent value.  Add a check prior the shift.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella beb6d2de65 math: Fix UB in setayload
The code can shift the 1ULL for value larger than 63 depending of
the exponent value.  Add a check prior the shift.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella b26c1af4bd math: Remove UB from float128 ilogbf
The subnormal exponent calculation invokes UB by left shifting the
high or lower work.  Use unsigned values and stdc_leading_zeros
instead.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 31bc3437c9 powerpc: Use generic ilogb/ilogbf and refactor ilogbf128
The powerpc64 leverages the use of xsxexpdp and xsxexpqp for
for both ilogb/ilogbf for float, double, and float128 types.
However with the new generic ilogb/ilogbf, this is not really
a gain anymore.

On POWER9 with gcc-13, the xsxexpdp/xsxexpqp shows:

$ ./benchtests/bench-ilogb
  "ilogb": {
   "subnormal": {
    "duration": 5.08829e+08,
    "iterations": 4.4588e+07,
    "max": 18.761,
    "min": 6.7005,
    "mean": 11.4118
   },
   "normal": {
    "duration": 5.04674e+08,
    "iterations": 9.9596e+07,
    "max": 7.386,
    "min": 5.0505,
    "mean": 5.06722
   }
$ ./benchtests/bench-ilogbf
  "ilogbf": {
   "subnormal": {
    "duration": 5.04918e+08,
    "iterations": 9.8732e+07,
    "max": 7.1595,
    "min": 5.0475,
    "mean": 5.11402
   },
   "normal": {
    "duration": 5.04971e+08,
    "iterations": 9.8744e+07,
    "max": 7.771,
    "min": 5.048,
    "mean": 5.11394
   }
  }

While the new generic implementation shows:

$ ./benchtests/bench-ilogb
  "ilogb": {
   "subnormal": {
    "duration": 5.05389e+08,
    "iterations": 9.2644e+07,
    "max": 11.0355,
    "min": 5.4255,
    "mean": 5.45517
   },
   "normal": {
    "duration": 5.04667e+08,
    "iterations": 1.02388e+08,
    "max": 9.758,
    "min": 4.8945,
    "mean": 4.92897
   }
  }[azanella@cfarm135 powerpc64le-linux-gnu-power9-gcc13]$ ./benchtests/bench-ilogbf
  "ilogbf": {
   "subnormal": {
    "duration": 5.05409e+08,
    "iterations": 9.238e+07,
    "max": 7.69,
    "min": 5.442,
    "mean": 5.47098
   },
   "normal": {
    "duration": 5.0456e+08,
    "iterations": 1.02012e+08,
    "max": 6.84,
    "min": 4.922,
    "mean": 4.94609
   }
  }

The xsxexpdp/xsxexpqp also adds some extra code size overhead since it
uses the generic ilogb/ilogbf for 0/inf/NaN handling.  It is still kept
for float128, and this patch also optimizes it to avoid need to call
extra generic symbol to handle not number inputs.

On same hardware (POWER9/gcc-13) it shows the improvement:

* master

  "ilogbf128": {
   "subnormal": {
    "duration": 5.09608e+08,
    "iterations": 3.3092e+07,
    "max": 28.845,
    "min": 6.824,
    "mean": 15.3997
   },
   "normal": {
    "duration": 5.05148e+08,
    "iterations": 9.1692e+07,
    "max": 7.744,
    "min": 5.377,
    "mean": 5.50918
   }
  }

* patch:

  "ilogbf128": {
   "subnormal": {
    "duration": 5.0586e+08,
    "iterations": 8.388e+07,
    "max": 7.3295,
    "min": 5.952,
    "mean": 6.03076
   },
   "normal": {
    "duration": 5.04783e+08,
    "iterations": 9.6608e+07,
    "max": 8.9255,
    "min": 5.185,
    "mean": 5.22507
   }
  }

Checked on powerpc64le-linux-gnu and powerpc64le-linux-gnu targetting
POWER8 and with --disable-multi-arch on POWER9.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella d8e83281aa math: Remove i386 ilogb/ilogbf/llogb/llogbf
The new float and double implementation does not required an
extra function call and error handling uses math_err function,
which results in better performance on i386 as well.

With gcc-14 on AMD AMD Ryzen 9 5900X, master shows:

$ ./benchtests/bench-ilogb
  "ilogb": {
   "subnormal": {
    "duration": 3.68863e+09,
    "iterations": 1.72228e+08,
    "max": 89.2995,
    "min": 21.016,
    "mean": 21.4171
   },
   "normal": {
    "duration": 3.68878e+09,
    "iterations": 1.72948e+08,
    "max": 78.6065,
    "min": 21.127,
    "mean": 21.3288
   }
  }
$ ./benchtests/bench-ilogbf
  "ilogbf": {
   "subnormal": {
    "duration": 3.68835e+09,
    "iterations": 1.66716e+08,
    "max": 46.953,
    "min": 21.793,
    "mean": 22.1236
   },
   "normal": {
    "duration": 3.68784e+09,
    "iterations": 1.66168e+08,
    "max": 46.9715,
    "min": 21.904,
    "mean": 22.1935
   }
  }

While with this patch:

$ ./benchtests/bench-ilogb
  "ilogb": {
   "subnormal": {
    "duration": 3.68134e+09,
    "iterations": 4.17516e+08,
    "max": 32.5045,
    "min": 8.3245,
    "mean": 8.81723
   },
   "normal": {
    "duration": 3.6677e+09,
    "iterations": 6.79468e+08,
    "max": 50.9305,
    "min": 5.3465,
    "mean": 5.3979
   }
}
$ ./benchtests/bench-ilogbf
  "ilogbf": {
   "subnormal": {
    "duration": 3.67553e+09,
    "iterations": 5.11032e+08,
    "max": 35.927,
    "min": 7.0485,
    "mean": 7.19237
   },
   "normal": {
    "duration": 3.66877e+09,
    "iterations": 6.556e+08,
    "max": 26.3625,
    "min": 5.5315,
    "mean": 5.59605
   }
 }

Checked on i686-linux-gnu.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 2713ad3e90 math: Optimize float ilogb/llogb
It removes the wrapper by moving the error/EDOM handling to an
out-of-line implementation (__math_invalidf_i/__math_invalidf_li).
Also, __glibc_unlikely is used on errors case since it helps
code generation on recent gcc.

The code now builds to with gcc-14 on aarch64:

0000000000000000 <__ilogbf>:
   0:   1e260000        fmov    w0, s0
   4:   d3577801        ubfx    x1, x0, #23, #8
   8:   340000e1        cbz     w1, 24 <__ilogbf+0x24>
   c:   5101fc20        sub     w0, w1, #0x7f
  10:   7103fc3f        cmp     w1, #0xff
  14:   54000040        b.eq    1c <__ilogbf+0x1c>  // b.none
  18:   d65f03c0        ret
  1c:   12b00000        mov     w0, #0x7fffffff                 // #2147483647
  20:   14000000        b       0 <__math_invalidf_i>
  24:   53175800        lsl     w0, w0, #9
  28:   340000a0        cbz     w0, 3c <__ilogbf+0x3c>
  2c:   5ac01000        clz     w0, w0
  30:   12800fc1        mov     w1, #0xffffff81                 // #-127
  34:   4b000020        sub     w0, w1, w0
  38:   d65f03c0        ret
  3c:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  40:   14000000        b       0 <__math_invalidf_i>

Some ABI requires additional adjustments:

  * i386 and m68k requires to use the template version, since
    both provide __ieee754_ilogb implementatations.

  * loongarch uses a custom implementation as well.

  * powerpc64le also has a custom implementation for POWER9, which
    is also used for float and float128 version.  The generic
    e_ilogb.c implementation is moved on powerpc to keep the
    current code as-is.

Checked on aarch64-linux-gnu and x86_64-linux-gnu.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 4977d28d6b math: Remove UB and optimize double ilogbf
The subnormal exponent calculation invokes UB by left shifting the
signed expoenent to find the first leading bit.

The patch reimplements ilogb using the math_config.h macros and
uses the new stdbit.h function to simplify the subnormal handling.

On aarch64 it generates better code:

* master:

0000000000000000 <__ieee754_ilogbf>:
   0:   1e260000        fmov    w0, s0
   4:   12007801        and     w1, w0, #0x7fffffff
   8:   72091c1f        tst     w0, #0x7f800000
   c:   54000141        b.ne    34 <__ieee754_ilogbf+0x34>  // b.any
  10:   34000201        cbz     w1, 50 <__ieee754_ilogbf+0x50>
  14:   53185c21        lsl     w1, w1, #8
  18:   12800fa0        mov     w0, #0xffffff82                 // #-126
  1c:   d503201f        nop
  20:   531f7821        lsl     w1, w1, #1
  24:   51000400        sub     w0, w0, #0x1
  28:   7100003f        cmp     w1, #0x0
  2c:   54ffffac        b.gt    20 <__ieee754_ilogbf+0x20>
  30:   d65f03c0        ret
  34:   13177c20        asr     w0, w1, #23
  38:   12b01002        mov     w2, #0x7f7fffff                 // #2139095039
  3c:   5101fc00        sub     w0, w0, #0x7f
  40:   6b02003f        cmp     w1, w2
  44:   12b00001        mov     w1, #0x7fffffff                 // #2147483647
  48:   1a819000        csel    w0, w0, w1, ls  // ls = plast
  4c:   d65f03c0        ret
  50:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  54:   d65f03c0        ret

* patch:

0000000000000000 <__ieee754_ilogbf>:
   0:   1e260001        fmov    w1, s0
   4:   d3577820        ubfx    x0, x1, #23, #8
   8:   350000e0        cbnz    w0, 24 <__ieee754_ilogbf+0x24>
   c:   53175821        lsl     w1, w1, #9
  10:   34000141        cbz     w1, 38 <__ieee754_ilogbf+0x38>
  14:   5ac01021        clz     w1, w1
  18:   12800fc0        mov     w0, #0xffffff81                 // #-127
  1c:   4b010000        sub     w0, w0, w1
  20:   d65f03c0        ret
  24:   7103fc1f        cmp     w0, #0xff
  28:   5101fc00        sub     w0, w0, #0x7f
  2c:   12b00001        mov     w1, #0x7fffffff                 // #2147483647
  30:   1a811000        csel    w0, w0, w1, ne  // ne = any
  34:   d65f03c0        ret
  38:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  3c:   d65f03c0        ret

Other architecture with support for stdc_leading_zeros and/or
__builtin_clzll should have similar improvements.

Checked on aarch64-linux-gnu and x86_64-linux-gnu.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 46e4070d56 math: Optimize double ilogb/llogb
It removes the wrapper by moving the error/EDOM handling to an
out-of-line implementation (__math_invalid_i/__math_invalid_li).
Also, __glibc_unlikely is used on errors case since it helps
code generation on recent gcc.

The code now builds to with gcc-14 on aarch64:

0000000000000000 <__ilogb>:
   0:   9e660000        fmov    x0, d0
   4:   d374f801        ubfx    x1, x0, #52, #11
   8:   340000e1        cbz     w1, 24 <__ilogb+0x24>
   c:   510ffc20        sub     w0, w1, #0x3ff
  10:   711ffc3f        cmp     w1, #0x7ff
  14:   54000040        b.eq    1c <__ilogb+0x1c>  // b.none
  18:   d65f03c0        ret
  1c:   12b00000        mov     w0, #0x7fffffff                 // #2147483647
  20:   14000000        b       0 <__math_invalid_i>
  24:   d374cc00        lsl     x0, x0, #12
  28:   b40000a0        cbz     x0, 3c <__ilogb+0x3c>
  2c:   dac01000        clz     x0, x0
  30:   12807fc1        mov     w1, #0xfffffc01                 // #-1023
  34:   4b000020        sub     w0, w1, w0
  38:   d65f03c0        ret
  3c:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  40:   14000000        b       0 <__math_invalid_i>

Some ABI requires additional adjustments:

  * i386 and m68k requires to use the template version, since
    both provide __ieee754_ilogb implementatations.

  * loongarch uses a custom implementation as well.

  * powerpc64le also has a custom implementation for POWER9, which
    is also used for float and float128 version.  The generic
    e_ilogb.c implementation is moved on powerpc to keep the
    current code as-is.

Checked on aarch64-linux-gnu and x86_64-linux-gnu.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella ac05570fcd math: Remove UB and optimize double ilogb
The subnormal exponent calculation invokes UB by left shifting the
signed expoenent to find the first leading bit.  The implementation
also uses 32 bits operations, which generates suboptimal code in
64 bits architectures.

The patch reimplements ilogb using the math_config.h macros and
uses the new stdbit function to simplify the subnormal handling.

On aarch64 it generates better code:

* master:

0000000000000000 <__ieee754_ilogb>:
   0:   9e660000        fmov    x0, d0
   4:   d360fc02        lsr     x2, x0, #32
   8:   d360f801        ubfx    x1, x0, #32, #31
   c:   f26c285f        tst     x2, #0x7ff00000
  10:   540001a1        b.ne    44 <__ieee754_ilogb+0x44>  // b.any
  14:   2a000022        orr     w2, w1, w0
  18:   34000322        cbz     w2, 7c <__ieee754_ilogb+0x7c>
  1c:   35000221        cbnz    w1, 60 <__ieee754_ilogb+0x60>
  20:   2a0003e1        mov     w1, w0
  24:   7100001f        cmp     w0, #0x0
  28:   12808240        mov     w0, #0xfffffbed                 // #-1043
  2c:   540000ad        b.le    40 <__ieee754_ilogb+0x40>
  30:   531f7821        lsl     w1, w1, #1
  34:   51000400        sub     w0, w0, #0x1
  38:   7100003f        cmp     w1, #0x0
  3c:   54ffffac        b.gt    30 <__ieee754_ilogb+0x30>
  40:   d65f03c0        ret
  44:   13147c20        asr     w0, w1, #20
  48:   12b00202        mov     w2, #0x7fefffff                 // #2146435071
  4c:   510ffc00        sub     w0, w0, #0x3ff
  50:   6b02003f        cmp     w1, w2
  54:   12b00001        mov     w1, #0x7fffffff                 // #2147483647
  58:   1a819000        csel    w0, w0, w1, ls  // ls = plast
  5c:   d65f03c0        ret
  60:   53155021        lsl     w1, w1, #11
  64:   12807fa0        mov     w0, #0xfffffc02                 // #-1022
  68:   531f7821        lsl     w1, w1, #1
  6c:   51000400        sub     w0, w0, #0x1
  70:   7100003f        cmp     w1, #0x0
  74:   54ffffac        b.gt    68 <__ieee754_ilogb+0x68>
  78:   d65f03c0        ret
  7c:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  80:   d65f03c0        ret

* patch:

0000000000000000 <__ieee754_ilogb>:
   0:   9e660001        fmov    x1, d0
   4:   d374f820        ubfx    x0, x1, #52, #11
   8:   350000e0        cbnz    w0, 24 <__ieee754_ilogb+0x24>
   c:   d374cc21        lsl     x1, x1, #12
  10:   b4000141        cbz     x1, 38 <__ieee754_ilogb+0x38>
  14:   dac01021        clz     x1, x1
  18:   12807fc0        mov     w0, #0xfffffc01                 // #-1023
  1c:   4b010000        sub     w0, w0, w1
  20:   d65f03c0        ret
  24:   711ffc1f        cmp     w0, #0x7ff
  28:   510ffc00        sub     w0, w0, #0x3ff
  2c:   12b00001        mov     w1, #0x7fffffff                 // #2147483647
  30:   1a811000        csel    w0, w0, w1, ne  // ne = any
  34:   d65f03c0        ret
  38:   320107e0        mov     w0, #0x80000001                 // #-2147483647
  3c:   d65f03c0        ret

Other architecture with support for stdc_leading_zeros and/or
__builtin_clzll should have similar improvements.

Checked on aarch64-linux-gnu and x86_64-linux-gnu.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella b59c34e8f9 math: Fix UB in expm1
Building with ubsan triggers:

UBSAN: Undefined behaviour in ../sysdeps/ieee754/dbl-64/s_expm1.c:242:4 left shift of 4294967271 by 20 cannot be represented in type 'int'

Since at the time k is always positive, just cast to uint32_t.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 541a425162 aarch64: Fix UB in ifunc resolvers
When building with ubsan the ifunc resolvers triggers:

UBSAN: Undefined behaviour in ../sysdeps/aarch64/multiarch/memchr.c:34:1 left shift of 255 by 24 cannot be represented in type 'int'

The midr is defined as uint64_t, so use UINT64_C to define the masks
as well.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 0fd666fb4b malloc: Fix UB in malloc-debug
Multiple tests fail when malloc-debug is built with ubsan:

UBSAN: Undefined behaviour in malloc-debug.c:231:24 applying non-zero offset to a NULL pointer

The main issue is it tries to apply DUMPED_MAIN_ARENA_CHUNK or
for mem2chunk for NULL pointers.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 5197a3a2f7 stdio: Fix UB on snprintf
The elf/tst-dl-printf-static test when built with ubsan triggers:

UBSAN: Undefined behaviour in vfprintf-process-arg.c:58:36 negation of 9223372036854775808 cannot be represented in type 'long int'
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 7417fcf25a x86: Fix UB in x86_cpu_present/x86_cpu_active
The elf/tst-cpu-features-supports (and other tests that check for
CPU features) triggers the following issue with ubsan:

UBSAN: Undefined behaviour in ../sysdeps/x86/sys/platform/x86.h:59:42 left shift of 1 by 31 cannot be represented in type 'int'

The active_array is unsigned, so use an unsigned constant as well.
2025-05-07 14:21:21 -03:00
Adhemerval Zanella 8cc687cbac x86_64: Fix UB on plt rewrite
The elf/tst-plt-rewrite2 and elf/tst-plt-rewrite2 triggers the
failures with ubsan:

UBSAN: Undefined behaviour in ../sysdeps/x86_64/dl-machine.h:637:39 store to misaligned address 0x00007adb50230021 for type 'uint32_t'
2025-05-07 14:21:20 -03:00
Adhemerval Zanella 84c6cfb9b6 elf: Fix UB on _dl_early_allocate
The ubsan triggers on elf/tst-tls-allocation-failure-static-patched:

UBSAN: Undefined behaviour in ../sysdeps/unix/sysv/linux/dl-early_allocate.c:58:16 pointer index expression with base 0x0000555578792000 overflowed  to 0x8000555578792cc0

The function is called with a size larger than PTRDIFF_MAX, and
the addition than overflow.  Fix it by limiting the size up to
PTRDIFF_MAX, like all other malloc functions.
2025-05-07 14:21:20 -03:00
Adhemerval Zanella 5c94ce98f7 elf: Fix UB on _dl_map_object_from_fd
On 32-bit architecture ubsan triggers:

UBSAN: Undefined behaviour in dl-load.c:1345:54 pointer index expression with base 0x00612508 overflowed  to 0xf7c3a508

Use explicit uintptr_t operation instead.
2025-05-07 14:20:40 -03:00
Adhemerval Zanella dc48df09cd argp: Fix shift bug
From gnulib commits 06094e390b0 and 88033d3779362a.
2025-05-07 14:20:40 -03:00
Adhemerval Zanella d5c20a5be6 locale: Fix UB on add_locale_uint32_array
The ubsan triggers:

UBSAN: Undefined behaviour in programs/locfile.c:644:3 null pointer passed as argument 2, nonnull attribute declared at unknown:0:0

The obstack_grow is only required if there is extra elements to be
inserted (n_elems > 0).
2025-05-07 14:20:40 -03:00
Adhemerval Zanella 8e44f1e0b6 locale: Fix UB in elem_hash
The ubsan triggers:

UBSAN: Undefined behaviour in ./elem-hash.h:27:14 left shift of 360447856 by 3 cannot be represented in type 'int'

Using unsigned shift here zero fill like signed.
2025-05-07 14:20:40 -03:00
Adhemerval Zanella 4c7cf51f83 localte: Fix UB on collate_finish
The ubsan triggers:

UBSAN: Undefined behaviour in programs/ld-collate.c:1557:7 variable length array bound evaluates to non-positive value 0

nrules is guaranteed to be at most sizeof (((struct element_t *)
0)->used_in_level) * 8, so use it instead.
2025-05-07 14:20:20 -03:00
Adhemerval Zanella 915959c55d locale: Fix UB on insert_weights
The ubsan triggers:

UBSAN: Undefined behaviour in programs/ld-collate.c:862:5 null pointer passed as argument 2, nonnull attribute declared at unknown:0:0,

The memcpy is only requires if current 'weights' is nonnull, so
check it before calling it.
2025-05-07 10:41:34 -03:00
Adhemerval Zanella 59d419cf12 locate: Fix UB on memcpy call
The ubsan triggers:

UBSAN: Undefined behaviour in programs/charmap.c:908:2 null pointer passed as argument 2, nonnull attribute declared at unknown:0:0

This is not an isseu since size is always '0' in this case.
2025-05-07 10:41:34 -03:00
Richard Henderson 73c7242778 elf: Adjust DT_EXTRATAGIDX to avoid undefined shifts
When building with --enable-ubsan, the relocation code triggers:

UBSAN: Undefined behaviour in get-dynamic-info.h:56:30 left shift of 1879047925 by 1 cannot be represented in type 'int'

Originally from
https://sourceware.org/pipermail/libc-alpha/2015-August/063015.html.
2025-05-07 10:41:34 -03:00
Adhemerval Zanella 8ab4aa30e5 locale: Fix --enable-ubsan build failure on some ABIs
On mips, arc, powerpc, and s390 gcc 14 triggers the warning

In function ‘charmap_new_char’,
    inlined from ‘parse_charmap.isra’ at ../locale/programs/charmap.c:570:6:
../locale/programs/charmap.c:1017:32: error: ‘strncmp’ specified bound [2147483649, 4294967295] exceeds maximum object size 2147483647 [-Werror=stringop-overread]
 1017 |   if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../locale/programs/charmap.c:1017:32: error: ‘strncmp’ specified bound [2147483649, 4294967295] exceeds maximum object size 2147483647 [-Werror=stringop-overread]
cc1: all warnings being treated as errors

So move the case to an special function and disable the sanitizer.
2025-05-07 10:41:34 -03:00
Adhemerval Zanella f13e58f9b1 riscv: Fix --enable-ubsan build failure on riscv
With ubsan enable, libc.so fails to build with:

[...]linkobj/libc_pic.a(setcontext.os): in function `__start_context':
[...]sysdeps/unix/sysv/linux/riscv/setcontext.S:111:(.text+0xc0): relocation
truncated to fit: R_RISCV_JAL against symbol `__GI_exit' defined in .text section
in [...]/linkobj/libc_pic.a(exit.os)

Using 'call' instead of 'j' works regardless whether UBSAN.
2025-05-07 10:41:34 -03:00
Adhemerval Zanella aacf6238fb ubsan: Add initial support for -fsanitize=undefined
It is enabled through a new configure flag, --enable-ubsan, and
should be used for debugging and/or testing.  Not all ubsan handlers
are implemented, only those generated/required by glibc libraries,
programs, and tests.  Some extra handlers might be needed in future
C++ tests, and __ubsan_handle_dynamic_type_cache_miss also needs a
proper implementation.

The ubsan handlers are exported from ld.so since they are used on
all libraries and tests.  This might interfere with ubsan from
compiler runtime (when programs are built with libubsan in shared
mode), and this is completely untested and/or not supported at the
moment.

There is no support for the UBSAN_OPTIONS environment variable,
although some options are supported through glibc.ubsan tunables.
Currently, glibc.ubsan.halt_on_errors can be used to avoid
the process halt when any UB handler is issued.

Using -fsanitize=undefined enables some extra compiler checks that
are not easily enabled through the libc-diag.h macro.  For instance
on iconv/iconvconfig.c, gcc 14.2.1 shows:

In file included from ../include/bits/string_fortified.h:1,
                 from ../string/string.h:548,
                 from ../include/string.h:60,
                 from iconvconfig.c:32:
In function ‘strcpy’,
    inlined from ‘write_output’ at iconvconfig.c:1033:7,
    inlined from ‘main’ at iconvconfig.c:340:14:
../string/bits/string_fortified.h:81:10: error: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Werror=array-bounds=]
   81 |   return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest));
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../string/bits/string_fortified.h:81:10: error: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Werror=array-bounds=]
cc1: all warnings being treated as errors

Some extra code adjustments are required to fix such cases.

This preliminary support is still incomplete:

  * Not all targets are supported, nor have I checked the test suitei
    on all successful targets.  Also, I only checked with limited gcc
    versions (only gcc 14.2.1 and for some targets 15.0.0).

    Currently --enable-ubsan builds on Linux for aarch64, arm, hppa,
    i686, powerpc64, microblaze, mips64, loongarch64, sparc, s390x, and
    x86_64.

  * The instrumentation is disabled on rltd.c, although it is enabled
    on other loaders functions.

  * A lot of test cases show failures due to UB.

Also, gcc-14 triggers an ICE building math routines.  gcc-15
works correctly.
2025-05-07 10:41:28 -03:00
170 changed files with 2338 additions and 643 deletions
+9
View File
@@ -292,6 +292,15 @@ passed to 'configure'. For example:
Default is to disable fortification.
'--enable-ubsan'
Build the GNU C library with, along with tests, with the
-fsanitize=undefined compiler option. The compiler runtime is not
used, instead UBSAN functions called by the compiler instrumentation
is provided by glibc itself.
This is a debug/development option and the default is to disable
the instrumentation.
To build the library and related programs, type 'make'. This will
produce a lot of output, some of which may look like errors from 'make'
but aren't. Look for error messages from 'make' containing '***'.
+4 -2
View File
@@ -995,12 +995,14 @@ ifeq "$(strip $(+cflags))" ""
+cflags := $(default_cflags)
endif # $(+cflags) == ""
+ubsan-flags = $(cflags-enable-ubsan)
# Force building with -fno-common because hidden_def, compat_symbol
# and other constructs do not work for common symbols (and would
# otherwise require specifying __attribute__ ((nocommon)) on a
# case-by-case basis).
+cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags) \
$(+stack-protector) -fno-common
$(+stack-protector) $(+ubsan-flags) -fno-common
+gcc-nowarn := -w
# We must filter out elf because the early bootstrap of the dynamic loader
@@ -1046,7 +1048,7 @@ libio-include = -I$(..)libio
built-modules = iconvprogs iconvdata ldconfig libmemusage \
libpcprofile librpcsvc locale-programs \
memusagestat nonlib nscd extramodules libnldbl libsupport \
testsuite testsuite-internal
testsuite testsuite-internal libubsan
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
$(libof-$(<F)) \
+9 -6
View File
@@ -735,12 +735,15 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
}
}
else
/* A long option. We use shifts instead of masking for extracting
the user value in order to preserve the sign. */
err =
group_parse (&parser->groups[group_key - 1], &parser->state,
(opt << GROUP_BITS) >> GROUP_BITS,
parser->opt_data.optarg);
/* A long option. Preserve the sign in the user key, without
invoking undefined behavior. Assume two's complement. */
{
int user_key =
((opt & (1 << (USER_BITS - 1))) ? ~USER_MASK : 0) | (opt & USER_MASK);
err =
group_parse (&parser->groups[group_key - 1], &parser->state,
user_key, parser->opt_data.optarg);
}
if (err == EBADKEY)
/* At least currently, an option not recognized is an error in the
+3
View File
@@ -227,6 +227,9 @@
/* An integer used to scale the timeout of test programs. */
#define TIMEOUTFACTOR 1
/* Define if glibc should be build with -fsanitize=undefined. */
#undef ENABLE_UBSAN
/*
*/
Vendored
+30
View File
@@ -701,6 +701,8 @@ INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
base_machine
cflags_disable_ubsan
cflags_enable_ubsan
build_pt_chown
build_nscd
memory_tagging
@@ -820,6 +822,7 @@ enable_mathvec
enable_cet
enable_scv
enable_fortify_source
enable_ubsan
with_cpu
'
ac_precious_vars='build_alias
@@ -1505,6 +1508,7 @@ Optional Features:
Use -D_FORTIFY_SOURCE=[1|2|3] to control code
hardening, defaults to highest possible value
supported by the build compiler.
--enable-ubsan Build glibc with -fsanitize=undefined
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -4883,6 +4887,32 @@ case "$enable_fortify_source" in
*) as_fn_error $? "Not a valid argument for --enable-fortify-source: \"$enable_fortify_source\"" "$LINENO" 5;;
esac
cflags_enable_ubsan=
cflags_disable_ubsan=
# Check whether --enable-ubsan was given.
if test ${enable_ubsan+y}
then :
enableval=$enable_ubsan; enable_ubsan=$enableval
else case e in #(
e) enable_ubsan=no ;;
esac
fi
config_vars="$config_vars
enable-ubsan = $enable_ubsan"
if test "$enable_ubsan" = yes; then
printf "%s\n" "#define ENABLE_UBSAN 1" >>confdefs.h
cflags_enable_ubsan="-fsanitize=undefined"
cflags_disable_ubsan="-fno-sanitize=undefined"
fi
config_vars="$config_vars
cflags-enable-ubsan = $cflags_enable_ubsan"
config_vars="$config_vars
cflags-disable-ubsan = $cflags_disable_ubsan"
# We keep the original values in `$config_*' and never modify them, so we
# can write them unchanged into config.make. Everything else uses
# $machine, $vendor, and $os, and changes them whenever convenient.
+18
View File
@@ -440,6 +440,24 @@ case "$enable_fortify_source" in
*) AC_MSG_ERROR([Not a valid argument for --enable-fortify-source: "$enable_fortify_source"]);;
esac
cflags_enable_ubsan=
cflags_disable_ubsan=
AC_ARG_ENABLE(ubsan,
AS_HELP_STRING([--enable-ubsan],
[Build glibc with -fsanitize=undefined]),
[enable_ubsan=$enableval],
[enable_ubsan=no])
LIBC_CONFIG_VAR([enable-ubsan], [$enable_ubsan])
if test "$enable_ubsan" = yes; then
AC_DEFINE(ENABLE_UBSAN)
cflags_enable_ubsan="-fsanitize=undefined"
cflags_disable_ubsan="-fno-sanitize=undefined"
fi
AC_SUBST(cflags_enable_ubsan)
AC_SUBST(cflags_disable_ubsan)
LIBC_CONFIG_VAR([cflags-enable-ubsan], [$cflags_enable_ubsan])
LIBC_CONFIG_VAR([cflags-disable-ubsan], [$cflags_disable_ubsan])
# We keep the original values in `$config_*' and never modify them, so we
# can write them unchanged into config.make. Everything else uses
# $machine, $vendor, and $os, and changes them whenever convenient.
+30 -2
View File
@@ -48,9 +48,35 @@ routines = \
rtld_static_init \
# routines
ifeq (yes,$(enable-ubsan))
ubsan-routines = \
ubsan_error \
ubsan_handle_add_overflow \
ubsan_handle_builtin_unreachable \
ubsan_handle_divrem_overflow \
ubsan_handle_dynamic_type_cache_miss \
ubsan_handle_invalid_builtin \
ubsan_handle_load_invalid_value \
ubsan_handle_mul_overflow \
ubsan_handle_negate_overflow \
ubsan_handle_nonnull_arg \
ubsan_handle_nonnull_return_v1 \
ubsan_handle_out_of_bounds \
ubsan_handle_overflow \
ubsan_handle_pointer_overflow \
ubsan_handle_shift_out_of_bounds \
ubsan_handle_sub_overflow \
ubsan_handle_type_mismatch_v1 \
ubsan_handle_vla_bound_not_positive \
ubsan_val_to_string \
ubsan_vptr_type_cache \
# ubsan-routines
endif
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
dl-routines = \
$(ubsan-routines) \
dl-call-libc-early-init \
dl-call_fini \
dl-catch \
@@ -102,6 +128,8 @@ ifeq (yes,$(have-loop-to-function))
CFLAGS-dl-tunables.c += -fno-tree-loop-distribute-patterns
endif
CFLAGS-ubsan_handle_builtin_unreachable.c += -fno-builtin
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
# But they are absent from the shared libc, because that code is in ld.so.
elide-routines.os = \
@@ -160,7 +188,7 @@ CFLAGS-dl-minimal-malloc.op = $(no-stack-protector)
# On targets without __builtin_memset, rtld.c uses a hand-coded loop
# in _dl_start. Make sure this isn't turned into a call to regular memset.
ifeq (yes,$(have-loop-to-function))
CFLAGS-rtld.c += -fno-tree-loop-distribute-patterns
CFLAGS-rtld.c += -fno-tree-loop-distribute-patterns $(cflags-disable-ubsan)
endif
# Compile rtld itself without stack protection.
@@ -3434,7 +3462,7 @@ endif
# ld.so. The test is always run directly, not under the dynamic
# linker. It is necessary to minimize run-time dependencies, by
# disabling stack protection and unwinding.
CFLAGS-tst-nolink-libc.c += $(no-stack-protector) \
CFLAGS-tst-nolink-libc.c += $(no-stack-protector) $(cflags-disable-ubsan) \
-fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables
$(objpfx)tst-nolink-libc-1: $(objpfx)tst-nolink-libc.o $(objpfx)ld.so
$(LINK.o) -nostdlib -nostartfiles -o $@ $< \
+19
View File
@@ -79,5 +79,24 @@ ld {
# Set value of a tunable.
__tunable_is_initialized;
__tunable_get_val;
# -fsanitize=undefined support
__ubsan_handle_add_overflow;
__ubsan_handle_builtin_unreachable;
__ubsan_handle_divrem_overflow;
__ubsan_handle_dynamic_type_cache_miss;
__ubsan_handle_invalid_builtin;
__ubsan_handle_load_invalid_value;
__ubsan_handle_mul_overflow;
__ubsan_handle_negate_overflow;
__ubsan_handle_nonnull_arg;
__ubsan_handle_nonnull_return_v1;
__ubsan_handle_out_of_bounds;
__ubsan_handle_pointer_overflow;
__ubsan_handle_shift_out_of_bounds;
__ubsan_handle_sub_overflow;
__ubsan_handle_type_mismatch_v1;
__ubsan_handle_vla_bound_not_positive;
__ubsan_vptr_type_cache;
}
}
+1 -1
View File
@@ -1340,7 +1340,7 @@ cannot enable executable stack as shared object requires");
/* Adjust the address of the TLS initialization image. */
if (l->l_tls_initimage != NULL)
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
l->l_tls_initimage = (void*)((uintptr_t)l->l_tls_initimage + l->l_addr);
/* Process program headers again after load segments are mapped in
case processing requires accessing those segments. Scan program
+6
View File
@@ -269,6 +269,12 @@ _dl_debug_printf_c (const char *fmt, ...)
}
void
_dl_debug_vprintf_c (const char *fmt, va_list ap)
{
_dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, ap);
}
/* Write the given file descriptor. */
void
_dl_dprintf (int fd, const char *fmt, ...)
+9
View File
@@ -177,4 +177,13 @@ glibc {
default: 1048576
}
}
ubsan {
halt_on_errors {
type: INT_32
minval: 0
maxval: 1
default: 1
}
}
}
+1 -1
View File
@@ -995,7 +995,7 @@ typedef struct
range. Be compatible. */
#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
#define DT_FILTER 0x7fffffff /* Shared object to get values from */
#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
#define DT_EXTRATAGIDX(tag) (-((Elf32_Sword)((Elf32_Word)(tag) * 2) / 2 + 1))
#define DT_EXTRANUM 3
/* Values of `d_un.d_val' in the DT_FLAGS entry. */
+12
View File
@@ -24,6 +24,18 @@
extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr);
#ifdef ENABLE_UBSAN
void __GI___ubsan_handle_pointer_overflow (void *d, void *v, void *r)
{
return __ubsan_handle_pointer_overflow (d, v, r);
}
void __GI___ubsan_handle_type_mismatch_v1 (void *d, void *p)
{
return __ubsan_handle_type_mismatch_v1 (d, p);
}
#endif
static int
do_test (void)
{
+57
View File
@@ -0,0 +1,57 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ldsodefs.h>
#include <stdarg.h>
#include <unistd.h>
#include <abort-instr.h>
#include <ubsan.h>
#include <dl-tunables.h>
static void _Noreturn
ubsan_abort (void)
{
/* abort() pulls a lot of extra definition from libc (rwlock, signal
hanlding, pthread, etc.; so use a more simpler implementation for
now. */
raise (SIGABRT);
#ifdef ABORT_INSTRUCTION
ABORT_INSTRUCTION;
#endif
_exit (127);
}
void
__ubsan_error (const struct source_location *source,
const char *fmt,
...)
{
_dl_debug_printf_c ("UBSAN: Undefined behaviour in %s:%u:%u ",
get_source_location_file_name (source),
get_source_location_line (source),
get_source_location_column (source));
va_list ap;
va_start (ap, fmt);
_dl_debug_vprintf_c (fmt, ap);
va_end (ap);
if (TUNABLE_GET (glibc, ubsan, halt_on_errors, int32_t, NULL))
ubsan_abort ();
}
+26
View File
@@ -0,0 +1,26 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_add_overflow (void *_data, void *lhs, void *rhs)
{
__ubsan_handle_overflow (_data, lhs, rhs, "+");
}
rtld_hidden_def (__ubsan_handle_add_overflow)
+27
View File
@@ -0,0 +1,27 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_builtin_unreachable (void *_data)
{
struct unreachable_data *data = _data;
__ubsan_error (&data->location, "calling __builtin_unreachable()\n");
}
rtld_hidden_def (__ubsan_handle_builtin_unreachable)
+40
View File
@@ -0,0 +1,40 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs)
{
struct overflow_data *data = _data;
char lhs_str[UBSAN_VAL_STR_LEN];
char rhs_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (lhs_str, data->type, lhs);
__ubsan_val_to_string (rhs_str, data->type, rhs);
if (ubsan_type_is_signed (data->type)
&& ubsan_get_signed_val (data->type, rhs))
__ubsan_error (&data->location,
"division overflow: division of %s by -1 cannot be "
"represented in type %s\n",
rhs_str, data->type->type_name);
else
__ubsan_error (&data->location, "division by zero");
}
rtld_hidden_def (__ubsan_handle_divrem_overflow)
@@ -0,0 +1,28 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_dynamic_type_cache_miss (void *_data, void *pointer, void *hash)
{
/* TODO: this failure requires additional check to check for real
issues. Ignore for now. */
}
rtld_hidden_def (__ubsan_handle_dynamic_type_cache_miss)
+39
View File
@@ -0,0 +1,39 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_invalid_builtin (void *_data)
{
struct invalid_builtin_data *data = _data;
switch (data->kind)
{
case ubsan_builtin_check_kind_assume_passed_false:
__ubsan_error (&data->location,
"assumption is violated during execution\n");
break;
default:
__ubsan_error (&data->location,
"passing zero to __builtin_%s()\n",
data->kind == ubsan_builtin_check_kind_ctz_passed_zero
? "ctz" : "clz");
break;
}
}
rtld_hidden_def (__ubsan_handle_invalid_builtin)
+33
View File
@@ -0,0 +1,33 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_load_invalid_value (void *_data, void *val)
{
struct invalid_value_data *data = _data;
char val_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (val_str, data->type, val);
__ubsan_error (&data->location,
"load of value %s is not a valid value for type %s\n",
val_str,
data->type->type_name);
}
rtld_hidden_def (__ubsan_handle_load_invalid_value)
+26
View File
@@ -0,0 +1,26 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_mul_overflow (void *_data, void *lhs, void *rhs)
{
__ubsan_handle_overflow (_data, lhs, rhs, "*");
}
rtld_hidden_def (__ubsan_handle_mul_overflow)
+34
View File
@@ -0,0 +1,34 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_negate_overflow (void *_data, void *val)
{
struct overflow_data *data = _data;
char val_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string(val_str, data->type, val);
__ubsan_error (&data->location,
"negation of %s cannot be represented in type %s\n",
val_str,
data->type->type_name);
}
rtld_hidden_def (__ubsan_handle_negate_overflow)
+34
View File
@@ -0,0 +1,34 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_nonnull_arg (void *_data)
{
struct nonnull_arg_data *data = _data;
__ubsan_error (&data->location,
"null pointer passed as argument %u, nonnull attribute "
"declared at %s:%u:%u\n",
data->arg_index,
get_source_location_file_name (&data->attr_location),
get_source_location_line (&data->attr_location),
get_source_location_column (&data->attr_location));
}
rtld_hidden_def (__ubsan_handle_nonnull_arg)
+34
View File
@@ -0,0 +1,34 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_nonnull_return_v1 (void *_data, void *_location)
{
struct nonnull_return_data *data = _data;
struct source_location *location = _location;
__ubsan_error (&data->location,
"null pointer returned from function declared as "
"returns_nonnull: source %s:%u:%u\n",
get_source_location_file_name (location),
get_source_location_line (location),
get_source_location_column (location));
}
rtld_hidden_def (__ubsan_handle_nonnull_return_v1)
+34
View File
@@ -0,0 +1,34 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_out_of_bounds (void *_data, void *index)
{
struct out_of_bounds_data *data = _data;
char index_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (index_str, data->index_type, index);
__ubsan_error (&data->location,
"index %s is out of bounds for type %s\n",
index_str,
data->array_type->type_name);
}
rtld_hidden_def (__ubsan_handle_out_of_bounds)
+39
View File
@@ -0,0 +1,39 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include "ubsan.h"
void
__ubsan_handle_overflow (const struct overflow_data * data, void *lhs,
void *rhs, const char *op)
{
char lhs_str[UBSAN_VAL_STR_LEN];
char rhs_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (lhs_str, data->type, lhs);
__ubsan_val_to_string (rhs_str, data->type, rhs);
__ubsan_error (&data->location,
"%s integer overflow: %s %s %s cannot be represened in "
"type %s\n",
ubsan_type_is_signed (data->type) ? "signed" : "unsigned",
lhs_str,
op,
rhs_str,
data->type->type_name);
}
+62
View File
@@ -0,0 +1,62 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <ubsan.h>
void
__ubsan_handle_pointer_overflow (void *_data, void *val, void *result)
{
struct pointer_overflow_data *data = _data;
if (val == NULL && result == NULL)
__ubsan_error (&data->location,
"applying zero offset to a NULL pointer\n");
else if (val == NULL && result != NULL)
__ubsan_error (&data->location,
"applying non-zero offset to a NULL pointer\n");
else if (val != NULL && result == NULL)
__ubsan_error (&data->location,
"applying non-zero offset to non-NULL pointer 0x%0*lx "
"produced NULL pointer\n",
(int) sizeof (void *) * 2,
(unsigned long int) val);
else if (((intptr_t)val >= 0) == ((intptr_t)result >= 0))
{
const char *operation = ((uintptr_t)val > (uintptr_t)result)
? "addition" : "subtraction";
__ubsan_error (&data->location,
"%s of unsigned offset to 0x%0*lx overflowed "
"to 0x%0*lx\n",
operation,
(int) sizeof (void *) * 2,
(unsigned long int) val,
(int) sizeof (void *) * 2,
(unsigned long int) result);
}
else
__ubsan_error (&data->location,
"pointer index expression with base 0x%0*lx overflowed "
"to 0x%0*lx\n",
(int) sizeof (void *) * 2,
(unsigned long int) val,
(int) sizeof (void *) * 2,
(unsigned long int) result);
}
rtld_hidden_def (__ubsan_handle_pointer_overflow)
+53
View File
@@ -0,0 +1,53 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs)
{
struct shift_out_of_bounds_data *data = _data;
char lhs_str[UBSAN_VAL_STR_LEN];
char rhs_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (lhs_str, data->lhs_type, lhs);
__ubsan_val_to_string (rhs_str, data->rhs_type, rhs);
if (ubsan_val_is_negative (data->rhs_type, rhs))
__ubsan_error (&data->location,
"shift expoenent %s is negative\n",
rhs_str);
else if (ubsan_get_unsigned_val (data->rhs_type, rhs) >=
ubsan_type_bit_width (data->lhs_type))
__ubsan_error (&data->location,
"shift exponent %s is too large for %u-bit type %s\n",
rhs_str,
ubsan_type_bit_width (data->lhs_type),
data->lhs_type->type_name);
else if (ubsan_val_is_negative (data->lhs_type, lhs))
__ubsan_error (&data->location,
"left shift of negative valor %s\n",
lhs_str);
else
__ubsan_error (&data->location,
"left shift of %s by %s cannot be represented in type %s\n",
lhs_str,
rhs_str,
data->lhs_type->type_name);
}
rtld_hidden_def (__ubsan_handle_shift_out_of_bounds)
+26
View File
@@ -0,0 +1,26 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_sub_overflow (void *_data, void *lhs, void *rhs)
{
__ubsan_handle_overflow (_data, lhs, rhs, "-");
}
rtld_hidden_def (__ubsan_handle_sub_overflow)
+75
View File
@@ -0,0 +1,75 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
static const char *
type_check_to_string (unsigned char type_check_kind)
{
switch (type_check_kind)
{
case ubsan_type_check_load: return "load of";
case ubsan_type_check_store: return "store to";
case ubsan_type_check_reference_binding: return "reference binding to";
case ubsan_type_check_member_access: return "member access within";
case ubsan_type_check_member_call: return "member call on";
case ubsan_type_check_constructor_call: return "constructor call on";
case ubsan_type_check_downcast_pointer:
case ubsan_type_check_downcast_reference: return "downcast of";
case ubsan_type_check_upcast: return "upcast of";
case ubsan_type_check_upcast_to_virtual_base: return "cast to virtual base of";
case ubsan_type_check_nonnull_assign: return "_Nonnull binding to";
case ubsan_type_check_dynamic_operation: return "dynamic operation on";
default: return "unknown";
}
}
static inline bool
is_misaligned_pointer (const struct type_mismatch_data_v1 *data, void *ptr)
{
uintptr_t alignment = 1UL << data->log_alignment;
return (uintptr_t) ptr & (alignment - 1);
}
void
__ubsan_handle_type_mismatch_v1 (void *_data, void *ptr)
{
struct type_mismatch_data_v1 *data = _data;
if (data->type_check_kind == ubsan_type_check_nonnull_assign)
__ubsan_error (&data->location,
"%s null pointer of type %s\n",
type_check_to_string (data->type_check_kind),
data->type->type_name);
else if (is_misaligned_pointer (data, ptr))
__ubsan_error (&data->location,
"%s misaligned address 0x%0*lx for type %s\n",
type_check_to_string (data->type_check_kind),
(int) sizeof (void *) * 2,
(unsigned long int) ptr,
data->type->type_name);
else
__ubsan_error (&data->location,
"%s address 0x%0*lx with insufficient space for an "
"object of type %s\n",
type_check_to_string (data->type_check_kind),
(int) sizeof (void *) * 2,
(unsigned long int) ptr,
data->type->type_name);
}
rtld_hidden_def (__ubsan_handle_type_mismatch_v1)
+34
View File
@@ -0,0 +1,34 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
void
__ubsan_handle_vla_bound_not_positive (void *_data, void *bound)
{
struct vla_bound_not_positive_data *data = _data;
char bound_str[UBSAN_VAL_STR_LEN];
__ubsan_val_to_string (bound_str, data->type, bound);
__ubsan_error (&data->location,
"variable length array bound evaluates to "
"non-positive value %s\n",
bound_str);
}
rtld_hidden_def (__ubsan_handle_vla_bound_not_positive)
+189
View File
@@ -0,0 +1,189 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <intprops.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "ubsan.h"
static const char lower_digits[] = "0123456789";
enum { BASE = 10 };
static char *
utoa (unsigned long long int value, char *buf, size_t len)
{
if (len == 0)
return buf;
char *ptr = buf;
do
{
if (len-- == 0)
break;
*ptr++ = lower_digits[value % BASE];
value /= BASE;
}
while (value != 0);
char *r = ptr;
*ptr-- = '\0';
while (buf < ptr)
{
char t = *ptr;
*ptr-- = *buf;
*buf++ = t;
}
return r;
}
static char *
itoa (long long int value, char *buf, size_t len)
{
if (len == 0)
return buf;
bool isneg = value < 0;
char *ptr = buf;
do
{
if (len-- == 0)
break;
*ptr++ = lower_digits[abs (value % BASE)];
value /= BASE;
}
while (value != 0);
if (isneg)
*ptr++ = '-';
char *r = ptr;
*ptr-- = '\0';
while (buf < ptr)
{
char t = *ptr;
*ptr-- = *buf;
*buf++ = t;
}
return r;
}
static long long int
ubsan_val_to_ll (int width, void *value, long long int def)
{
switch (width)
{
case 8:
return (int8_t) (intptr_t) value;
case 16:
return (int16_t) (intptr_t) value;
case 32:
if (sizeof (value) >= sizeof (int32_t))
return (int32_t) (intptr_t) value;
else
return *(int32_t *) value;
case 64:
if (sizeof (value) >= sizeof (int64_t))
return (int64_t) (intptr_t) value;
else
return *(int64_t *) value;
default:
return def;
}
}
static unsigned long long int
ubsan_val_to_ull (int width, void *value, unsigned long long int def)
{
switch (width)
{
case 8:
return (uint8_t) (uintptr_t) value;
case 16:
return (uint16_t) (uintptr_t) value;
case 32:
if (sizeof (value) >= sizeof (uint32_t))
return (uint32_t) (uintptr_t) value;
else
return *(uint32_t *) value;
case 64:
if (sizeof (value) >= sizeof (uint64_t))
return (uint64_t) (uintptr_t) value;
else
return *(uint64_t *) value;
default:
return def;
}
}
static inline char *
add_string (char *str, const char *s, size_t *len)
{
char *endp = __stpncpy (str, s, *len);
*len -= endp - str;
return endp;
}
static inline char *
add_uint (char *str, unsigned long long int value, size_t *len)
{
char *endp = utoa (value, str, *len);
*len -= endp - str;
return endp;
}
void
__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN],
struct type_descriptor *type, void *value)
{
int width = ubsan_type_bit_width (type);
switch (type->type_kind)
{
case ubsan_type_kind_int:
if (ubsan_type_is_signed (type))
{
long long int v = ubsan_val_to_ll (width, value, 0);
itoa (v, str, UBSAN_VAL_STR_LEN);
}
else
{
unsigned long long int v = ubsan_val_to_ull (width, value, 0);
utoa (v, str, UBSAN_VAL_STR_LEN);
}
break;
case ubsan_type_kind_float:
{
char *endp = __stpcpy (str, "float size ");
utoa (width, endp, UBSAN_VAL_STR_LEN);
}
break;
default:
{
size_t size = UBSAN_VAL_STR_LEN;
char *endp = add_string (str, "kind ", &size);
endp = add_uint (endp, type->type_kind, &size);
endp = add_string (endp, " (width ", &size);
endp = add_uint (endp, width, &size);
add_string (endp, " )", &size);
}
break;
}
}
+21
View File
@@ -0,0 +1,21 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <ubsan.h>
unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE];
+3 -3
View File
@@ -45,8 +45,8 @@ unsigned int bshort[5][0x100 / sizeof (int)];
unsigned int blong[1][0x1000 / sizeof (int)];
unsigned int vlong[1][0x2000 / sizeof (int)];
static long int
fac (long int n)
static long unsigned int
fac (long int unsigned n)
{
if (n == 0)
return 1;
@@ -60,7 +60,7 @@ main (int argc, char **argv)
struct timeval tv, start;
struct prof prof[32];
double t_tick, delta;
long int sum = 0;
long int unsigned sum = 0;
int i, j;
for (i = 0; i < NELEMS (taddr); ++i)
+5 -2
View File
@@ -28,6 +28,7 @@
#include <dlfcn.h>
#include <gconv_int.h>
#include <pointer_guard.h>
#include <intprops.h>
/* Simple data structure for alias mapping. We have two names, `from'
@@ -507,8 +508,10 @@ find_derivation (const char *toset, const char *toset_expand,
const char *result_set = (strcmp (runp->to_string, "-") == 0
? (toset_expand ?: toset)
: runp->to_string);
int cost_hi = runp->cost_hi + current->cost_hi;
int cost_lo = runp->cost_lo + current->cost_lo;
int cost_hi, cost_lo;
INT_ADD_WRAPV (runp->cost_hi, current->cost_hi, &cost_hi);
INT_ADD_WRAPV (runp->cost_lo, current->cost_lo, &cost_lo);
struct derivation_step *step;
/* We managed to find a derivation. First see whether
+8 -5
View File
@@ -1019,11 +1019,14 @@ write_output (void)
/* Open the output file. */
if (output_file == NULL)
{
assert (GCONV_MODULES_CACHE[0] == '/');
strcpy (stpcpy (mempcpy (tmpfname, prefix, prefix_len),
GCONV_MODULES_CACHE),
".XXXXXX");
strcpy (mempcpy (finalname, prefix, prefix_len), GCONV_MODULES_CACHE);
snprintf (tmpfname, sizeof tmpfname, "%.*s%s.XXXXXX",
(int) prefix_len,
prefix,
GCONV_MODULES_CACHE);
snprintf (finalname, sizeof finalname, "%.*s%s",
(int) prefix_len,
prefix,
GCONV_MODULES_CACHE);
}
else
strcpy (mempcpy (tmpfname, output_file, output_file_len), ".XXXXXX");
+3
View File
@@ -65,5 +65,8 @@ libc_hidden_proto (_libc_intl_domainname)
# undef N_
# define N_(msgid) msgid
# undef gettext
# define gettext(msgid) (dgettext (NULL, msgid) ?: (char *)msgid)
# endif /* !_ISOMAC */
#endif
+6
View File
@@ -63,4 +63,10 @@ rtld_hidden_proto (__chk_fail)
# define __attribute_optimization_barrier__ __attribute__ ((noinline, noclone))
#endif
#ifdef ENABLE_UBSAN
# define __attribute_disable_ubsan__ __attribute__((no_sanitize("undefined")))
#else
# define __attribute_disable_ubsan__
#endif
#endif
+327
View File
@@ -0,0 +1,327 @@
/* Undefined Behavior Sanitizer support.
Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef __UBSAN_H__
#define __UBSAN_H__
#include <stdint.h>
#include <stdbool.h>
#include <endian.h>
#ifdef __SIZEOF_INT128__
typedef __int128 ubsan_s_max;
typedef unsigned __int128 ubsan_u_max;
#else
typedef int64_t ubsan_u_max;
typedef uint64_t ubsan_s_max;
#endif
#define REPORTED_BIT 31
#if (__WORDSIZE == 64 && BYTE_ORDER == BIG_ENDIAN)
# define COLUMN_MASK (~(1U << REPORTED_BIT))
# define LINE_MASK (~0U)
#else
# define COLUMN_MASK (~0U)
# define LINE_MASK (~(1U << REPORTED_BIT))
#endif
struct source_location
{
const char *file_name;
unsigned int line;
unsigned int column;
};
static inline const char *
get_source_location_file_name (const struct source_location *location)
{
return location->file_name ? location->file_name : "unknown";
}
static inline unsigned int
get_source_location_line (const struct source_location *location)
{
return location->line & LINE_MASK;
}
static inline unsigned int
get_source_location_column (const struct source_location *location)
{
return location->column & COLUMN_MASK;
}
struct nonnull_arg_data
{
struct source_location location;
struct source_location attr_location;
int arg_index;
};
struct type_descriptor
{
uint16_t type_kind;
uint16_t type_info;
char type_name[];
};
static inline bool
ubsan_type_is_signed (const struct type_descriptor *type)
{
return type->type_kind & 1;
}
static inline unsigned int
ubsan_type_bit_width (const struct type_descriptor *type)
{
return 1 << (type->type_info >> 1);
}
static inline bool
ubsan_is_inline_int (const struct type_descriptor *type)
{
unsigned int inline_bits = sizeof (unsigned long) * 8;
unsigned int bits = ubsan_type_bit_width (type);
return bits <= inline_bits;
}
static inline ubsan_s_max
ubsan_get_signed_val (const struct type_descriptor *type, void *val)
{
if (ubsan_is_inline_int (type))
{
unsigned int extra_bits = sizeof (ubsan_s_max) * 8
- ubsan_type_bit_width (type);
unsigned long ul_val = (unsigned long) val;
return ((ubsan_s_max) ul_val) << extra_bits >> extra_bits;
}
if (ubsan_type_bit_width (type) == 64)
return *(int64_t*) val;
return *(ubsan_s_max *) val;
}
static inline ubsan_u_max
ubsan_get_unsigned_val (const struct type_descriptor *type, void *val)
{
if (ubsan_is_inline_int (type))
return (unsigned long) val;
if (ubsan_type_bit_width (type) == 64)
return *(uint64_t*) val;
return *(ubsan_u_max *)val;
}
static inline bool
ubsan_val_is_negative (const struct type_descriptor *type, void *val)
{
return ubsan_type_is_signed (type) && ubsan_get_signed_val (type, val) < 0;
}
struct invalid_value_data
{
struct source_location location;
struct type_descriptor *type;
};
/* The type_mismatch_data_v1::type_check_kind */
enum
{
ubsan_type_check_load,
ubsan_type_check_store,
ubsan_type_check_reference_binding,
ubsan_type_check_member_access,
ubsan_type_check_member_call,
ubsan_type_check_constructor_call,
ubsan_type_check_downcast_pointer,
ubsan_type_check_downcast_reference,
ubsan_type_check_upcast,
ubsan_type_check_upcast_to_virtual_base,
ubsan_type_check_nonnull_assign,
ubsan_type_check_dynamic_operation
};
struct type_mismatch_data_v1
{
struct source_location location;
struct type_descriptor *type;
unsigned char log_alignment;
unsigned char type_check_kind;
};
struct pointer_overflow_data
{
struct source_location location;
};
struct overflow_data
{
struct source_location location;
struct type_descriptor *type;
};
struct out_of_bounds_data
{
struct source_location location;
struct type_descriptor *array_type;
struct type_descriptor *index_type;
};
struct shift_out_of_bounds_data
{
struct source_location location;
struct type_descriptor *lhs_type;
struct type_descriptor *rhs_type;
};
struct vla_bound_not_positive_data
{
struct source_location location;
struct type_descriptor *type;
};
struct unreachable_data
{
struct source_location location;
};
struct invalid_builtin_data
{
struct source_location location;
unsigned char kind;
};
struct nonnull_return_data
{
struct source_location location;
};
struct dynamic_type_cache_miss_data
{
struct source_location location;
struct type_descriptor *type;
void *info;
unsigned char kind;
};
enum
{
ubsan_type_kind_int = 0,
ubsan_type_kind_float = 1,
ubsan_type_unknown = 0xffff
};
enum
{
ubsan_builtin_check_kind_ctz_passed_zero,
ubsan_builtin_check_kind_clz_passed_zero,
ubsan_builtin_check_kind_assume_passed_false,
};
#define UBSAN_VAL_STR_LEN 32
void
__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN],
struct type_descriptor *type, void *value)
attribute_hidden;
#define UBSAN_VPTR_TYPE_CACHE_SIZE 128
extern unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE];
#if IS_IN(rtld)
# define ubsan_hidden attribute_hidden
#else
# define ubsan_hidden
#endif
void __ubsan_error (const struct source_location *source,
const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)))
attribute_hidden;
void __ubsan_handle_overflow (const struct overflow_data *, void *,
void *, const char *op)
attribute_hidden;
void __ubsan_handle_load_invalid_value (void *data, void *value)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_load_invalid_value)
void __ubsan_handle_type_mismatch_v1 (void *data, void *ptr)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_type_mismatch_v1)
void __ubsan_handle_pointer_overflow (void *data, void *val, void *result)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_pointer_overflow)
void __ubsan_handle_add_overflow (void *data, void *lhs, void *rhs)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_add_overflow)
void __ubsan_handle_sub_overflow (void *data, void *lhs, void *rhs)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_sub_overflow)
void __ubsan_handle_mul_overflow (void *data, void *lhs, void *rhs)
attribute_hidden;
rtld_hidden_proto (__ubsan_handle_mul_overflow)
void __ubsan_handle_out_of_bounds (void *data, void *index)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_out_of_bounds)
void __ubsan_handle_negate_overflow (void *data, void *val)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_negate_overflow)
void __ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_shift_out_of_bounds)
void __ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_divrem_overflow)
void __ubsan_handle_vla_bound_not_positive (void *data, void *bound)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_vla_bound_not_positive)
void __ubsan_handle_builtin_unreachable (void *data)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_builtin_unreachable)
void __ubsan_handle_invalid_builtin (void *data)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_invalid_builtin)
void __ubsan_handle_nonnull_arg (void *data)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_nonnull_arg);
void __ubsan_handle_nonnull_return_v1 (void *data, void *location)
ubsan_hidden;
rtld_hidden_proto (__ubsan_handle_nonnull_return_v1)
void __ubsan_handle_dynamic_type_cache_miss (void *, void *, void *);
rtld_hidden_proto (__ubsan_handle_dynamic_type_cache_miss)
#endif /* __UBSAN_H__ */
+3
View File
@@ -228,6 +228,9 @@ __libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
const char *from_start, const char *from_end,
size_t max)
{
if (max == 0)
return 0;
int result;
const unsigned char *cp = (const unsigned char *) from_start;
wchar_t to_buf[max];
+1 -1
View File
@@ -24,7 +24,7 @@ elem_hash (const char *str, int32_t n)
while (n-- > 0)
{
result <<= 3;
result = (uint32_t)result << 3;
result += *str++;
}
+40 -34
View File
@@ -212,58 +212,64 @@ static void
CONCAT(add_locale_,TABLE) (struct locale_file *file, struct TABLE *t)
{
size_t i, j, k;
uint32_t reorder3[t->level3_size];
uint32_t reorder2[t->level2_size];
uint32_t level2_offset, level3_offset, last_offset;
/* Uniquify level3 blocks. */
k = 0;
for (j = 0; j < t->level3_size; j++)
if (t->level3_size > 0)
{
for (i = 0; i < k; i++)
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (ELEMENT)) == 0)
break;
/* Relocate block j to block i. */
reorder3[j] = i;
if (i == k)
uint32_t reorder3[t->level3_size];
for (j = 0; j < t->level3_size; j++)
{
if (i != j)
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (ELEMENT));
k++;
for (i = 0; i < k; i++)
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (ELEMENT)) == 0)
break;
/* Relocate block j to block i. */
reorder3[j] = i;
if (i == k)
{
if (i != j)
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (ELEMENT));
k++;
}
}
for (i = 0; i < (t->level2_size << t->q); i++)
if (t->level2[i] != EMPTY)
t->level2[i] = reorder3[t->level2[i]];
}
t->level3_size = k;
for (i = 0; i < (t->level2_size << t->q); i++)
if (t->level2[i] != EMPTY)
t->level2[i] = reorder3[t->level2[i]];
/* Uniquify level2 blocks. */
k = 0;
for (j = 0; j < t->level2_size; j++)
if (t->level2_size > 0)
{
for (i = 0; i < k; i++)
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder2[j] = i;
if (i == k)
uint32_t reorder2[t->level2_size];
for (j = 0; j < t->level2_size; j++)
{
if (i != j)
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t));
k++;
for (i = 0; i < k; i++)
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder2[j] = i;
if (i == k)
{
if (i != j)
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t));
k++;
}
}
for (i = 0; i < t->level1_size; i++)
if (t->level1[i] != EMPTY)
t->level1[i] = reorder2[t->level1[i]];
}
t->level2_size = k;
for (i = 0; i < t->level1_size; i++)
if (t->level1[i] != EMPTY)
t->level1[i] = reorder2[t->level1[i]];
/* Create and fill the resulting compressed representation. */
last_offset =
5 * sizeof (uint32_t)
+4 -4
View File
@@ -904,9 +904,9 @@ number of bytes for byte sequence of beginning and end of range not the same: %d
(struct width_rule *) obstack_alloc (&result->mem_pool,
(new_size
* sizeof (struct width_rule)));
memcpy (new_rules, result->width_rules,
result->nwidth_rules_max * sizeof (struct width_rule));
if (result->width_rules != NULL)
memcpy (new_rules, result->width_rules,
result->nwidth_rules_max * sizeof (struct width_rule));
result->width_rules = new_rules;
result->nwidth_rules_max = new_size;
@@ -1014,7 +1014,7 @@ hexadecimal range format should use only capital characters"));
prefix_len = (cp - from) + 1;
if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
if (check_illegal_range (cp, from, len1, to, prefix_len))
goto illegal_range;
errno = 0;
+7
View File
@@ -62,6 +62,13 @@ struct charseq
unsigned char bytes[];
};
static inline bool
__attribute_disable_ubsan__
check_illegal_range (const char *cp, const char *from, size_t len1,
const char *to, size_t prefix_len)
{
return cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0;
}
/* True if the encoding is not ASCII compatible. */
extern bool enc_not_ascii_compatible;
+3 -2
View File
@@ -858,7 +858,8 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
max += 10;
newp = (struct element_t **)
alloca (max * sizeof (struct element_t *));
memcpy (newp, weights, cnt * sizeof (struct element_t *));
if (weights != NULL)
memcpy (newp, weights, cnt * sizeof (struct element_t *));
weights = newp;
}
weights[cnt++] = charelem;
@@ -1553,7 +1554,7 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
The multibyte case is easy. We simply sort into an array with
256 elements. */
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
int mbact[nrules];
int mbact[sizeof (((struct element_t *)0)->used_in_level) * 8];
int wcact;
int mbseqact;
int wcseqact;
+40 -34
View File
@@ -3423,58 +3423,64 @@ static void
add_locale_wctype_table (struct locale_file *file, struct wctype_table *t)
{
size_t i, j, k;
uint32_t reorder3[t->level3_size];
uint32_t reorder2[t->level2_size];
uint32_t level2_offset, level3_offset;
/* Uniquify level3 blocks. */
k = 0;
for (j = 0; j < t->level3_size; j++)
if (t->level3_size > 0)
{
for (i = 0; i < k; i++)
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder3[j] = i;
if (i == k)
uint32_t reorder3[t->level3_size];
for (j = 0; j < t->level3_size; j++)
{
if (i != j)
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (uint32_t));
k++;
for (i = 0; i < k; i++)
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder3[j] = i;
if (i == k)
{
if (i != j)
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
(1 << t->p) * sizeof (uint32_t));
k++;
}
}
for (i = 0; i < (t->level2_size << t->q); i++)
if (t->level2[i] != EMPTY)
t->level2[i] = reorder3[t->level2[i]];
}
t->level3_size = k;
for (i = 0; i < (t->level2_size << t->q); i++)
if (t->level2[i] != EMPTY)
t->level2[i] = reorder3[t->level2[i]];
/* Uniquify level2 blocks. */
k = 0;
for (j = 0; j < t->level2_size; j++)
if (t->level2_size > 0)
{
for (i = 0; i < k; i++)
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder2[j] = i;
if (i == k)
uint32_t reorder2[t->level2_size];
for (j = 0; j < t->level2_size; j++)
{
if (i != j)
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t));
k++;
for (i = 0; i < k; i++)
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t)) == 0)
break;
/* Relocate block j to block i. */
reorder2[j] = i;
if (i == k)
{
if (i != j)
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
(1 << t->q) * sizeof (uint32_t));
k++;
}
}
for (i = 0; i < t->level1_size; i++)
if (t->level1[i] != EMPTY)
t->level1[i] = reorder2[t->level1[i]];
}
t->level2_size = k;
for (i = 0; i < t->level1_size; i++)
if (t->level1[i] != EMPTY)
t->level1[i] = reorder2[t->level1[i]];
t->result_size =
5 * sizeof (uint32_t)
+ t->level1_size * sizeof (uint32_t)
+4
View File
@@ -595,6 +595,8 @@ void
add_locale_raw_data (struct locale_file *file, const void *data, size_t size)
{
record_offset (file);
if (size == 0)
return;
obstack_grow (&file->data, data, size);
}
@@ -641,6 +643,8 @@ add_locale_uint32_array (struct locale_file *file,
{
align_locale_data (file, LOCFILE_ALIGN);
record_offset (file);
if (n_elems == 0)
return;
obstack_grow (&file->data, data, n_elems * sizeof (uint32_t));
maybe_swap_uint32_obstack (&file->data, n_elems);
}
+2 -1
View File
@@ -124,7 +124,8 @@ extern void end_locale_structure (struct locale_file *file);
extern void start_locale_prelude (struct locale_file *file);
extern void end_locale_prelude (struct locale_file *file);
extern void write_locale_data (const char *output_path, int catidx,
const char *category, struct locale_file *file);
const char *category, struct locale_file *file)
__attribute__ ((nonnull (1, 3, 4)));
/* Entrypoints for the parsers of the individual categories. */
+1 -1
View File
@@ -433,7 +433,7 @@ hexadecimal range format should use only capital characters"));
prefix_len = (cp - from) + 1;
if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
if (check_illegal_range (cp, from, len1, to, prefix_len))
goto invalid_range;
errno = 0;
+2 -2
View File
@@ -202,7 +202,7 @@ __debug_free (void *mem)
if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
mem = free_mcheck (mem);
if (DUMPED_MAIN_ARENA_CHUNK (mem2chunk (mem)))
if (mem != NULL && DUMPED_MAIN_ARENA_CHUNK (mem2chunk (mem)))
/* Do nothing. */;
else if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
free_check (mem);
@@ -227,7 +227,7 @@ __debug_realloc (void *oldmem, size_t bytes)
if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
|| !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim)))
{
mchunkptr oldp = mem2chunk (oldmem);
mchunkptr oldp = oldmem != NULL ? mem2chunk (oldmem) : NULL;
/* If this is a faked mmapped chunk from the dumped main arena,
always make a copy (and do not free the old chunk). */
+8
View File
@@ -320,6 +320,14 @@ If not provided, @option{LEVEL} defaults to highest possible value supported by
the build compiler.
Default is to disable fortification.
@item --enable-ubsan
Build @theglibc{}, along with tests, with the @code{-fsanitize=undefined}
compiler option. The compiler runtime is not used, instead UBSAN functions
called by the compiler instrumentation is provided by glibc itself.
This is a debug/development option and the default is to disable
the instrumentation.
@end table
To build the library and related programs, type @code{make}. This will
+2
View File
@@ -23,6 +23,8 @@ static const struct test_f_i_data isnan_test_data[] =
TEST_f_b (isnan, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, 10, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, 4294967297, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, -4294967297, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, min_subnorm_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, -min_subnorm_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_b (isnan, min_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+2 -1
View File
@@ -28,7 +28,8 @@
FLOAT
M_DECL_FUNC (__significand) (FLOAT x)
{
return M_SUF (__ieee754_scalb) (x,(FLOAT) - M_SUF (__ilogb) (x));
int ex = - (unsigned int) M_SUF (__ilogb) (x);
return M_SUF (__ieee754_scalb) (x,(FLOAT) ex);
}
/* Don't provide _FloatN aliases for significand which was originally
+9
View File
@@ -41,6 +41,9 @@
#include <support/support.h>
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
#define assume_nonnull(x) assume ((x) != NULL)
/*
The following define is necessary for glibc 2.0.6
*/
@@ -175,11 +178,17 @@ test_hosts (void)
hptr1 = gethostbyname2 ("localhost", AF_INET);
output_hostent ("gethostbyname2 (\"localhost\", AF_INET)", hptr1);
name = xmalloc (2);
namelen += 2;
while (gethostname (name, namelen) < 0 && errno == ENAMETOOLONG)
{
namelen += 2; /* tiny increments to test a lot */
name = xrealloc (name, namelen);
}
assume_nonnull (name);
if (gethostname (name, namelen) == 0)
{
printf ("Hostname: %s\n", name);
+1 -1
View File
@@ -62,7 +62,7 @@ static int
do_test (void)
{
size_t i, j;
for (i = 0; i < 100; ++i)
for (i = 1; i < 100; ++i)
{
for (j = 0; j < 8192; ++j)
{
+3 -2
View File
@@ -1397,9 +1397,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (s.length < need
&& !scratch_buffer_set_array_size (&s, need, 1))
goto memory_error;
char *p = mempcpy (s.data, directory, dirlen);
char *pdata = s.data;
char *p = mempcpy (pdata, directory, dirlen);
*p = '/';
p += p[-1] != '/';
p += pdata[p - pdata - 1] != '/';
memcpy (p, d.name, namelen + 1);
if (! is_dir (s.data, flags, pglob))
continue;
+1 -10
View File
@@ -801,7 +801,7 @@ reopen (res_state statp, int *terrno, int ns)
{
if (EXT(statp).nssocks[ns] == -1) {
struct sockaddr *nsap = __res_get_nsaddr (statp, ns);
socklen_t slen;
socklen_t slen = 0;
/* only try IPv6 if IPv6 NS and if not failed before */
if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
@@ -845,16 +845,7 @@ reopen (res_state statp, int *terrno, int ns)
* error message is received. We can thus detect
* the absence of a nameserver without timing out.
*/
/* With GCC 5.3 when compiling with -Os the compiler
emits a warning that slen may be used uninitialized,
but that is never true. Both slen and
EXT(statp).nssocks[ns] are initialized together or
the function return -1 before control flow reaches
the call to connect with slen. */
DIAG_PUSH_NEEDS_COMMENT;
DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
if (__connect (EXT (statp).nssocks[ns], nsap, slen) < 0) {
DIAG_POP_NEEDS_COMMENT;
__res_iclose(statp, false);
return (0);
}
+4
View File
@@ -21,6 +21,9 @@
#include <support/next_to_fault.h>
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
#define assume_nonnull(x) assume ((x) != NULL)
#define SPRINTF_BUFFER_SIZE 65536
static struct support_next_to_fault ntf;
@@ -42,6 +45,7 @@ printf_under_test_fini (void)
({ \
__label__ out; \
char *str = ntf.buffer; \
assume_nonnull (str); \
int result; \
\
result = sprintf (str, __VA_ARGS__); \
+4
View File
@@ -22,6 +22,9 @@
#include <support/next_to_fault.h>
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
#define assume_nonnull(x) assume ((x) != NULL)
#define SPRINTF_BUFFER_SIZE 65536
static struct support_next_to_fault ntf;
@@ -43,6 +46,7 @@ static int
printf_under_test (const char *restrict fmt, ...)
{
char *str = ntf.buffer;
assume_nonnull (str);
va_list ap;
int result;
+4 -2
View File
@@ -38,7 +38,8 @@ LABEL (form_integer):
{
long long int signed_number = process_arg_long_long_int ();
is_negative = signed_number < 0;
number.longlong = is_negative ? (- signed_number) : signed_number;
number.longlong = is_negative ? (- (unsigned long long) signed_number)
: signed_number;
goto LABEL (longlong_number);
}
@@ -55,7 +56,8 @@ LABEL (form_integer):
signed_number = (short int) process_arg_unsigned_int ();
is_negative = signed_number < 0;
number.word = is_negative ? (- signed_number) : signed_number;
number.word = is_negative ? (- (unsigned long) signed_number)
: signed_number;
goto LABEL (number);
}
+2 -1
View File
@@ -36,7 +36,8 @@ __erand48_r (unsigned short int xsubi[3], struct drand48_data *buffer,
temp.ieee.negative = 0;
temp.ieee.exponent = IEEE754_DOUBLE_BIAS;
temp.ieee.mantissa0 = (xsubi[2] << 4) | (xsubi[1] >> 12);
temp.ieee.mantissa1 = ((xsubi[1] & 0xfff) << 20) | (xsubi[0] << 4);
temp.ieee.mantissa1 = (((uint32_t)xsubi[1] & 0xfff) << 20)
| ((uint32_t)xsubi[0] << 4);
/* Please note the lower 4 bits of mantissa1 are always 0. */
*result = temp.d - 1.0;
+1 -1
View File
@@ -26,7 +26,7 @@ __jrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer,
return -1;
/* Store the result. */
*result = (int32_t) ((xsubi[2] << 16) | xsubi[1]);
*result = (int32_t) (((uint32_t)xsubi[2] << 16) | (uint32_t)xsubi[1]);
return 0;
}
+2 -7
View File
@@ -44,13 +44,8 @@ __BEGIN_DECLS
/* Use __pacify_uint16 (N) instead of (uint16_t) (N) when the cast is helpful
only to pacify older GCC (e.g., GCC 10 -Wconversion) or non-GCC (e.g
clang -Wimplicit-int-conversion). */
#if __GNUC_PREREQ (11, 0)
# define __pacify_uint8(n) (n)
# define __pacify_uint16(n) (n)
#else
# define __pacify_uint8(n) ((uint8_t) (n))
# define __pacify_uint16(n) ((uint16_t) (n))
#endif
#define __pacify_uint8(n) ((uint8_t) (n))
#define __pacify_uint16(n) ((uint16_t) (n))
/* Count leading zeros. */
extern unsigned int stdc_leading_zeros_uc (unsigned char __x)
+5 -2
View File
@@ -150,9 +150,11 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
#if BITS_PER_MP_LIMB == 32
# define MAX_DIG_PER_LIMB 9
# define MAX_FAC_PER_LIMB 1000000000UL
# define SHIFT_CTE(N) N ## U
#elif BITS_PER_MP_LIMB == 64
# define MAX_DIG_PER_LIMB 19
# define MAX_FAC_PER_LIMB 10000000000000000000ULL
# define SHIFT_CTE(N) N ## UL
#else
# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
#endif
@@ -1572,12 +1574,13 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group,
{
if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
BITS_PER_MP_LIMB, 0);
BITS_PER_MP_LIMB, SHIFT_CTE (0));
else
{
used = MANT_DIG - bits;
if (used > 0)
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used,
SHIFT_CTE (0));
}
bits += BITS_PER_MP_LIMB;
}
+19 -11
View File
@@ -26,6 +26,24 @@
char putenv_val[100] = VAR "=some longer value";
static int
__attribute_disable_ubsan__
check_null_argument (void)
{
/* This deliberately tests supplying a null pointer to a function whose
argument is marked __attribute__ ((nonnull)). */
DIAG_PUSH_NEEDS_COMMENT;
DIAG_IGNORE_NEEDS_COMMENT(5, "-Wnonnull");
errno = 0;
if (unsetenv (NULL) >= 0 || errno != EINVAL)
{
puts ("unsetenv #1 failed");
return 1;
}
DIAG_POP_NEEDS_COMMENT;
return 0;
}
static int
do_test (void)
{
@@ -189,17 +207,7 @@ do_test (void)
result = 1;
}
/* This deliberately tests supplying a null pointer to a function whose
argument is marked __attribute__ ((nonnull)). */
DIAG_PUSH_NEEDS_COMMENT;
DIAG_IGNORE_NEEDS_COMMENT(5, "-Wnonnull");
errno = 0;
if (unsetenv (NULL) >= 0 || errno != EINVAL)
{
puts ("unsetenv #1 failed");
result = 1;
}
DIAG_POP_NEEDS_COMMENT;
result = check_null_argument ();
errno = 0;
if (unsetenv ("") >= 0 || errno != EINVAL)
+12 -4
View File
@@ -15,6 +15,14 @@ bitval (int bits)
return val;
}
static unsigned long long int
ubitval (int bits)
{
unsigned long long int val = 0;
while (bits-- > 0)
val |= 1ull << bits;
return val;
}
static int
do_test (void)
@@ -41,19 +49,19 @@ do_test (void)
TEST (INT_MIN, "d", (int) -bitval (sizeof (int) * CHAR_BIT - 1) - 1);
TEST (INT_MAX, "d", (int) bitval (sizeof (int) * CHAR_BIT - 1));
TEST (UINT_MAX, "u",
(unsigned int) bitval (sizeof (unsigned int) * CHAR_BIT));
(unsigned int) ubitval (sizeof (unsigned int) * CHAR_BIT));
TEST (LONG_MIN, "ld",
(long int) -bitval (sizeof (long int) * CHAR_BIT - 1) - 1);
TEST (LONG_MAX, "ld", (long int) bitval (sizeof (long int) * CHAR_BIT - 1));
TEST (ULONG_MAX, "lu",
(unsigned long int) bitval (sizeof (unsigned long int) * CHAR_BIT));
(unsigned long int) ubitval (sizeof (unsigned long int) * CHAR_BIT));
TEST (LLONG_MIN, "lld", -bitval (sizeof (long long int) * CHAR_BIT - 1) - 1);
TEST (LLONG_MAX, "lld", bitval (sizeof (long long int) * CHAR_BIT - 1));
TEST (ULLONG_MAX, "llu",
(unsigned long long int) bitval (sizeof (unsigned long long int)
* CHAR_BIT));
(unsigned long long int) ubitval (sizeof (unsigned long long int)
* CHAR_BIT));
/* Values from POSIX and Unix. */
#ifdef PAGESIZE
+34 -34
View File
@@ -53,23 +53,23 @@ f1 (int a00, int a01, int a02, int a03, int a04, int a05, int a06, int a07,
a24, a25, a26, a27, a28, a29, a30, a31,
a32, flag);
if (a00 != (0x00000001 << flag) || a01 != (0x00000004 << flag)
|| a02 != (0x00000012 << flag) || a03 != (0x00000048 << flag)
|| a04 != (0x00000123 << flag) || a05 != (0x0000048d << flag)
|| a06 != (0x00001234 << flag) || a07 != (0x000048d1 << flag)
|| a08 != (0x00012345 << flag) || a09 != (0x00048d15 << flag)
|| a10 != (0x00123456 << flag) || a11 != (0x0048d159 << flag)
|| a12 != (0x01234567 << flag) || a13 != (0x048d159e << flag)
|| a14 != (0x12345678 << flag) || a15 != (0x48d159e2 << flag)
|| a16 != (0x23456789 << flag) || a17 != (0x8d159e26 << flag)
|| a18 != (0x3456789a << flag) || a19 != (0xd159e26a << flag)
|| a20 != (0x456789ab << flag) || a21 != (0x159e26af << flag)
|| a22 != (0x56789abc << flag) || a23 != (0x59e26af3 << flag)
|| a24 != (0x6789abcd << flag) || a25 != (0x9e26af37 << flag)
|| a26 != (0x789abcde << flag) || a27 != (0xe26af37b << flag)
|| a28 != (0x89abcdef << flag) || a29 != (0x26af37bc << flag)
|| a30 != (0x9abcdef0 << flag) || a31 != (0x6af37bc3 << flag)
|| a32 != (0xabcdef0f << flag))
if (a00 != (0x00000001u << flag) || a01 != (0x00000004u << flag)
|| a02 != (0x00000012u << flag) || a03 != (0x00000048u << flag)
|| a04 != (0x00000123u << flag) || a05 != (0x0000048du << flag)
|| a06 != (0x00001234u << flag) || a07 != (0x000048d1u << flag)
|| a08 != (0x00012345u << flag) || a09 != (0x00048d15u << flag)
|| a10 != (0x00123456u << flag) || a11 != (0x0048d159u << flag)
|| a12 != (0x01234567u << flag) || a13 != (0x048d159eu << flag)
|| a14 != (0x12345678u << flag) || a15 != (0x48d159e2u << flag)
|| a16 != (0x23456789u << flag) || a17 != (0x8d159e26u << flag)
|| a18 != (0x3456789au << flag) || a19 != (0xd159e26au << flag)
|| a20 != (0x456789abu << flag) || a21 != (0x159e26afu << flag)
|| a22 != (0x56789abcu << flag) || a23 != (0x59e26af3u << flag)
|| a24 != (0x6789abcdu << flag) || a25 != (0x9e26af37u << flag)
|| a26 != (0x789abcdeu << flag) || a27 != (0xe26af37bu << flag)
|| a28 != (0x89abcdefu << flag) || a29 != (0x26af37bcu << flag)
|| a30 != (0x9abcdef0u << flag) || a31 != (0x6af37bc3u << flag)
|| a32 != (0xabcdef0fu << flag))
{
puts ("arg mismatch");
exit (-1);
@@ -146,23 +146,23 @@ main (void)
ctx[1].uc_link = &ctx[0];
errno = 0;
makecontext (&ctx[1], (void (*) (void)) f1, 33,
0x00000001 << flag, 0x00000004 << flag,
0x00000012 << flag, 0x00000048 << flag,
0x00000123 << flag, 0x0000048d << flag,
0x00001234 << flag, 0x000048d1 << flag,
0x00012345 << flag, 0x00048d15 << flag,
0x00123456 << flag, 0x0048d159 << flag,
0x01234567 << flag, 0x048d159e << flag,
0x12345678 << flag, 0x48d159e2 << flag,
0x23456789 << flag, 0x8d159e26 << flag,
0x3456789a << flag, 0xd159e26a << flag,
0x456789ab << flag, 0x159e26af << flag,
0x56789abc << flag, 0x59e26af3 << flag,
0x6789abcd << flag, 0x9e26af37 << flag,
0x789abcde << flag, 0xe26af37b << flag,
0x89abcdef << flag, 0x26af37bc << flag,
0x9abcdef0 << flag, 0x6af37bc3 << flag,
0xabcdef0f << flag);
0x00000001u << flag, 0x00000004u << flag,
0x00000012u << flag, 0x00000048u << flag,
0x00000123u << flag, 0x0000048du << flag,
0x00001234u << flag, 0x000048d1u << flag,
0x00012345u << flag, 0x00048d15u << flag,
0x00123456u << flag, 0x0048d159u << flag,
0x01234567u << flag, 0x048d159eu << flag,
0x12345678u << flag, 0x48d159e2u << flag,
0x23456789u << flag, 0x8d159e26u << flag,
0x3456789au << flag, 0xd159e26au << flag,
0x456789abu << flag, 0x159e26afu << flag,
0x56789abcu << flag, 0x59e26af3u << flag,
0x6789abcdu << flag, 0x9e26af37u << flag,
0x789abcdeu << flag, 0xe26af37bu << flag,
0x89abcdefu << flag, 0x26af37bcu << flag,
0x9abcdef0u << flag, 0x6af37bc3u << flag,
0xabcdef0fu << flag);
/* Without this check, a stub makecontext can make us spin forever. */
if (errno == ENOSYS)
+3 -1
View File
@@ -40,7 +40,9 @@ __ffs (int i)
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
unsigned int a;
unsigned int x = i & -i;
/* Isolate the least significant one. */
unsigned int u_i = i;
unsigned int x = u_i & -u_i;
a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
+3 -1
View File
@@ -29,7 +29,9 @@ __ffsll (long long int i)
#if USE_FFSLL_BUILTIN
return __builtin_ffsll (i);
#else
unsigned long long int x = i & -i;
/* Isolate the least significant one. */
unsigned long long int i_u = i;
unsigned long long int x = i_u & -i_u;
if (x <= 0xffffffff)
return ffs (i);
+1 -1
View File
@@ -88,7 +88,7 @@ stpcpy_unaligned_loop (op_t *restrict dst, const op_t *restrict src,
}
/* Align the final partial of P2. */
w2 = MERGE (w2b, sh_1, 0, sh_2);
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
}
out:
+1 -1
View File
@@ -89,7 +89,7 @@ strcmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs)
/* Load the final word of P1 and align the final partial of P2. */
w1 = *x1++;
w2 = MERGE (w2b, sh_1, 0, sh_2);
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
}
return final_cmp (w1, w2);
+1 -1
View File
@@ -100,7 +100,7 @@ strncmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs,
/* Load the final word of P1 and align the final partial of P2. */
w1 = *x1++;
w2 = MERGE (w2b, sh_1, 0, sh_2);
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
}
return final_cmp (w1, w2, n);
+3 -2
View File
@@ -40,9 +40,10 @@ do_test (void)
#define TEST(fct, type) \
try (#fct, 0, fct ((type) 0), 0); \
for (i=0 ; i < 8 * sizeof (type); i++) \
try (#fct, 1ll << i, fct (((type) 1) << i), i + 1); \
try (#fct, 1ull << i, fct (((unsigned type) 1) << i), i + 1); \
for (i=0 ; i < 8 * sizeof (type) ; i++) \
try (#fct, (~((type) 0) >> i) << i, fct ((~((type) 0) >> i) << i), i + 1);\
try (#fct, (~((unsigned type) 0) >> i) << i, \
fct ((~((unsigned type) 0) >> i) << i), i + 1);\
try (#fct, 0x80008000, fct ((type) 0x80008000), 16)
TEST (ffs, int);
+2 -2
View File
@@ -97,9 +97,9 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
for (i = 0; i < len; ++i)
{
buf[align + i] = (random () * random ()) & max_char;
buf[align + i] = ((int64_t)random () * random ()) & max_char;
if (!buf[align + i])
buf[align + i] = (random () * random ()) & max_char;
buf[align + i] = ((int64_t)random () * random ()) & max_char;
if (!buf[align + i])
buf[align + i] = 1;
if ((i > pos || pos >= len) && buf[align + i] == seek_char)
+1 -1
View File
@@ -259,7 +259,7 @@ xdr_hyper (XDR *xdrs, quad_t *llp)
{
if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
return FALSE;
*llp = ((quad_t) t1) << 32;
*llp = ((u_quad_t) t1) << 32;
*llp |= (uint32_t) t2;
return TRUE;
}
+4 -4
View File
@@ -24,19 +24,19 @@
#include <stdbool.h>
#define MIDR_PARTNUM_SHIFT 4
#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
#define MIDR_PARTNUM_MASK (UINT64_C(0xfff) << MIDR_PARTNUM_SHIFT)
#define MIDR_PARTNUM(midr) \
(((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
#define MIDR_ARCHITECTURE_SHIFT 16
#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT)
#define MIDR_ARCHITECTURE_MASK (UINT64_C(0xf) << MIDR_ARCHITECTURE_SHIFT)
#define MIDR_ARCHITECTURE(midr) \
(((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
#define MIDR_VARIANT_SHIFT 20
#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
#define MIDR_VARIANT_MASK (UINT64_C(0xf) << MIDR_VARIANT_SHIFT)
#define MIDR_VARIANT(midr) \
(((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
#define MIDR_IMPLEMENTOR_SHIFT 24
#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT)
#define MIDR_IMPLEMENTOR_MASK (UINT64_C(0xff) << MIDR_IMPLEMENTOR_SHIFT)
#define MIDR_IMPLEMENTOR(midr) \
(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
+5
View File
@@ -31,6 +31,11 @@ $(objpfx)tst-armtlsdescextnow: $(objpfx)tst-armtlsdescextnowmod.so
$(objpfx)tst-armtlsdescextlazy: $(objpfx)tst-armtlsdescextlazymod.so
endif
endif
ifeq ($(enable-ubsan),yes)
# aeabi_unwind_cpp_pr1 is built as rtld module
CFLAGS-aeabi_unwind_cpp_pr1.c += -DDISABLE_USAN_INTERNAL_REDIR
endif
endif
ifeq ($(subdir),csu)
+2 -1
View File
@@ -84,7 +84,8 @@ extern int search_aux_cache (struct stat *stat_buf, int *flags,
extern void add_to_aux_cache (struct stat *stat_buf, int flags,
unsigned int isa_level, const char *soname);
extern void save_aux_cache (const char *aux_cache_name);
extern void save_aux_cache (const char *aux_cache_name)
__attribute__((nonnull (1)));
/* Declared in readlib.c. */
extern int process_file (const char *real_file_name, const char *file_name,
+3
View File
@@ -27,6 +27,7 @@
#include <stddef.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <elf.h>
#include <dlfcn.h>
@@ -773,6 +774,8 @@ extern void _dl_debug_printf (const char *fmt, ...)
extern void _dl_debug_printf_c (const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 1, 2))) attribute_hidden;
extern void _dl_debug_vprintf_c (const char *fmt, va_list ap)
__attribute__ ((__format__ (__printf__, 1, 0))) attribute_hidden;
/* Write a message on the specified descriptor FD. The parameters are
interpreted as for a `printf' call. */
+5 -22
View File
@@ -19,28 +19,11 @@
#ifndef _STRING_FZI_H
#define _STRING_FZI_H 1
#include <stdbit.h>
#include <limits.h>
#include <endian.h>
#include <string-fza.h>
static __always_inline int
clz (find_t c)
{
if (sizeof (find_t) == sizeof (unsigned long))
return __builtin_clzl (c);
else
return __builtin_clzll (c);
}
static __always_inline int
ctz (find_t c)
{
if (sizeof (find_t) == sizeof (unsigned long))
return __builtin_ctzl (c);
else
return __builtin_ctzll (c);
}
/* A subroutine for the index_zero functions. Given a test word C, return
the (memory order) index of the first byte (in memory order) that is
non-zero. */
@@ -49,9 +32,9 @@ index_first (find_t c)
{
int r;
if (__BYTE_ORDER == __LITTLE_ENDIAN)
r = ctz (c);
r = stdc_trailing_zeros (c);
else
r = clz (c);
r = stdc_leading_zeros (c);
return r / CHAR_BIT;
}
@@ -62,9 +45,9 @@ index_last (find_t c)
{
int r;
if (__BYTE_ORDER == __LITTLE_ENDIAN)
r = clz (c);
r = stdc_leading_zeros (c);
else
r = ctz (c);
r = stdc_trailing_zeros (c);
return sizeof (find_t) - 1 - (r / CHAR_BIT);
}
+36
View File
@@ -18,3 +18,39 @@ asm (".hidden __stack_chk_fail_local\n"
"__stack_chk_fail = __stack_chk_fail_local");
# endif
#endif
#if !defined __ASSEMBLER__ && IS_IN(rtld) && defined ENABLE_UBSAN \
&& !defined DISABLE_USAN_INTERNAL_REDIR
/* These are autogenerated by the compiler, so no subject to either
hidden_attribute or hidden_proto alias definition. */
asm ("__ubsan_handle_negate_overflow = "
"__GI___ubsan_handle_negate_overflow");
asm ("__ubsan_handle_shift_out_of_bounds = "
"__GI___ubsan_handle_shift_out_of_bounds");
asm ("__ubsan_handle_divrem_overflow = "
"__GI___ubsan_handle_divrem_overflow");
asm ("__ubsan_handle_vla_bound_not_positive = "
"__GI___ubsan_handle_vla_bound_not_positive");
asm ("__ubsan_handle_pointer_overflow = "
"__GI___ubsan_handle_pointer_overflow");
asm ("__ubsan_handle_load_invalid_value ="
"__GI___ubsan_handle_load_invalid_value");
asm ("__ubsan_handle_out_of_bounds = "
"__GI___ubsan_handle_out_of_bounds");
asm ("__ubsan_handle_sub_overflow = "
"__GI___ubsan_handle_sub_overflow");
asm ("__ubsan_handle_add_overflow = "
"__GI___ubsan_handle_add_overflow");
asm ("__ubsan_handle_mul_overflow = "
"__GI___ubsan_handle_mul_overflow");
asm ("__ubsan_handle_type_mismatch_v1 = "
"__GI___ubsan_handle_type_mismatch_v1");
asm ("__ubsan_handle_nonnull_return_v1 = "
"__GI___ubsan_handle_nonnull_return_v1");
asm ("__ubsan_handle_nonnull_arg = "
"__GI___ubsan_handle_nonnull_arg");
asm ("__ubsan_handle_invalid_builtin = "
"__GI___ubsan_handle_invalid_builtin");
asm ("__ubsan_handle_builtin_unreachable = "
"__GI___ubsan_handle_builtin_unreachable");
#endif
-41
View File
@@ -1,41 +0,0 @@
/*
* Public domain.
*/
#include <machine/asm.h>
RCSID("$NetBSD: s_ilogb.S,v 1.5 1995/10/12 15:53:09 jtc Exp $")
ENTRY(__ieee754_ilogb)
fldl 4(%esp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
-- jakub@redhat.com. */
fxam /* Is NaN or +-Inf? */
fstsw %ax
movb $0x45, %dh
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-0, jump. */
fxtract
pushl %eax
cfi_adjust_cfa_offset (4)
fstp %st
fistpl (%esp)
fwait
popl %eax
cfi_adjust_cfa_offset (-4)
ret
1: fstp %st
movl $0x7fffffff, %eax
ret
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogb)
-41
View File
@@ -1,41 +0,0 @@
/*
* Public domain.
*/
#include <machine/asm.h>
RCSID("$NetBSD: s_ilogbf.S,v 1.4 1995/10/22 20:32:43 pk Exp $")
ENTRY(__ieee754_ilogbf)
flds 4(%esp)
/* I added the following ugly construct because ilogb(+-Inf) is
required to return INT_MAX in ISO C99.
-- jakub@redhat.com. */
fxam /* Is NaN or +-Inf? */
fstsw %ax
movb $0x45, %dh
andb %ah, %dh
cmpb $0x05, %dh
je 1f /* Is +-Inf, jump. */
cmpb $0x40, %dh
je 2f /* Is +-0, jump. */
fxtract
pushl %eax
cfi_adjust_cfa_offset (4)
fstp %st
fistpl (%esp)
fwait
popl %eax
cfi_adjust_cfa_offset (-4)
ret
1: fstp %st
movl $0x7fffffff, %eax
ret
2: fstp %st
movl $0x80000000, %eax /* FP_ILOGB0 */
ret
END (__ieee754_ilogbf)
-1
View File
@@ -1 +0,0 @@
/* Not needed. */
+1 -63
View File
@@ -1,63 +1 @@
/* @(#)s_ilogb.c 5.1 93/09/24 */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_ilogb.c,v 1.9 1995/05/10 20:47:28 jtc Exp $";
#endif
/* ilogb(double x)
* return the binary exponent of non-zero x
* ilogb(0) = FP_ILOGB0
* ilogb(NaN) = FP_ILOGBNAN (no signal is raised)
* ilogb(+-Inf) = INT_MAX (no signal is raised)
*/
#include <limits.h>
#include <math.h>
#include <math_private.h>
int
__ieee754_ilogb (double x)
{
int32_t hx, lx, ix;
GET_HIGH_WORD (hx, x);
hx &= 0x7fffffff;
if (hx < 0x00100000)
{
GET_LOW_WORD (lx, x);
if ((hx | lx) == 0)
return FP_ILOGB0; /* ilogb(0) = FP_ILOGB0 */
else /* subnormal x */
if (hx == 0)
{
for (ix = -1043; lx > 0; lx <<= 1)
ix -= 1;
}
else
{
for (ix = -1022, hx <<= 11; hx > 0; hx <<= 1)
ix -= 1;
}
return ix;
}
else if (hx < 0x7ff00000)
return (hx >> 20) - 1023;
else if (FP_ILOGBNAN != INT_MAX)
{
/* ISO C99 requires ilogb(+-Inf) == INT_MAX. */
GET_LOW_WORD (lx, x);
if (((hx ^ 0x7ff00000) | lx) == 0)
return INT_MAX;
}
return FP_ILOGBNAN;
}
/* ilogb is implemented at w_ilogb.c */
+2
View File
@@ -164,6 +164,8 @@ attribute_hidden double __math_divzero (uint32_t);
/* Invalid input unless it is a quiet NaN. */
attribute_hidden double __math_invalid (double);
attribute_hidden int __math_invalid_i (int);
attribute_hidden long int __math_invalid_li (long int);
/* Error handling using output checking, only for errno setting. */
+32
View File
@@ -29,8 +29,24 @@ with_errno (double y, int e)
errno = e;
return y;
}
NOINLINE static int
with_errno_i (int y, int e)
{
errno = e;
return y;
}
NOINLINE static long int
with_errno_li (long int y, int e)
{
errno = e;
return y;
}
#else
#define with_errno(x, e) (x)
#define with_errno_i(x, e) (x)
#define with_errno_li(x, e) (x)
#endif
attribute_hidden double
@@ -83,6 +99,22 @@ __math_invalid (double x)
return isnan (x) ? y : with_errno (y, EDOM);
}
attribute_hidden int
__math_invalid_i (int r)
{
double y = 0.0 / 0.0;
math_force_eval (y);
return with_errno_i (r, EDOM);
}
attribute_hidden long int
__math_invalid_li (long int r)
{
double y = 0.0 / 0.0;
math_force_eval (y);
return with_errno_li (r, EDOM);
}
/* Check result and set errno if necessary. */
attribute_hidden double
+1 -1
View File
@@ -239,7 +239,7 @@ __expm1 (double x)
uint32_t high;
y = one - (e - x);
GET_HIGH_WORD (high, y);
SET_HIGH_WORD (y, high + (k << 20)); /* add k to y's exponent */
SET_HIGH_WORD (y, high + ((uint32_t)k << 20)); /* add k to y's exponent */
return y - one;
}
t = one;
+1 -1
View File
@@ -95,7 +95,7 @@ __lrint (double x)
if (j0 == 20)
result = (long int) i0;
else
result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
result = (i0 << (j0 - 20)) | (i1 >> (52 - j0));
}
}
else
+2 -1
View File
@@ -37,7 +37,8 @@ __rint (double x)
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
int64_t i0, sx;
int64_t i0;
uint64_t sx;
int32_t j0;
EXTRACT_WORDS64 (i0, x);
sx = (i0 >> 63) & 1;
+3 -1
View File
@@ -37,7 +37,9 @@ FUNC (double *x, double payload)
except for 0 when allowed; (c) not an integer. */
if (exponent >= BIAS + PAYLOAD_DIG
|| (exponent < BIAS && !(SET_HIGH_BIT && ix == 0))
|| (ix & ((1ULL << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0)
|| ((BIAS + EXPLICIT_MANT_DIG - exponent) < 64
&& (ix & ((1ULL << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1))
!= 0))
{
INSERT_WORDS64 (*x, 0);
return 1;
+37
View File
@@ -0,0 +1,37 @@
/* Get integer exponent of a floating-point value.
Copyright (C) 1999-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
static inline RET_TYPE
IMPL_NAME (double x)
{
uint64_t ux = asuint64 (x);
int ex = (ux & ~SIGN_MASK) >> MANTISSA_WIDTH;
if (__glibc_unlikely (ex == 0)) /* zero or subnormal */
{
/* Clear sign and exponent */
ux <<= 12;
if (ux == 0)
return RET_INVALID (RET_LOGB0);
/* subnormal */
return (RET_TYPE)-1023 - stdc_leading_zeros (ux);
}
if (__glibc_unlikely (ex == EXPONENT_MASK >> MANTISSA_WIDTH))
/* NaN or Inf */
return RET_INVALID (ux << 12 ? RET_LOGBNAN : RET_LOGMAX);
return ex - 1023;
}
+52
View File
@@ -0,0 +1,52 @@
/* Get integer exponent of a floating-point value.
Copyright (C) 1999-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <limits.h>
#include <math.h>
#include <stdbit.h>
#include <libm-alias-double.h>
#include "math_config.h"
#ifdef DEF_AS_LLOGB
# define DECL_NAME __llogb
# define FUNC_NAME llogb
# define RET_TYPE long int
# define RET_LOGB0 FP_LLOGB0
# define RET_LOGBNAN FP_LLOGBNAN
# define RET_LOGMAX LONG_MAX
# define RET_INVALID __math_invalid_li
#else
# define DECL_NAME __ilogb
# define FUNC_NAME ilogb
# define RET_TYPE int
# define RET_LOGB0 FP_ILOGB0
# define RET_LOGBNAN FP_ILOGBNAN
# define RET_LOGMAX INT_MAX
# define RET_INVALID __math_invalid_i
#endif
#define __IMPL_NAME(x,y) x ## _ ## y
#define _IMPL_NAME(x,y) __IMPL_NAME(x,y)
#define IMPL_NAME _IMPL_NAME(FUNC_NAME, impl)
#include <w_ilogb-impl.h>
RET_TYPE
DECL_NAME (double x)
{
return IMPL_NAME (x);
}
libm_alias_double (DECL_NAME, FUNC_NAME)
+2
View File
@@ -0,0 +1,2 @@
#define DEF_AS_LLOGB
#include "w_ilogb.c"
+1 -43
View File
@@ -1,43 +1 @@
/* s_ilogbf.c -- float version of s_ilogb.c.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_ilogbf.c,v 1.4 1995/05/10 20:47:31 jtc Exp $";
#endif
#include <limits.h>
#include <math.h>
#include <math_private.h>
int __ieee754_ilogbf(float x)
{
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
hx &= 0x7fffffff;
if(hx<0x00800000) {
if(hx==0)
return FP_ILOGB0; /* ilogb(0) = FP_ILOGB0 */
else /* subnormal x */
for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
return ix;
}
else if (hx<0x7f800000) return (hx>>23)-127;
else if (FP_ILOGBNAN != INT_MAX) {
/* ISO C99 requires ilogbf(+-Inf) == INT_MAX. */
if (hx==0x7f800000)
return INT_MAX;
}
return FP_ILOGBNAN;
}
/* ilogbf is implemented at w_ilogbf.c */
+4 -1
View File
@@ -23,6 +23,7 @@
#include <math_private.h>
#include <nan-high-order-bit.h>
#include <stdint.h>
#include <stdbit.h>
#ifndef WANT_ROUNDING
/* Correct special case results in non-nearest rounding modes. */
@@ -102,7 +103,7 @@ roundevenf_finite (float x)
{
union { float f; uint32_t i; } u = {y};
union { float f; uint32_t i; } v = {y - copysignf (1.0, x)};
if (__builtin_ctzl (v.i) > __builtin_ctzl (u.i))
if (stdc_leading_zeros (v.i) > stdc_leading_zeros (u.i))
y = v.f;
}
return y;
@@ -208,6 +209,8 @@ attribute_hidden float __math_uflowf (uint32_t);
attribute_hidden float __math_may_uflowf (uint32_t);
attribute_hidden float __math_divzerof (uint32_t);
attribute_hidden float __math_invalidf (float);
attribute_hidden int __math_invalidf_i (int);
attribute_hidden long int __math_invalidf_li (long int);
attribute_hidden float __math_edomf (float x);
/* Shared between expf, exp2f, exp10f, and powf. */
+33
View File
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <math-barriers.h>
#include "math_config.h"
#if WANT_ERRNO
@@ -27,8 +28,24 @@ with_errnof (float y, int e)
errno = e;
return y;
}
NOINLINE static int
with_errnof_i (int y, int e)
{
errno = e;
return y;
}
NOINLINE static long int
with_errnof_li (long int y, int e)
{
errno = e;
return y;
}
#else
# define with_errnof(x, e) (x)
# define with_errnof_i(x, x) (x)
# define with_errnof_li(x, x) (x)
#endif
attribute_hidden float
@@ -80,3 +97,19 @@ __math_invalidf (float x)
float y = (x - x) / (x - x);
return isnan (x) ? y : with_errnof (y, EDOM);
}
attribute_hidden int
__math_invalidf_i (int x)
{
float y = 0.0f / 0.0f;
math_force_eval (y);
return with_errnof_i (x, EDOM);
}
attribute_hidden long int
__math_invalidf_li (long int x)
{
float y = 0.0f / 0.0f;
math_force_eval (y);
return with_errnof_li (x, EDOM);
}
+2 -1
View File
@@ -34,7 +34,8 @@ __nearbyintf (float x)
-8.3886080000e+06, /* 0xcb000000 */
};
fenv_t env;
int32_t i0, j0, sx;
int32_t i0, j0;
uint32_t sx;
float w, t;
GET_FLOAT_WORD (i0, x);
sx = (i0 >> 31) & 1;
+2 -1
View File
@@ -30,7 +30,8 @@ __rintf (float x)
8.3886080000e+06, /* 0x4b000000 */
-8.3886080000e+06, /* 0xcb000000 */
};
int32_t i0, j0, sx;
int32_t i0, j0;
uint32_t sx;
float w, t;
GET_FLOAT_WORD (i0, x);
sx = (i0 >> 31) & 1;
+2 -1
View File
@@ -37,7 +37,8 @@ FUNC (float *x, float payload)
except for 0 when allowed; (c) not an integer. */
if (exponent >= BIAS + PAYLOAD_DIG
|| (exponent < BIAS && !(SET_HIGH_BIT && ix == 0))
|| (ix & ((1U << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0)
|| ((BIAS + EXPLICIT_MANT_DIG - exponent) < 32
&& (ix & ((1U << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0))
{
SET_FLOAT_WORD (*x, 0);
return 1;

Some files were not shown because too many files have changed in this diff Show More