diff options
author | Joseph Myers <joseph@codesourcery.com> | 2020-10-30 22:25:42 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2020-10-30 22:25:42 +0000 |
commit | 548f467fa14ffe7d955beeb31b30e2aeae4467e0 (patch) | |
tree | 110b58e4d121c3650cb103a883f02091d06c5e84 | |
parent | 882774658cb8daee4c16677a3fd674f6052cc157 (diff) | |
download | glibc-548f467fa14ffe7d955beeb31b30e2aeae4467e0.zip glibc-548f467fa14ffe7d955beeb31b30e2aeae4467e0.tar.gz glibc-548f467fa14ffe7d955beeb31b30e2aeae4467e0.tar.bz2 |
Avoid -Wstringop-overflow warning in pthread_cleanup_push macros
GCC 11 introduces a -Wstringop-overflow warning for calls to functions
with an array argument passed as a pointer to memory not large enough
for that array. This includes the __sigsetjmp calls from
pthread_cleanup_push macros, because those use a structure in
__pthread_unwind_buf_t, which has a common initial subsequence with
jmp_buf but does not include the saved signal mask; this is OK in this
case because the second argument to __sigsetjmp is 0 so the signal
mask is not accessed.
To avoid this warning, use a function alias __sigsetjmp_cancel with
first argument an array of exactly the type used in the calls to the
function, if using GCC 11 or later. With older compilers, continue to
use __sigsetjmp with a cast, to avoid any issues with compilers
predating the returns_twice attribute not applying the same special
handling to __sigsetjmp_cancel as to __sigsetjmp.
Tested with build-many-glibcs.py for arm-linux-gnueabi that this fixes
the testsuite build failures.
-rw-r--r-- | misc/sys/cdefs.h | 8 | ||||
-rw-r--r-- | sysdeps/nptl/pthread.h | 37 |
2 files changed, 35 insertions, 10 deletions
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 6b9763a..86906c2 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -563,4 +563,12 @@ _Static_assert (0, "IEEE 128-bits long double requires redirection on this platf # define __attr_access(x) #endif +/* Specify that a function such as setjmp or vfork may return + twice. */ +#if __GNUC_PREREQ (4, 1) +# define __attribute_returns_twice__ __attribute__ ((__returns_twice__)) +#else +# define __attribute_returns_twice__ /* Ignore. */ +#endif + #endif /* sys/cdefs.h */ diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h index d4194da..3a34d82 100644 --- a/sysdeps/nptl/pthread.h +++ b/sysdeps/nptl/pthread.h @@ -512,13 +512,15 @@ extern void pthread_testcancel (void); /* Cancellation handling with integration into exception handling. */ +struct __cancel_jmp_buf_tag +{ + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; +}; + typedef struct { - struct - { - __jmp_buf __cancel_jmp_buf; - int __mask_was_saved; - } __cancel_jmp_buf[1]; + struct __cancel_jmp_buf_tag __cancel_jmp_buf[1]; void *__pad[4]; } __pthread_unwind_buf_t __attribute__ ((__aligned__)); @@ -658,8 +660,8 @@ __pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ void *__cancel_arg = (arg); \ - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ - __cancel_buf.__cancel_jmp_buf, 0); \ + int __not_first_call = __sigsetjmp_cancel (__cancel_buf.__cancel_jmp_buf, \ + 0); \ if (__glibc_unlikely (__not_first_call)) \ { \ __cancel_routine (__cancel_arg); \ @@ -693,8 +695,8 @@ extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ void *__cancel_arg = (arg); \ - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ - __cancel_buf.__cancel_jmp_buf, 0); \ + int __not_first_call = __sigsetjmp_cancel (__cancel_buf.__cancel_jmp_buf, \ + 0); \ if (__glibc_unlikely (__not_first_call)) \ { \ __cancel_routine (__cancel_arg); \ @@ -730,9 +732,24 @@ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) ; #endif -/* Function used in the macros. */ +/* Function used in the macros. Calling __sigsetjmp, with its first + argument declared as an array, results in a -Wstringop-overflow + warning from GCC 11 because struct pthread_unwind_buf is smaller + than jmp_buf. The calls from the macros have __SAVEMASK set to 0, + so nothing beyond the common prefix is used and this warning is a + false positive. Use an alias with its first argument declared to + use the type in the macros if possible to avoid this warning. */ +#if __GNUC_PREREQ (11, 0) +extern int __REDIRECT_NTHNL (__sigsetjmp_cancel, + (struct __cancel_jmp_buf_tag __env[1], + int __savemask), + __sigsetjmp) __attribute_returns_twice__; +#else +# define __sigsetjmp_cancel(env, savemask) \ + __sigsetjmp ((struct __jmp_buf_tag *) (void *) (env), (savemask)) extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROWNL; +#endif /* Mutex handling. */ |