From 88b504b7a8c5affb0ffa97990d22af2b199e36ed Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 26 Oct 2021 14:34:16 -0600 Subject: [PATCH] Detect overflow by atomic functions [PR102453]. Resolves: PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed gcc/ChangeLog: PR middle-end/102453 * gimple-ssa-warn-access.cc (pass_waccess::check_atomic_builtin): New. (pass_waccess::check_atomic_builtin): Call it. gcc/testsuite/ChangeLog: PR middle-end/102453 * gcc.dg/Warray-bounds-90.c: New test. * gcc.dg/Wstringop-overflow-77.c: New test. * gcc.dg/Wstringop-overflow-78.c: New test. * gcc.dg/Wstringop-overflow-79.c: New test. * gcc.dg/Wstringop-overflow-80.c: New test. * c-c++-common/gomp/atomic-4.c: Avoid an out-of-bounds access. --- gcc/gimple-ssa-warn-access.cc | 91 +++- gcc/testsuite/c-c++-common/gomp/atomic-4.c | 2 +- gcc/testsuite/gcc.dg/Warray-bounds-90.c | 147 ++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-77.c | 516 ++++++++++++++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-78.c | 518 +++++++++++++++++++ gcc/testsuite/gcc.dg/Wstringop-overflow-79.c | 70 +++ gcc/testsuite/gcc.dg/Wstringop-overflow-80.c | 70 +++ 7 files changed, 1410 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-90.c create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-77.c create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-78.c create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-79.c create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-80.c diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 00c3ea0f5050..88a2e72645b7 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -2109,6 +2109,9 @@ private: pass_waccess (pass_waccess &) = delete; void operator= (pass_waccess &) = delete; + /* Check a call to an atomic built-in function. */ + bool check_atomic_builtin (gcall *); + /* Check a call to a built-in function. */ bool check_builtin (gcall *); @@ -2681,6 +2684,87 @@ pass_waccess::check_memop_access (gimple *stmt, tree dest, tree src, tree size) srcsize, dstsize, data.mode, &data); } +/* Check a call STMT to an atomic or sync built-in. */ + +bool +pass_waccess::check_atomic_builtin (gcall *stmt) +{ + tree callee = gimple_call_fndecl (stmt); + if (!callee) + return false; + + /* The size in bytes of the access by the function, and the number + of the second argument to check (if any). */ + unsigned bytes = 0, arg2 = UINT_MAX; + + switch (DECL_FUNCTION_CODE (callee)) + { +#define BUILTIN_ACCESS_SIZE_FNSPEC(N) \ + BUILT_IN_ATOMIC_LOAD_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_ADD_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_SUB_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_OR_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_AND_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_XOR_ ## N: \ + case BUILT_IN_SYNC_FETCH_AND_NAND_ ## N: \ + case BUILT_IN_SYNC_ADD_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_SUB_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_OR_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_AND_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_XOR_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_NAND_AND_FETCH_ ## N: \ + case BUILT_IN_SYNC_LOCK_TEST_AND_SET_ ## N: \ + case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_ ## N: \ + case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_ ## N: \ + case BUILT_IN_SYNC_LOCK_RELEASE_ ## N: \ + case BUILT_IN_ATOMIC_EXCHANGE_ ## N: \ + case BUILT_IN_ATOMIC_STORE_ ## N: \ + case BUILT_IN_ATOMIC_ADD_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_SUB_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_AND_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_NAND_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_XOR_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_OR_FETCH_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_ADD_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_SUB_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_AND_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_NAND_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_OR_ ## N: \ + case BUILT_IN_ATOMIC_FETCH_XOR_ ## N: \ + bytes = N; \ + break; \ + case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_ ## N: \ + bytes = N; \ + arg2 = 1 + + case BUILTIN_ACCESS_SIZE_FNSPEC (1); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (2); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (4); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (8); + break; + case BUILTIN_ACCESS_SIZE_FNSPEC (16); + break; + + default: + return false; + } + + tree size = build_int_cstu (sizetype, bytes); + tree dst = gimple_call_arg (stmt, 0); + check_memop_access (stmt, dst, NULL_TREE, size); + + if (arg2 != UINT_MAX) + { + tree dst = gimple_call_arg (stmt, arg2); + check_memop_access (stmt, dst, NULL_TREE, size); + } + + return true; +} + /* Check call STMT to a built-in function for invalid accesses. Return true if a call has been handled. */ @@ -2795,10 +2879,11 @@ pass_waccess::check_builtin (gcall *stmt) } default: - return false; + if (check_atomic_builtin (stmt)) + return true; + break; } - - return true; + return false; } /* Returns the type of the argument ARGNO to function with type FNTYPE diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-4.c b/gcc/testsuite/c-c++-common/gomp/atomic-4.c index 7f27370d535b..5dd18d1d5fa0 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-4.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-4.c @@ -8,7 +8,7 @@ int *bar(void); void f1(void) { #pragma omp atomic - a[4] += 1; + a[3] += 1; #pragma omp atomic *p += 1; #pragma omp atomic diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-90.c b/gcc/testsuite/gcc.dg/Warray-bounds-90.c new file mode 100644 index 000000000000..2e72a3daa1c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-90.c @@ -0,0 +1,147 @@ +/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed + Verify that out-of-bounds accesses by atomic functions are diagnosed. + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#ifndef __cplusplus +# define bool _Bool +#endif + +#define load __atomic_load +#define store __atomic_store +#define add_fetch __atomic_add_fetch +#define sub_fetch __atomic_sub_fetch +#define and_fetch __atomic_and_fetch +#define or_fetch __atomic_or_fetch +#define xor_fetch __atomic_xor_fetch +#define nand_fetch __atomic_nand_fetch + +typedef __SIZE_TYPE__ size_t; + +void sink (void*, ...); +#define sink(...) sink (0, __VA_ARGS__) + +extern _Bool eb; +extern char ec; +extern short int esi; +extern int ei; +extern long int eli; +extern long long int elli; + +extern const _Bool ecb; +extern const char ecc; +extern const short int ecsi; +extern const int eci; +extern const long int ecli; +extern const long long int eclli; + +extern _Atomic _Bool eab; +extern _Atomic char eac; +extern _Atomic short int easi; +extern _Atomic int eai; +extern _Atomic long int eali; +extern _Atomic long long int ealli; + +extern _Atomic const _Bool eacb; +extern _Atomic const char eacc; +extern _Atomic const short int eacsi; +extern _Atomic const int eaci; +extern _Atomic const long int eacli; +extern _Atomic const long long int eaclli; + + +void nowarn_atomic_load (void) +{ + load (&eacb, &eb, 0); + load (&eacc, &ec, 0); + load (&eacsi, &esi, 0); + load (&eaci, &ei, 0); + load (&eacli, &eli, 0); + load (&eaclli, &elli, 0); +} + + +void warn_atomic_load_note (void) +{ + int i; // { dg-message "'i'" } + + int *pi = (int*)((char*)&i + 1); + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + sink (&i); + + pi = (int*)((char*)&i + 2); + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + sink (&i); + + pi = &i + 1; + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + sink (&i); +} + + +void warn_atomic_load (void) +{ + bool *pb = &eb + 1; + load (&eacb, pb, 0); // { dg-warning "-Warray-bounds" } + + char *pc = &ec + 1; + load (&eacc, pc, 0); // { dg-warning "-Warray-bounds" } + + short *psi = (short*)((char*)&esi + 1); + load (&eacsi, psi, 0); // { dg-warning "-Warray-bounds" } + psi = (short*)((char*)&esi + 2); + load (&eacsi, psi, 0); // { dg-warning "-Warray-bounds" } + + int *pi = (int*)((char*)&ei + 1); + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + pi = (int*)((char*)&ei + 2); + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + pi = (int*)((char*)&ei + sizeof ei); + load (&eaci, pi, 0); // { dg-warning "-Warray-bounds" } + + long *pli = (long*)((char*)&eli + 1); + load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" } + pli = (long*)((char*)&eli + 1); + load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" } + pli = &eli + 1; + load (&eacli, pli, 0); // { dg-warning "-Warray-bounds" } + + long long *plli = (long long*)((char*)&elli + 1); + load (&eaclli, plli, 0); // { dg-warning "-Warray-bounds" } + plli = (long long*)((char*)&elli + 1); + load (&eacli, plli, 0); // { dg-warning "-Warray-bounds" } + plli = &elli + 1; + load (&eaclli, plli, 0); // { dg-warning "-Warray-bounds" } +} + + +void warn_atomic_store (void) +{ + const bool *pb = &eb + 1; + store (&eab, pb, 0); // { dg-warning "-Warray-bounds" } + + const char *pc = &ec + 1; + store (&eac, pc, 0); // { dg-warning "-Warray-bounds" } + + const short *psi = (const short*)((const char*)&ecsi + 1); + store (&easi, psi, 0); // { dg-warning "-Warray-bounds" } + psi = (const short*)((const char*)&esi + 2); + store (&easi, psi, 0); // { dg-warning "-Warray-bounds" } + + const int *pi = (const int*)((const char*)&eci + 1); + store (&eai, pi, 0); // { dg-warning "-Warray-bounds" } + pi = (const int*)((const char*)&ei + 2); + store (&eai, pi, 0); // { dg-warning "-Warray-bounds" } + pi = (const int*)((const char*)&ei + sizeof ei); + store (&eai, pi, 0); // { dg-warning "-Warray-bounds" } + + const long *pli = (const long*)((const char*)&eli + 1); + store (&eali, pli, 0); // { dg-warning "-Warray-bounds" } + pli = (const long*)((const char*)&eli + sizeof (eli)); + store (&eali, pli, 0); // { dg-warning "-Warray-bounds" } + + const long long *plli = (const long long*)((const char*)&elli + 1); + store (&ealli, plli, 0); // { dg-warning "-Warray-bounds" } + plli = (const long long*)((const char*)&elli + sizeof elli); + store (&ealli, plli, 0); // { dg-warning "-Warray-bounds" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c new file mode 100644 index 000000000000..732f56849ae8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-77.c @@ -0,0 +1,516 @@ +/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed + Verify that out-of-bounds accesses by atomic functions are diagnosed with + optimization disabled. + { dg-do compile } + { dg-options "-O0 -Wall -ftrack-macro-expansion=0" } */ + +#ifndef __cplusplus +# define bool _Bool +#endif + +#define add_fetch(p, q) __atomic_add_fetch (p, q, 0) +#define sub_fetch(p, q) __atomic_sub_fetch (p, q, 0) +#define and_fetch(p, q) __atomic_and_fetch (p, q, 0) +#define or_fetch(p, q) __atomic_or_fetch (p, q, 0) +#define xor_fetch(p, q) __atomic_xor_fetch (p, q, 0) +#define nand_fetch(p, q) __atomic_nand_fetch (p, q, 0) +#define exchange(p, q, r) __atomic_exchange (p, q, r, 0) +#define exchange_n(p, n) __atomic_exchange_n (p, n, 0) +#define cmpxchg(p, q, r) __atomic_compare_exchange (p, q, r, 0, 0, 0) + +typedef __SIZE_TYPE__ size_t; + +void sink (void*, ...); +#define sink(...) sink (0, __VA_ARGS__) + +extern _Bool eb; +extern char ec; +extern short int esi; +extern int ei; +extern long int eli; +extern long long int elli; + +extern const _Bool ecb; +extern const char ecc; +extern const short int ecsi; +extern const int eci; +extern const long int ecli; +extern const long long int eclli; + +extern _Atomic _Bool eab; +extern _Atomic char eac; +extern _Atomic short int easi; +extern _Atomic int eai; +extern _Atomic long int eali; +extern _Atomic long long int ealli; + +extern _Atomic const _Bool eacb; +extern _Atomic const char eacc; +extern _Atomic const short int eacsi; +extern _Atomic const int eaci; +extern _Atomic const long int eacli; +extern _Atomic const long long int eaclli; + + +void nowarn_atomic_add_fetch (void) +{ + add_fetch (&eac, ecc); + add_fetch (&easi, esi); + add_fetch (&eai, ei); + add_fetch (&eali, eli); + add_fetch (&ealli, elli); +} + + +void warn_atomic_add_fetch (void) +{ + _Atomic char *pc = &eac + 1; + add_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + add_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_sub_fetch (void) +{ + _Atomic char *pc = &eac; + sub_fetch (pc, ecc); + + _Atomic short *psi = &easi; + sub_fetch (psi, esi); + + _Atomic int *pi = &eai; + sub_fetch (pi, ei); + + _Atomic long *pli = &eali; + sub_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + sub_fetch (plli, elli); +} + + +void warn_atomic_sub_fetch (void) +{ + _Atomic char *pc = &eac + 1; + sub_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + sub_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_and_fetch (void) +{ + _Atomic char *pc = &eac; + and_fetch (pc, ecc); + + _Atomic short *psi = &easi; + and_fetch (psi, esi); + + _Atomic int *pi = &eai; + and_fetch (pi, ei); + + _Atomic long *pli = &eali; + and_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + and_fetch (plli, elli); +} + + +void warn_atomic_and_fetch (void) +{ + _Atomic char *pc = &eac + 1; + and_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + and_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_or_fetch (void) +{ + _Atomic char *pc = &eac; + or_fetch (pc, ecc); + + _Atomic short *psi = &easi; + or_fetch (psi, esi); + + _Atomic int *pi = &eai; + or_fetch (pi, ei); + + _Atomic long *pli = &eali; + or_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + or_fetch (plli, elli); +} + + +void warn_atomic_or_fetch (void) +{ + _Atomic char *pc = &eac + 1; + or_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + or_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_xor_fetch (void) +{ + _Atomic char *pc = &eac; + xor_fetch (pc, ecc); + + _Atomic short *psi = &easi; + xor_fetch (psi, esi); + + _Atomic int *pi = &eai; + xor_fetch (pi, ei); + + _Atomic long *pli = &eali; + xor_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + xor_fetch (plli, elli); +} + + +void warn_atomic_xor_fetch (void) +{ + _Atomic char *pc = &eac + 1; + xor_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 1); + xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&eali + 1); + xor_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_nand_fetch (void) +{ + _Atomic char *pc = &eac; + nand_fetch (pc, ecc); + + _Atomic short *psi = &easi; + nand_fetch (psi, esi); + + _Atomic int *pi = &eai; + nand_fetch (pi, ei); + + _Atomic long *pli = &eali; + nand_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + nand_fetch (plli, elli); +} + + +void warn_atomic_nand_fetch (void) +{ + _Atomic char *pc = &eac + 1; + nand_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 1); + nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&eai + 1); + nand_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +void nowarn_atomic_exchange (void) +{ + char rc; + _Atomic char *pc = &eac; + exchange (pc, &ecc, &rc); + + short rsi; + _Atomic short *psi = &easi; + exchange (psi, &esi, &rsi); + + int ri; + _Atomic int *pi = &eai; + exchange (pi, &ei, &ri); + + long rli; + _Atomic long *pli = &eali; + exchange (pli, &eli, &rli); + + long long rlli; + _Atomic long long *plli = &ealli; + exchange (plli, &elli, &rlli); + + sink (&rc, &rsi, &ri, &rli, &rlli); +} + +void warn_atomic_exchange (void) +{ + char rc; + _Atomic char *pc = &eac + 1; + exchange (pc, &ecc, &rc); // { dg-warning "-Wstringop-overflow" } + + short rsi[2]; + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + exchange (psi, &ecsi, rsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + exchange (psi, &ecsi, rsi + 1); // { dg-warning "-Wstringop-overflow" } + + int ri[3]; + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + exchange (pi, &eci, ri); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + exchange (pi, &eci, ri + 1); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + exchange (pi, &eci, ri + 2); // { dg-warning "-Wstringop-overflow" } + + long rli[3]; + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + exchange (pli, &ecli, rli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + exchange (pli, &ecli, rli + 1); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + exchange (pli, &ecli, rli + 2); // { dg-warning "-Wstringop-overflow" } + + long long rlli[3]; + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + exchange (plli, &eclli, rlli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + exchange (plli, &eclli, rlli + 1); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + exchange (plli, &eclli, rlli + 2); // { dg-warning "-Wstringop-overflow" } + + sink (&rc, rsi, ri, rli, rlli); +} + + +void nowarn_atomic_exchange_n (_Atomic unsigned char *pauc, + _Atomic unsigned short *pausi, + _Atomic unsigned int *paui, + _Atomic unsigned long *pauli, + _Atomic unsigned long long *paulli) +{ + char rc = exchange_n (&eac, ecc); + short rsi = exchange_n (&easi, esi); + int ri = exchange_n (&eai, ei); + long rli = exchange_n (&eali, eli); + long long rlli = exchange_n (&ealli, elli); + + sink (rc, rsi, ri, rli, rlli); + + char ruc = exchange_n (pauc, ecc); + short rusi = exchange_n (pausi, esi); + int rui = exchange_n (paui, ei); + long ruli = exchange_n (pauli, eli); + long long rulli = exchange_n (paulli, elli); + + sink (ruc, rusi, rui, ruli, rulli); +} + + +void warn_atomic_exchange_n (void) +{ + _Atomic char *pc = &eac + 1; + char rc = exchange_n (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + short rsi[2]; + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + rsi[0] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + rsi[1] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" } + + int ri[3]; + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + ri[0] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + ri[1] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + ri[2] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + + long rli[3]; + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + rli[0] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + rli[1] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + rli[2] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + + long long rlli[3]; + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + rlli[0] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + rlli[1] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + rlli[2] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + + sink (&rc, rsi, ri, rli, rlli); +} + + +void warn_atomic_compare_exchange (void) +{ + _Atomic char *pc = &eac + 1; + cmpxchg (pc, &ec, &ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c new file mode 100644 index 000000000000..a25a418ed76f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-78.c @@ -0,0 +1,518 @@ +/* PR middle-end/102453 - buffer overflow by atomic built-ins not diagnosed + Verify that out-of-bounds accesses by atomic functions are diagnosed with + optimization enabled. + { dg-do compile } + { dg-options "-O3 -Wall -ftrack-macro-expansion=0" } */ + +#ifndef __cplusplus +# define bool _Bool +#endif + +#define NOIPA __attribute__ ((noipa)) + +#define add_fetch(p, q) __atomic_add_fetch (p, q, 0) +#define sub_fetch(p, q) __atomic_sub_fetch (p, q, 0) +#define and_fetch(p, q) __atomic_and_fetch (p, q, 0) +#define or_fetch(p, q) __atomic_or_fetch (p, q, 0) +#define xor_fetch(p, q) __atomic_xor_fetch (p, q, 0) +#define nand_fetch(p, q) __atomic_nand_fetch (p, q, 0) +#define exchange(p, q, r) __atomic_exchange (p, q, r, 0) +#define exchange_n(p, n) __atomic_exchange_n (p, n, 0) +#define cmpxchg(p, q, r) __atomic_compare_exchange (p, q, r, __COUNTER__, 0, 0) + +typedef __SIZE_TYPE__ size_t; + +void sink (void*, ...); +#define sink(...) sink (0, __VA_ARGS__) + +extern _Bool eb; +extern char ec; +extern short int esi; +extern int ei; +extern long int eli; +extern long long int elli; + +extern const _Bool ecb; +extern const char ecc; +extern const short int ecsi; +extern const int eci; +extern const long int ecli; +extern const long long int eclli; + +extern _Atomic _Bool eab; +extern _Atomic char eac; +extern _Atomic short int easi; +extern _Atomic int eai; +extern _Atomic long int eali; +extern _Atomic long long int ealli; + +extern _Atomic const _Bool eacb; +extern _Atomic const char eacc; +extern _Atomic const short int eacsi; +extern _Atomic const int eaci; +extern _Atomic const long int eacli; +extern _Atomic const long long int eaclli; + + +NOIPA void nowarn_atomic_add_fetch (void) +{ + add_fetch (&eac, ecc); + add_fetch (&easi, esi); + add_fetch (&eai, ei); + add_fetch (&eali, eli); + add_fetch (&ealli, elli); +} + + +NOIPA void warn_atomic_add_fetch (void) +{ + _Atomic char *pc = &eac + 1; + add_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + add_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + add_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + add_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + add_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + add_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_sub_fetch (void) +{ + _Atomic char *pc = &eac; + sub_fetch (pc, ecc); + + _Atomic short *psi = &easi; + sub_fetch (psi, esi); + + _Atomic int *pi = &eai; + sub_fetch (pi, ei); + + _Atomic long *pli = &eali; + sub_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + sub_fetch (plli, elli); +} + + +NOIPA void warn_atomic_sub_fetch (void) +{ + _Atomic char *pc = &eac + 1; + sub_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + sub_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + sub_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + sub_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + sub_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + sub_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_and_fetch (void) +{ + _Atomic char *pc = &eac; + and_fetch (pc, ecc); + + _Atomic short *psi = &easi; + and_fetch (psi, esi); + + _Atomic int *pi = &eai; + and_fetch (pi, ei); + + _Atomic long *pli = &eali; + and_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + and_fetch (plli, elli); +} + + +NOIPA void warn_atomic_and_fetch (void) +{ + _Atomic char *pc = &eac + 1; + and_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + and_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + and_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + and_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + and_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + and_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_or_fetch (void) +{ + _Atomic char *pc = &eac; + or_fetch (pc, ecc); + + _Atomic short *psi = &easi; + or_fetch (psi, esi); + + _Atomic int *pi = &eai; + or_fetch (pi, ei); + + _Atomic long *pli = &eali; + or_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + or_fetch (plli, elli); +} + + +NOIPA void warn_atomic_or_fetch (void) +{ + _Atomic char *pc = &eac + 1; + or_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + or_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + or_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + or_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + or_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + or_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_xor_fetch (void) +{ + _Atomic char *pc = &eac; + xor_fetch (pc, ecc); + + _Atomic short *psi = &easi; + xor_fetch (psi, esi); + + _Atomic int *pi = &eai; + xor_fetch (pi, ei); + + _Atomic long *pli = &eali; + xor_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + xor_fetch (plli, elli); +} + + +NOIPA void warn_atomic_xor_fetch (void) +{ + _Atomic char *pc = &eac + 1; + xor_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 1); + xor_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + xor_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + xor_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&eali + 1); + xor_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + xor_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_nand_fetch (void) +{ + _Atomic char *pc = &eac; + nand_fetch (pc, ecc); + + _Atomic short *psi = &easi; + nand_fetch (psi, esi); + + _Atomic int *pi = &eai; + nand_fetch (pi, ei); + + _Atomic long *pli = &eali; + nand_fetch (pli, eli); + + _Atomic long long *plli = &ealli; + nand_fetch (plli, elli); +} + + +NOIPA void warn_atomic_nand_fetch (void) +{ + _Atomic char *pc = &eac + 1; + nand_fetch (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 1); + nand_fetch (psi, esi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + nand_fetch (pi, ei); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + nand_fetch (pli, eli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&eai + 1); + nand_fetch (plli, eali); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + nand_fetch (plli, elli); // { dg-warning "-Wstringop-overflow" } +} + + +NOIPA void nowarn_atomic_exchange (void) +{ + char rc; + _Atomic char *pc = &eac; + exchange (pc, &ecc, &rc); + + short rsi; + _Atomic short *psi = &easi; + exchange (psi, &esi, &rsi); + + int ri; + _Atomic int *pi = &eai; + exchange (pi, &ei, &ri); + + long rli; + _Atomic long *pli = &eali; + exchange (pli, &eli, &rli); + + long long rlli; + _Atomic long long *plli = &ealli; + exchange (plli, &elli, &rlli); + + sink (&rc, &rsi, &ri, &rli, &rlli); +} + +NOIPA void warn_atomic_exchange (void) +{ + char rc; + _Atomic char *pc = &eac + 1; + exchange (pc, &ecc, &rc); // { dg-warning "-Wstringop-overflow" } + + short rsi[2]; + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + exchange (psi, &ecsi, rsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + exchange (psi, &ecsi, rsi + 1); // { dg-warning "-Wstringop-overflow" } + + int ri[3]; + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + exchange (pi, &eci, ri); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + exchange (pi, &eci, ri + 1); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + exchange (pi, &eci, ri + 2); // { dg-warning "-Wstringop-overflow" } + + long rli[3]; + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + exchange (pli, &ecli, rli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + exchange (pli, &ecli, rli + 1); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + exchange (pli, &ecli, rli + 2); // { dg-warning "-Wstringop-overflow" } + + long long rlli[3]; + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + exchange (plli, &eclli, rlli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + exchange (plli, &eclli, rlli + 1); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + exchange (plli, &eclli, rlli + 2); // { dg-warning "-Wstringop-overflow" } + + sink (&rc, rsi, ri, rli, rlli); +} + + +NOIPA void nowarn_atomic_exchange_n (_Atomic unsigned char *pauc, + _Atomic unsigned short *pausi, + _Atomic unsigned int *paui, + _Atomic unsigned long *pauli, + _Atomic unsigned long long *paulli) +{ + char rc = exchange_n (&eac, ecc); + short rsi = exchange_n (&easi, esi); + int ri = exchange_n (&eai, ei); + long rli = exchange_n (&eali, eli); + long long rlli = exchange_n (&ealli, elli); + + sink (rc, rsi, ri, rli, rlli); + + char ruc = exchange_n (pauc, ecc); + short rusi = exchange_n (pausi, esi); + int rui = exchange_n (paui, ei); + long ruli = exchange_n (pauli, eli); + long long rulli = exchange_n (paulli, elli); + + sink (ruc, rusi, rui, ruli, rulli); +} + + +NOIPA void warn_atomic_exchange_n (void) +{ + _Atomic char *pc = &eac + 1; + char rc = exchange_n (pc, ecc); // { dg-warning "-Wstringop-overflow" } + + short rsi[2]; + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + rsi[0] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + rsi[1] = exchange_n (psi, ecsi); // { dg-warning "-Wstringop-overflow" } + + int ri[3]; + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + ri[0] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + ri[1] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + ri[2] = exchange_n (pi, eci); // { dg-warning "-Wstringop-overflow" } + + long rli[3]; + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + rli[0] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + rli[1] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + rli[2] = exchange_n (pli, ecli); // { dg-warning "-Wstringop-overflow" } + + long long rlli[3]; + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + rlli[0] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + rlli[1] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + rlli[2] = exchange_n (plli, eclli); // { dg-warning "-Wstringop-overflow" } + + sink (&rc, rsi, ri, rli, rlli); +} + + +NOIPA void warn_atomic_compare_exchange (void) +{ + _Atomic char *pc = &eac + 1; + cmpxchg (pc, &ec, &ecc); // { dg-warning "-Wstringop-overflow" } + + _Atomic short *psi = (_Atomic short*)((char*)&easi + 1); + cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" } + psi = (_Atomic short*)((char*)&easi + 2); + cmpxchg (psi, &esi, &ecsi); // { dg-warning "-Wstringop-overflow" } + + _Atomic int *pi = (_Atomic int*)((char*)&eai + 1); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + 2); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + pi = (_Atomic int*)((char*)&eai + sizeof eai); + cmpxchg (pi, &ei, &eci); // { dg-warning "-Wstringop-overflow" } + + _Atomic long *pli = (_Atomic long*)((char*)&eali + 1); + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + pli = (_Atomic long*)((char*)&eali + 1); + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + pli = &eali + 1; + cmpxchg (pli, &eli, &ecli); // { dg-warning "-Wstringop-overflow" } + + _Atomic long long *plli = (_Atomic long long*)((char*)&ealli + 1); + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } + plli = (_Atomic long long*)((char*)&ealli + 1); + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } + plli = &ealli + 1; + cmpxchg (plli, &elli, &eclli); // { dg-warning "-Wstringop-overflow" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c new file mode 100644 index 000000000000..15eb26fbdb73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-79.c @@ -0,0 +1,70 @@ +/* Verify that a separate note is issued for each offset into the same + object after a -Wstringop-overflow. Since all arguments are known + the test doesn't need optimization. Wstringop-overflow-79.c verifies + they're also issued at -O2. + { dg-do compile } + { dg-options "-O0 -Wno-array-bounds" } */ + +extern char a[8]; // dg-message at offset \\\[3, 6] into destination object 'a'" "note 1" } + // dg-message at offset \\\[5, 8] into destination object 'a'" "note 2" { target *-*-* } .-1 } + +void test_2_notes (int i) +{ + char *p = i ? a + 3 : a + 5; + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char b[8]; // dg-message at offset \\\[3, 6] into destination object 'b'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'b'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'b'" "note 3" { target *-*-* } .-2 } + +void test_3_notes (int i) +{ + char *p = i < 0 ? b + 3 : 0 < i ? b + 5 : b + 4; + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char c[8]; // dg-message at offset \\\[3, 6] into destination object 'c'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'c'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 } + // dg-message at offset \\\[6, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 } + +void test_4_notes (int i) +{ + char *p; + if (i < -1) + p = c + 3; + else if (i < 0) + p = c + 4; + else if (0 < i) + p = c + 6; + else + p = c + 5; + + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char d[8]; // dg-message at offset \\\[3, 6] into destination object 'd'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'd'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'd'" "note 3" { target *-*-* } .-2 } + // dg-message at offset \\\[6, 8] into destination object 'd'" "note 3" { target *-*-* } .-3 } + // dg-message at offset \\\[7, 8] into destination object 'd'" "note 3" { target *-*-* } .-4 } + +void test_5_notes (int i) +{ + char *p; + switch (i) + { + case -9: p = d + 3; break; + case -5: p = d + 4; break; + case 0: p = d + 5; break; + case 3: p = d + 6; break; + case 4: p = d + 7; break; + default: return; + } + + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c new file mode 100644 index 000000000000..1628c2f0159c --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-80.c @@ -0,0 +1,70 @@ +/* Verify that a separate note is issued for each offset into the same + object after a -Wstringop-overflow. Even though the warnings don't + need optimization the test enables it to verify they're still issued + with it. Wstringop-overflow-78.c verifies they're issued at -O0. + { dg-do compile } + { dg-options "-O2 -Wno-array-bounds" } */ + +extern char a[8]; // dg-message at offset \\\[3, 6] into destination object 'a'" "note 1" } + // dg-message at offset \\\[5, 8] into destination object 'a'" "note 2" { target *-*-* } .-1 } + +void test_2_notes (int i) +{ + char *p = i ? a + 3 : a + 5; + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char b[8]; // dg-message at offset \\\[3, 6] into destination object 'b'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'b'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'b'" "note 3" { target *-*-* } .-2 } + +void test_3_notes (int i) +{ + char *p = i < 0 ? b + 3 : 0 < i ? b + 5 : b + 4; + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char c[8]; // dg-message at offset \\\[3, 6] into destination object 'c'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'c'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 } + // dg-message at offset \\\[6, 8] into destination object 'c'" "note 3" { target *-*-* } .-2 } + +void test_4_notes (int i) +{ + char *p; + if (i < -1) + p = c + 3; + else if (i < 0) + p = c + 4; + else if (0 < i) + p = c + 6; + else + p = c + 5; + + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} + + +extern char d[8]; // dg-message at offset \\\[3, 6] into destination object 'd'" "note 1" } + // dg-message at offset \\\[4, 7] into destination object 'd'" "note 2" { target *-*-* } .-1 } + // dg-message at offset \\\[5, 8] into destination object 'd'" "note 3" { target *-*-* } .-2 } + // dg-message at offset \\\[6, 8] into destination object 'd'" "note 3" { target *-*-* } .-3 } + // dg-message at offset \\\[7, 8] into destination object 'd'" "note 3" { target *-*-* } .-4 } + +void test_5_notes (int i) +{ + char *p; + switch (i) + { + case -9: p = d + 3; break; + case -5: p = d + 4; break; + case 0: p = d + 5; break; + case 3: p = d + 6; break; + case 4: p = d + 7; break; + default: return; + } + + __builtin_memset (p, 0, 7); // { dg-warning "-Wstringop-overflow" } +} -- 2.47.2