teak-llvm/clang/test/Sema/transpose-memset.c
Erik Pilkington b6e16ea006 [Sema] Add some compile time _FORTIFY_SOURCE diagnostics
These diagnose overflowing calls to subset of fortifiable functions. Some
functions, like sprintf or strcpy aren't supported right not, but we should
probably support these in the future. We previously supported this kind of
functionality with -Wbuiltin-memcpy-chk-size, but that diagnostic doesn't work
with _FORTIFY implementations that use wrapper functions. Also unlike that
diagnostic, we emit these warnings regardless of whether _FORTIFY_SOURCE is
actually enabled, which is nice for programs that don't enable the runtime
checks.

Why not just use diagnose_if, like Bionic does? We can get better diagnostics in
the compiler (i.e. mention the sizes), and we have the potential to diagnose
sprintf and strcpy which is impossible with diagnose_if (at least, in languages
that don't support C++14 constexpr). This approach also saves standard libraries
from having to add diagnose_if.

rdar://48006655

Differential revision: https://reviews.llvm.org/D58797

llvm-svn: 356397
2019-03-18 19:23:45 +00:00

62 lines
3.6 KiB
C

// RUN: %clang_cc1 -Wmemset-transposed-args -verify %s
// RUN: %clang_cc1 -xc++ -Wmemset-transposed-args -verify %s
#define memset(...) __builtin_memset(__VA_ARGS__)
#define bzero(x,y) __builtin_memset(x, 0, y)
#define real_bzero(x,y) __builtin_bzero(x,y)
int array[10];
int *ptr;
int main() {
memset(array, sizeof(array), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}}
memset(array, sizeof(array), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}} expected-warning{{'memset' will always overflow; destination buffer has size 40, but size argument is 255}}
memset(ptr, sizeof(ptr), 0); // expected-warning{{'size' argument to memset is '0'; did you mean to transpose the last two arguments?}} expected-note{{parenthesize the third argument to silence}}
memset(ptr, sizeof(*ptr) * 10, 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
memset(ptr, 10 * sizeof(int *), 1); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
memset(ptr, 10 * sizeof(int *) + 10, 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
memset(ptr, sizeof(char) * sizeof(int *), 0xff); // expected-warning{{setting buffer to a 'sizeof' expression; did you mean to transpose the last two arguments?}} expected-note{{cast the second argument to 'int' to silence}}
memset(array, sizeof(array), sizeof(array)); // Uh... fine I guess.
memset(array, 0, sizeof(array));
memset(ptr, 0, sizeof(int *) * 10);
memset(array, (int)sizeof(array), (0)); // no warning
memset(array, (int)sizeof(array), 32); // no warning
memset(array, 32, (0)); // no warning
memset(array, 0, 0); // no warning
bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}}
real_bzero(ptr, 0); // expected-warning{{'size' argument to bzero is '0'}} expected-note{{parenthesize the second argument to silence}}
}
void macros() {
#define ZERO 0
int array[10];
memset(array, 0xff, ZERO); // no warning
// Still emit a diagnostic for memsetting a sizeof expression:
memset(array, sizeof(array), ZERO); // expected-warning{{'sizeof'}} expected-note{{cast}}
bzero(array, ZERO); // no warning
real_bzero(array, ZERO); // no warning
#define NESTED_DONT_DIAG \
memset(array, 0xff, ZERO); \
real_bzero(array, ZERO);
NESTED_DONT_DIAG;
#define NESTED_DO_DIAG \
memset(array, 0xff, 0); \
real_bzero(array, 0)
NESTED_DO_DIAG; // expected-warning{{'size' argument to memset}} expected-warning{{'size' argument to bzero}} expected-note2{{parenthesize}}
#define FN_MACRO(p) \
memset(array, 0xff, p)
FN_MACRO(ZERO);
FN_MACRO(0); // FIXME: should we diagnose this?
__builtin_memset(array, 0, ZERO); // no warning
__builtin_bzero(array, ZERO);
__builtin_memset(array, 1, 0); // expected-warning{{'size' argument to memset}} // expected-note{{parenthesize}}
__builtin_bzero(array, 0); // expected-warning{{'size' argument to bzero}} // expected-note{{parenthesize}}
}