aboutsummaryrefslogtreecommitdiff
path: root/stdlib
AgeCommit message (Collapse)AuthorFilesLines
2024-11-21stdlib: Make getenv thread-safe in more casesFlorian Weimer8-79/+609
Async-signal-safety is preserved, too. In fact, getenv is fully reentrant and can be called from the malloc call in setenv (if a replacement malloc uses getenv during its initialization). This is relatively easy to implement because even before this change, setenv, unsetenv, clearenv, putenv do not deallocate the environment strings themselves as they are removed from the environment. The main changes are: * Use release stores for environment array updates, following the usual pattern for safely publishing immutable data (in this case, the environment strings). * Do not deallocate the environment array. Instead, keep older versions around and adopt an exponential resizing policy. This results in an amortized constant space leak per active environment variable, but there already is such a leak for the variable itself (and that is even length-dependent, and includes no-longer used values). * Add a seqlock-like mechanism to retry getenv if a concurrent unsetenv is observed. Without that, it is possible that getenv returns NULL for a variable that is never unset. This is visible on some AArch64 implementations with the newly added stdlib/tst-getenv-unsetenv test case. The mechanism is not a pure seqlock because it tolerates one write from unsetenv. This avoids the need for a second copy of the environ array that getenv can read from a signal handler that happens to interrupt an unsetenv call. No manual updates are included with this patch because environ usage with execve, posix_spawn, system is still not thread-safe relative unsetenv. The new process may end up with an environment that misses entries that were never unset. This is the same issue described above for getenv. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-11-12linux: Add support for getrandom vDSOAdhemerval Zanella2-0/+49
Linux 6.11 has getrandom() in vDSO. It operates on a thread-local opaque state allocated with mmap using flags specified by the vDSO. Multiple states are allocated at once, as many as fit into a page, and these are held in an array of available states to be doled out to each thread upon first use, and recycled when a thread terminates. As these states run low, more are allocated. To make this procedure async-signal-safe, a simple guard is used in the LSB of the opaque state address, falling back to the syscall if there's reentrancy contention. Also, _Fork() is handled by blocking signals on opaque state allocation (so _Fork() always sees a consistent state even if it interrupts a getrandom() call) and by iterating over the thread stack cache on reclaim_stack. Each opaque state will be in the free states list (grnd_alloc.states) or allocated to a running thread. The cancellation is handled by always using GRND_NONBLOCK flags while calling the vDSO, and falling back to the cancellable syscall if the kernel returns EAGAIN (would block). Since getrandom is not defined by POSIX and cancellation is supported as an extension, the cancellation is handled as 'may occur' instead of 'shall occur' [1], meaning that if vDSO does not block (the expected behavior) getrandom will not act as a cancellation entrypoint. It avoids a pthread_testcancel call on the fast path (different than 'shall occur' functions, like sem_wait()). It is currently enabled for x86_64, which is available in Linux 6.11, and aarch64, powerpc32, powerpc64, loongarch64, and s390x, which are available in Linux 6.12. Link: https://pubs.opengroup.org/onlinepubs/9799919799/nframe.html [1] Co-developed-by: Jason A. Donenfeld <Jason@zx2c4.com> Tested-by: Jason A. Donenfeld <Jason@zx2c4.com> # x86_64 Tested-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> # x86_64, aarch64 Tested-by: Xi Ruoyao <xry111@xry111.site> # x86_64, aarch64, loongarch64 Tested-by: Stefan Liebler <stli@linux.ibm.com> # s390x
2024-10-08stdlib: Make abort/_Exit AS-safe (BZ 26275)Adhemerval Zanella1-83/+55
The recursive lock used on abort does not synchronize with a new process creation (either by fork-like interfaces or posix_spawn ones), nor it is reinitialized after fork(). Also, the SIGABRT unblock before raise() shows another race condition, where a fork or posix_spawn() call by another thread, just after the recursive lock release and before the SIGABRT signal, might create programs with a non-expected signal mask. With the default option (without POSIX_SPAWN_SETSIGDEF), the process can see SIG_DFL for SIGABRT, where it should be SIG_IGN. To fix the AS-safe, raise() does not change the process signal mask, and an AS-safe lock is used if a SIGABRT is installed or the process is blocked or ignored. With the signal mask change removal, there is no need to use a recursive loc. The lock is also taken on both _Fork() and posix_spawn(), to avoid the spawn process to see the abort handler as SIG_DFL. A read-write lock is used to avoid serialize _Fork and posix_spawn execution. Both sigaction (SIGABRT) and abort() requires to lock as writer (since both change the disposition). The fallback is also simplified: there is no need to use a loop of ABORT_INSTRUCTION after _exit() (if the syscall does not terminate the process, the system is broken). The proposed fix changes how setjmp works on a SIGABRT handler, where glibc does not save the signal mask. So usage like the below will now always abort. static volatile int chk_fail_ok; static jmp_buf chk_fail_buf; static void handler (int sig) { if (chk_fail_ok) { chk_fail_ok = 0; longjmp (chk_fail_buf, 1); } else _exit (127); } [...] signal (SIGABRT, handler); [....] chk_fail_ok = 1; if (! setjmp (chk_fail_buf)) { // Something that can calls abort, like a failed fortify function. chk_fail_ok = 0; printf ("FAIL\n"); } Such cases will need to use sigsetjmp instead. The _dl_start_profile calls sigaction through _profil, and to avoid pulling abort() on loader the call is replaced with __libc_sigaction. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reviewed-by: DJ Delorie <dj@redhat.com>
2024-09-20Make tst-strtod-underflow type-genericJoseph Myers1-60/+297
The test tst-strtod-underflow covers various edge cases close to the underflow threshold for strtod (especially cases where underflow on architectures with after-rounding tininess detection depends on the rounding mode). Make it use the type-generic machinery, with corresponding test inputs for each supported floating-point format, so that other functions in the strtod family are tested for underflow edge cases as well. Tested for x86_64.
2024-09-20Add tests of more strtod special casesJoseph Myers1-0/+14
There is very little test coverage of inputs to strtod-family functions that don't contain anything that can be parsed as a number (one test of ".y" in tst-strtod2), and none that I can see of skipping initial whitespace. Add some tests of these things to tst-strtod2. Tested for x86_64.
2024-09-20Add more tests of strtod end pointerJoseph Myers1-2/+39
Although there are some tests in tst-strtod2 and tst-strtod3 for the end pointer provided by strtod when it doesn't parse the whole string, they aren't very thorough. Add tests of more such cases to tst-strtod2. Tested for x86_64.
2024-09-20Make tst-strtod2 and tst-strtod5 type-genericJoseph Myers2-82/+118
Some of the strtod tests use type-generic machinery in tst-strtod.h to test the strto* functions for all floating types, while others only test double even when the tests are in fact meaningful for all floating types. Convert tst-strtod2 and tst-strtod5 to use the type-generic machinery so they test all floating types. I haven't tried to convert them to use newer test interfaces in other ways, just made the changes necessary to use the type-generic machinery. Tested for x86_64.
2024-09-04Do not set errno for overflowing NaN payload in strtod/nan (bug 32045)Joseph Myers1-0/+3
As reported in bug 32045, it's incorrect for strtod/nan functions to set errno based on overflowing payload (strtod should only set errno for overflow / underflow of its actual result, and potentially if nothing in the string can be parsed as a number at all; nan should be a pure function that never sets it). Save and restore errno around the internal strtoull call and add associated test coverage. Tested for x86_64.
2024-08-27Make __strtod_internal tests type-genericJoseph Myers4-180/+313
Some of the strtod tests use type-generic machinery in tst-strtod.h to test the strto* functions for all floating types, while others only test double even when the tests are in fact meaningful for all floating types. Convert the tests of the internal __strtod_internal interface to cover all floating types. I haven't tried to convert them to use newer test interfaces in other ways, just made the changes necessary to use the type-generic machinery. As an internal interface, there are no aliases for different types with the same ABI (however, __strtold_internal is defined even if long double has the same ABI as double), so macros used by the type-generic testing code are redefined as needed to avoid expecting such aliases to be present. Tested for x86_64.
2024-08-27Fix strtod subnormal rounding (bug 30220)Joseph Myers3-0/+386
As reported in bug 30220, the implementation of strtod-family functions has a bug in the following case: the input string would, with infinite exponent range, take one more bit to represent than is available in the normal precision of the return type; the value represented is in the subnormal range; and there are no nonzero bits in the value, below those that can be represented in subnormal precision, other than the least significant bit and possibly the 0.5ulp bit. In this case, round_and_return ends up discarding the least significant bit. Fix by saving that bit to merge into more_bits (it can't be merged in at the time it's computed, because more_bits mustn't include this bit in the case of after-rounding tininess detection checking if the result is still subnormal when rounded to normal precision, so merging this bit into more_bits needs to take place after that check). Tested for x86_64.
2024-08-27More thoroughly test underflow / errno in tst-strtod-roundJoseph Myers3-7761/+7857
Add tests of underflow in tst-strtod-round, and thus also test for errno being unchanged when there is neither overflow nor underflow. The errno setting before the function call to test for being unchanged is adjusted to set errno to 12345 instead of 0, so that any bugs where strtod sets errno to 0 would be detected. This doesn't add any new test inputs for tst-strtod-round, and in particular doesn't cover the edge cases of underflow the way tst-strtod-underflow does (none of the existing test inputs for tst-strtod-round actually exercise cases that have underflow with before-rounding tininess detection but not with after-rounding tininess detection), but at least it provides some coverage (as per the recent discussions) that ordinary non-overflowing non-underflowing inputs to these functions do not set errno. Tested for x86_64.
2024-08-16support: Use macros for *stat wrappersFlorian Weimer1-1/+1
Macros will automatically use the correct types, without having to fiddle with internal glibc macros. It's also impossible to get the types wrong due to aliasing because support_check_stat_fd and support_check_stat_path do not depend on the struct stat* types. The changes reveal some inconsistencies in tests. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-08-14Test errno setting on strtod overflow in tst-strtod-roundJoseph Myers1-0/+11
We have no tests that errno is set to ERANGE on overflow of strtod-family functions (we do have some tests for underflow, in tst-strtod-underflow). Add such tests to tst-strtod-round. Tested for x86_64.
2024-08-06stdlib: Link tst-concurrent-quick_exit with $(shared-thread-library)Adhemerval Zanella1-0/+1
This avoids a Hurd build failure. Fixes commit c6af8a9a3c ("stdlib: Allow concurrent quick_exit (BZ 31997)").
2024-08-05stdlib: Allow concurrent quick_exit (BZ 31997)Adhemerval Zanella5-146/+196
As for exit, also allows concurrent quick_exit to avoid race conditions when it is called concurrently. Since it uses the same internal function as exit, the __exit_lock lock is moved to __run_exit_handlers. It also solved a potential concurrent when calling exit and quick_exit concurrently. The test case 'expected' is expanded to a value larger than the minimum required by C/POSIX (32 entries) so at_quick_exit() will require libc to allocate a new block. This makes the test mre likely to trigger concurrent issues (through free() at __run_exit_handlers) if quick_exit() interacts with the at_quick_exit list concurrently. This is also the latest interpretation of the Austin Ticket [1]. Checked on x86_64-linux-gnu. [1] https://austingroupbugs.net/view.php?id=1845 Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-08-05Fix name space violation in fortify wrappers (bug 32052)Andreas Schwab1-5/+5
Rename the identifier sz to __sz everywhere. Fixes: a643f60c53 ("Make sure that the fortified function conditionals are constant")
2024-08-02stdlib: Link tst-concurrent-exit with $(shared-thread-library)Florian Weimer1-0/+1
This avoids a Hurd build failure. Fixes commit f6ba993e0cda0ca ("stdlib: Allow concurrent exit (BZ 31997)").
2024-07-31stdlib: Mark `abort` as `cold`Noah Goldstein1-1/+1
This helps HotColdSplitting in GCC/LLVM. Thought about doing `exit` as well since its only called once per process, but since its easy to imagine a hot path leading into `exit(0)`, its less clear if its profitable. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-07-30stdlib: Allow concurrent exit (BZ 31997)Adhemerval Zanella3-0/+166
Even if C/POSIX standard states that exit is not formally thread-unsafe, calling it more than once is UB. The glibc already supports it for the single-thread, and both elf/nodelete2.c and tst-rseq-disable.c call exit from a DSO destructor (which is called by _dl_fini, registered at program startup with __cxa_atexit). However, there are still race issues when it is called more than once concurrently by multiple threads. A recent Rust PR triggered this issue [1], which resulted in an Austin Group ask for clarification [2]. Besides it, there is a discussion to make concurrent calling not UB [3], wtih a defined semantic where any remaining callers block until the first call to exit has finished (reentrant calls, leaving through longjmp, and exceptions are still undefined). For glibc, at least reentrant calls are required to be supported to avoid changing the current behaviour. This requires locking using a recursive lock, where any exit called by atexit() handlers resumes at the point of the current handler (thus avoiding calling the current handle multiple times). Checked on x86_64-linux-gnu and aarch64-linux-gnu. [1] https://github.com/rust-lang/rust/issues/126600 [2] https://austingroupbugs.net/view.php?id=1845 [3] https://www.openwall.com/lists/libc-coord/2024/07/24/4 Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-07-19Fix usage of _STACK_GROWS_DOWN and _STACK_GROWS_UP defines [BZ 31989]John David Anglin1-2/+2
Signed-off-by: John David Anglin <dave.anglin@bell.net> Reviewed-By: Andreas K. Hüttel <dilfridge@gentoo.org>
2024-07-08stdlib: fix arc4random fallback to /dev/urandom (BZ 31612)Adhemerval Zanella1-1/+1
The __getrandom_nocancel used by __arc4random_buf uses INLINE_SYSCALL_CALL (which returns -1/errno) and the loop checks for the return value instead of errno to fallback to /dev/urandom. The malloc code now uses __getrandom_nocancel_nostatus, which uses INTERNAL_SYSCALL_CALL, so there is no need to use the variant that does not set errno (BZ#29624). Checked on x86_64-linux-gnu. Reviewed-by: Xi Ruoyao <xry111@xry111.site>
2024-06-03stdlib: Describe __cxa_finalize usage in function commentFlorian Weimer1-1/+16
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
2024-03-23stdlib: Fix tst-makecontext2 log when swapcontext failsStafford Horne1-1/+1
The log incorrectly prints, setcontext failed. Update this to indicate that actually swapcontext failed. Signed-off-by: Stafford Horne <shorne@gmail.com> Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2024-02-27stdlib: Improve fortify with clangAdhemerval Zanella1-11/+28
It improve fortify checks for realpath, ptsname_r, wctomb, mbstowcs, and wcstombs. The runtime and compile checks have similar coverage as with GCC. Checked on aarch64, armhf, x86_64, and i686. Tested-by: Carlos O'Donell <carlos@redhat.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-02-08localedata: hr_HR: change currency to EUR/€Dragan Stanojević (Nevidljivi)1-4/+4
Resolves: BZ # 29845
2024-02-01Rename c2x / gnu2x tests to c23 / gnu23Joseph Myers3-4/+4
Complete the internal renaming from "C2X" and related names in GCC by renaming *-c2x and *-gnu2x tests to *-c23 and *-gnu23. Tested for x86_64, and with build-many-glibcs.py for powerpc64le.
2024-02-01Refer to C23 in place of C2X in glibcJoseph Myers15-37/+38
WG14 decided to use the name C23 as the informal name of the next revision of the C standard (notwithstanding the publication date in 2024). Update references to C2X in glibc to use the C23 name. This is intended to update everything *except* where it involves renaming files (the changes involving renaming tests are intended to be done separately). In the case of the _ISOC2X_SOURCE feature test macro - the only user-visible interface involved - support for that macro is kept for backwards compatibility, while adding _ISOC23_SOURCE. Tested for x86_64.
2024-01-31Use gcc __builtin_stdc_* builtins in stdbit.h if possibleJakub Jelinek3-14/+849
The following patch uses the GCC 14 __builtin_stdc_* builtins in stdbit.h for the type-generic macros, so that when compiled with GCC 14 or later, it supports not just 8/16/32/64-bit unsigned integers, but also 128-bit (if target supports them) and unsigned _BitInt (any supported precision). And so that the macros don't expand arguments multiple times and can be evaluated in constant expressions. The new testcase is gcc's gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c adjusted to test stdbit.h and the type-generic macros in there instead of the builtins and adjusted to use glibc test framework rather than gcc style tests with __builtin_abort (). Signed-off-by: Jakub Jelinek <jakub@redhat.com> Reviewed-by: Joseph Myers <josmyers@redhat.com>
2024-01-23qsort: Fix a typo causing unnecessary malloc/free (BZ 31276)Xi Ruoyao1-1/+1
In qsort_r we allocate a buffer sized QSORT_STACK_SIZE (1024) on stack and we intend to use it if all elements can fit into it. But there is a typo: if (total_size < sizeof buf) buf = tmp; else /* allocate a buffer on heap and use it ... */ Here "buf" is a pointer, thus sizeof buf is just 4 or 8, instead of 1024. There is also a minor issue that we should use "<=" instead of "<". This bug is detected debugging some strange heap corruption running the Ruby-3.3.0 test suite (on an experimental Linux From Scratch build using Binutils-2.41.90 and Glibc trunk, and also Fedora Rawhide [1]). It seems Ruby is doing some wild "optimization" by jumping into somewhere in qsort_r instead of calling it normally, resulting in a double free of buf if we allocate it on heap. The issue can be reproduced deterministically with: LD_PRELOAD=/usr/lib/libc_malloc_debug.so MALLOC_CHECK_=3 \ LD_LIBRARY_PATH=. ./ruby test/runner.rb test/ruby/test_enum.rb in Ruby-3.3.0 tree after building it. This change would hide the issue for Ruby, but Ruby is likely still buggy (if using this "optimization" sorting larger arrays). [1]:https://kojipkgs.fedoraproject.org/work/tasks/9729/111889729/build.log Signed-off-by: Xi Ruoyao <xry111@xry111.site>
2024-01-17stdlib: Remove unused is_aligned function from qsort.cAdhemerval Zanella1-13/+0
Checked on x86_64-linux-gnu.
2024-01-16stdlib: Verify heapsort for two-element casesKuan-Wei Chiu1-3/+1
Adjust the testing approach to start from scenarios with only 2 elements, as insertion sort no longer handles such cases. Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-01-16stdlib: Fix heapsort for cases with exactly two elementsKuan-Wei Chiu1-1/+1
When malloc fails to allocate a buffer and falls back to heapsort, the current heapsort implementation does not perform sorting when there are exactly two elements. Heapsort is now skipped only when there is exactly one element. Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-01-15stdlib: Reinstate stable mergesort implementation on qsortAdhemerval Zanella4-441/+226
The mergesort removal from qsort implementation (commit 03bf8357e8) had the side-effect of making sorting nonstable. Although neither POSIX nor C standard specify that qsort should be stable, it seems that it has become an instance of Hyrum's law where multiple programs expect it. Also, the resulting introsort implementation is not faster than the previous mergesort (which makes the change even less appealing). This patch restores the previous mergesort implementation, with the exception of machinery that checks the resulting allocation against the _SC_PHYS_PAGES (it only adds complexity and the heuristic not always make sense depending on the system configuration and load). The alloca usage was replaced with a fixed-size buffer. For the fallback mechanism, the implementation uses heapsort. It is simpler than quicksort, and it does not suffer from adversarial inputs. With memory overcommit, it should be rarely triggered. The drawback is mergesort requires O(n) extra space, and since it is allocated with malloc the function is AS-signal-unsafe. It should be feasible to change it to use mmap, although I am not sure how urgent it is. The heapsort is also nonstable, so programs that require a stable sort would still be subject to this latent issue. The tst-qsort5 is removed since it will not create quicksort adversarial inputs with the current qsort_r implementation. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-01-05stdlib: Fix stdbit.h with -Wconversion for clangAdhemerval Zanella1-11/+12
With clang 14 and also with main the tst-stdbit-Wconversion issues the warnings: ../stdlib/stdbit.h:701:40: error: implicit conversion loses integer precision: 'int' to 'uint16_t' (aka 'unsigned short') [-Werror,-Wimplicit-int-conversion] return __x == 0 ? 0 : ((uint16_t) 1) << (__bw16_inline (__x) - 1); ~~~~~~ ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h:707:39: error: implicit conversion loses integer precision: 'int' to 'uint8_t' (aka 'unsigned char') [-Werror,-Wimplicit-int-conversion] return __x == 0 ? 0 : ((uint8_t) 1) << (__bw8_inline (__x) - 1); ~~~~~~ ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h:751:40: error: implicit conversion loses integer precision: 'int' to 'uint16_t' (aka 'unsigned short') [-Werror,-Wimplicit-int-conversion] return __x <= 1 ? 1 : ((uint16_t) 2) << (__bw16_inline (__x - 1) - 1); ~~~~~~ ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h:757:39: error: implicit conversion loses integer precision: 'int' to 'uint8_t' (aka 'unsigned char') [-Werror,-Wimplicit-int-conversion] return __x <= 1 ? 1 : ((uint8_t) 2) << (__bw8_inline (__x - 1) - 1); ~~~~~~ ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tst-stdbit-Wconversion.c:45:31: error: implicit conversion loses integer precision: 'unsigned short' to 'uint8_t' (aka 'unsigned char') [-Werror,-Wimplicit-int-conversion] (void) stdc_trailing_zeros (us); ~~~~~~~~~~~~~~~~~~~~~^~~ ../stdlib/stdbit.h:164:30: note: expanded from macro 'stdc_trailing_zeros' : stdc_trailing_zeros_uc (x)) ~~~~~~~~~~~~~~~~~~~~~~~~^~ ../stdlib/stdbit.h:191:52: note: expanded from macro 'stdc_trailing_zeros_uc' # define stdc_trailing_zeros_uc(x) (__ctz8_inline (x)) ~~~~~~~~~~~~~ ^ tst-stdbit-Wconversion.c:46:31: error: implicit conversion loses integer precision: 'unsigned int' to 'uint16_t' (aka 'unsigned short') [-Werror,-Wimplicit-int-conversion] (void) stdc_trailing_zeros (ui); ~~~~~~~~~~~~~~~~~~~~~^~~ ../stdlib/stdbit.h:163:48: note: expanded from macro 'stdc_trailing_zeros' : sizeof (x) == 2 ? stdc_trailing_zeros_us (x) \ ~~~~~~~~~~~~~~~~~~~~~~~~^~ ../stdlib/stdbit.h:192:53: note: expanded from macro 'stdc_trailing_zeros_us' # define stdc_trailing_zeros_us(x) (__ctz16_inline (x)) ~~~~~~~~~~~~~~ ^ tst-stdbit-Wconversion.c:46:31: error: implicit conversion loses integer precision: 'unsigned int' to 'uint8_t' (aka 'unsigned char') [-Werror,-Wimplicit-int-conversion] (void) stdc_trailing_zeros (ui); ~~~~~~~~~~~~~~~~~~~~~^~~ ../stdlib/stdbit.h:164:30: note: expanded from macro 'stdc_trailing_zeros' : stdc_trailing_zeros_uc (x)) ~~~~~~~~~~~~~~~~~~~~~~~~^~ ../stdlib/stdbit.h:191:52: note: expanded from macro 'stdc_trailing_zeros_uc' # define stdc_trailing_zeros_uc(x) (__ctz8_inline (x)) ~~~~~~~~~~~~~ ^ tst-stdbit-Wconversion.c:47:31: error: implicit conversion loses integer precision: 'unsigned long' to 'uint16_t' (aka 'unsigned short') [-Werror,-Wimplicit-int-conversion] (void) stdc_trailing_zeros (ul); ~~~~~~~~~~~~~~~~~~~~~^~~ ../stdlib/stdbit.h:163:48: note: expanded from macro 'stdc_trailing_zeros' : sizeof (x) == 2 ? stdc_trailing_zeros_us (x) \ ~~~~~~~~~~~~~~~~~~~~~~~~^~ ../stdlib/stdbit.h:192:53: note: expanded from macro 'stdc_trailing_zeros_us' # define stdc_trailing_zeros_us(x) (__ctz16_inline (x)) ~~~~~~~~~~~~~~ ^ [...] It seems to boiler down to __builtin_clz not having a variant for 8 or 16 bits. Fix it by explicit casting to the expected types. Although not strickly required for older gcc, using the same __pacify macro simpify the required code. Checked on x86_64-linux-gnu and i686-linux-gnu.
2024-01-05stdlib: Fix stdbit.h with -Wconversion for older gccAdhemerval Zanella1-8/+26
With gcc 6.5.0, 7.5.0, 8.5.0, and 9.5.0 the tst-stdbit-Wconversion issues the warnings: ../stdlib/stdbit.h: In function ‘__clo16_inline’: ../stdlib/stdbit.h:128:26: error: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value [-Werror=conversion] return __clz16_inline (~__x); ^ ../stdlib/stdbit.h: In function ‘__clo8_inline’: ../stdlib/stdbit.h:134:25: error: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Werror=conversion] return __clz8_inline (~__x); ^ ../stdlib/stdbit.h: In function ‘__cto16_inline’: ../stdlib/stdbit.h:232:26: error: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value [-Werror=conversion] return __ctz16_inline (~__x); ^ ../stdlib/stdbit.h: In function ‘__cto8_inline’: ../stdlib/stdbit.h:238:25: error: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Werror=conversion] return __ctz8_inline (~__x); ^ ../stdlib/stdbit.h: In function ‘__bf16_inline’: ../stdlib/stdbit.h:701:23: error: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value [-Werror=conversion] return __x == 0 ? 0 : ((uint16_t) 1) << (__bw16_inline (__x) - 1); ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h: In function ‘__bf8_inline’: ../stdlib/stdbit.h:707:23: error: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Werror=conversion] return __x == 0 ? 0 : ((uint8_t) 1) << (__bw8_inline (__x) - 1); ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h: In function ‘__bc16_inline’: ../stdlib/stdbit.h:751:59: error: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value [-Werror=conversion] return __x <= 1 ? 1 : ((uint16_t) 2) << (__bw16_inline (__x - 1) - 1); ^~~ ../stdlib/stdbit.h:751:23: error: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value [-Werror=conversion] return __x <= 1 ? 1 : ((uint16_t) 2) << (__bw16_inline (__x - 1) - 1); ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../stdlib/stdbit.h: In function ‘__bc8_inline’: ../stdlib/stdbit.h:757:57: error: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Werror=conversion] return __x <= 1 ? 1 : ((uint8_t) 2) << (__bw8_inline (__x - 1) - 1); ^~~ ../stdlib/stdbit.h:757:23: error: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Werror=c