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'
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'
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'
$ 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'
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'
$ 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'
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'
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'
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
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'
$ 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
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'
$ 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'
$ 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
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.
$ 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.
UBSAN: Undefined behaviour in tst-sprofil.c:140:6 unsigned integer overflow: 2432902008176640000 + 7812407968270641256 cannot be represened in type 'long int'
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.
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
UBSAN: Undefined behaviour in ../sysdeps/ieee754/float128/../ldbl-128/s_isnanl.c:29:30 negation of 9223372036854775808 cannot be represented in type 'long int'
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'
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.
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:
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:
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:
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.
* 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.
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.
* 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.
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.
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.
[...]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.
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.
Collin Funk [Mon, 5 May 2025 02:31:34 +0000 (19:31 -0700)]
nss: remove undefined behavior and optimize getaddrinfo
On x86-64 and compiling with -O2 using stdc_leading_zeros compiles to
the bsr instruction. The fls function removed by this patch is inlined
but still loops while checking each bit individually.
* nss/getaddrinfo.c: Include <stdbit.h>.
(fls): Remove function. This function contains a left shift of 31 on an
'int' which is undefined.
(rfc3484_sort): Use stdc_leading_zeros instead of fls.
These routines are not extensively used (gnulib documentation even
recommend use a replacement [1]), and there is already a POWER8
version that uses proper vectorized instructions.
DJ Delorie [Sat, 3 May 2025 00:51:18 +0000 (20:51 -0400)]
manual: add more pthread functions
Add stubs and partial docs for many undocumented pthreads functions.
While neither exhaustive nor complete, gives minimal usage docs
for many functions and expands the pthreads chapters, making it
easier to continue improving this section in the future.
Stefan Liebler [Tue, 29 Apr 2025 11:28:58 +0000 (13:28 +0200)]
S390: Add new s390 platform z17.
The glibc-hwcaps subdirectories are extended by "z17". Libraries are loaded if
the z17 facility bits are active:
- Miscellaneous-instruction-extensions facility 4
- Vector-enhancements-facility 3
- Vector-Packed-Decimal-Enhancement Facility 3
- CPU: Concurrent-Functions Facility
tst-glibc-hwcaps.c is extended in order to test z17 via new marker6.
In case of running on a z17 with a kernel not recognizing z17 yet,
AT_PLATFORM will be z900 but vector-bit in AT_HWCAP is set. This situation
is now recognized and this testcase does not fail.
A fatal glibc error is dumped if glibc was build with architecture
level set for z17, but run on an older machine (See dl-hwcap-check.h).
Note, you might get an SIGILL before this check if you don't use:
configure --with-rtld-early-cflags=-march=<older-machine>
ld.so --list-diagnostics now also dumps information about s390.cpu_features.
Independent from z17, the s390x kernel won't introduce new HWCAP-Bits if there
is no special handling needed in kernel itself. For z17, we don't have new
HWCAP flags, but have to check the facility bits retrieved by
stfle-instruction.
Instead of storing all the stfle-bits (currently four 64bit values) in the
cpu_features struct, we now only store those bits, which are needed within
glibc itself. Note that we have this list twice, one with original values and
the other one which can be filtered with GLIBC_TUNABLES=glibc.cpu.hwcaps.
Those new fields are stored in so far reserved space in cpu_features struct.
Thus processes started in between the update of glibc package and we e.g. have
a new ld.so and an old libc.so, won't crash. The glibc internal ifunc-resolvers
would not select the best optimized variant.
The users of stfle-bits are also updated:
- parsing of GLIBC_TUNABLES=glibc.cpu.hwcaps
- glibc internal ifunc-resolvers
- __libc_ifunc_impl_list
- sysconf
Joseph Myers [Thu, 1 May 2025 22:28:59 +0000 (22:28 +0000)]
Correct test descriptors in libm-test-pown.inc
While working on implementing compoundn, I noticed that
libm-test-pown.inc was wrongly using TEST_ff_f and AUTO_TESTS_ff_f
when the actual types involved meant fL_f should be used instead of
ff_f; fix to use the correct descriptor strings for pown. (These
strings affect how gen-libm-test.py generates a C file in some cases.
The structure type test_fL_f_data for expected results and the use of
RUN_TEST_LOOP_fL_f in the ALL_RM_TEST call were already correct.)
Tested for x86_64. The generated libm-test-pown.c was actually
unchanged, but the old descriptor strings were still logically
incorrect.
Inline tcache_try_malloc into calloc since it is the only caller. Also fix
usize2tidx and use it in __libc_malloc, __libc_calloc and _mid_memalign.
The result is simpler, cleaner code.