diff --git a/clang/test/Analysis/out-of-bounds-constraint-check.c b/clang/test/Analysis/out-of-bounds-constraint-check.c index df48c8c170713..f20159da02997 100644 --- a/clang/test/Analysis/out-of-bounds-constraint-check.c +++ b/clang/test/Analysis/out-of-bounds-constraint-check.c @@ -1,112 +1,163 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,security.ArrayBound,debug.ExprInspection \ // RUN: -analyzer-config eagerly-assume=false -verify %s -void clang_analyzer_eval(int); -void clang_analyzer_printState(void); - -typedef typeof(sizeof(int)) size_t; -const char a[] = "abcd"; // extent: 5 bytes - -void symbolic_size_t_and_int0(size_t len) { - (void)a[len + 1]; // no-warning - // We infered that the 'len' must be in a specific range to make the previous indexing valid. - // len: [0,3] - clang_analyzer_eval(len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} - -void symbolic_size_t_and_int1(size_t len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} - -void symbolic_size_t_and_int2(size_t len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_uint_and_int0(unsigned len) { - (void)a[len + 1]; // no-warning - // len: [0,3] - clang_analyzer_eval(0 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} - -void symbolic_uint_and_int1(unsigned len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} -void symbolic_uint_and_int2(unsigned len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_int_and_int0(int len) { - (void)a[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} -void symbolic_int_and_int1(int len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} -void symbolic_int_and_int2(int len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_longlong_and_int0(long long len) { - (void)a[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} +// When the checker security.ArrayBound encounters an array subscript operation +// that _may be_ in bounds, it assumes that indexing _is_ in bound. This test +// file validates these assumptions. + +void clang_analyzer_value(int); + +// Simple case: memory area with a static extent. + +extern int FiveInts[5]; + +void int_plus_one(int len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} +} + +void int_neutral(int len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void int_minus_one(int len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void unsigned_plus_one(unsigned len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} +} + +void unsigned_neutral(unsigned len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void unsigned_minus_one(unsigned len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void ll_plus_one(long long len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} +} + +void ll_neutral(long long len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void ll_minus_one(long long len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void ull_plus_one(unsigned long long len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} +} + +void ull_neutral(unsigned long long len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void ull_minus_one(unsigned long long len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} } +// Also try the same with a dynamically allocated memory block, because in the +// past there were issues with the type/signedness of dynamic extent symbols. + +typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); -void symbolic_longlong_and_int0_dynamic_extent(long long len) { - char *b = malloc(5); - (void)b[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} - free(b); -} - -void symbolic_longlong_and_int1(long long len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} - -void symbolic_longlong_and_int2(long long len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} + +void dyn_int_plus_one(int len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} + free(p); +} + +void dyn_int_neutral(int len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_int_minus_one(int len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_unsigned_plus_one(unsigned len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} + free(p); +} + +void dyn_unsigned_neutral(unsigned len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_unsigned_minus_one(unsigned len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_ll_plus_one(long long len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} + free(p); +} + +void dyn_ll_neutral(long long len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_ll_minus_one(long long len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_ull_plus_one(unsigned long long len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} + free(p); +} + +void dyn_ull_neutral(unsigned long long len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_ull_minus_one(unsigned long long len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); } diff --git a/clang/test/Analysis/out-of-bounds.c b/clang/test/Analysis/out-of-bounds.c index 923797200d0b4..9f410e884d763 100644 --- a/clang/test/Analysis/out-of-bounds.c +++ b/clang/test/Analysis/out-of-bounds.c @@ -1,6 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,security.ArrayBound,debug.ExprInspection -verify %s - -void clang_analyzer_eval(int); +// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,security.ArrayBound -verify %s // Tests doing an out-of-bounds access after the end of an array using: // - constant integer index @@ -142,12 +140,6 @@ void test4(int x) { buf[x] = 1; // expected-warning{{Out of bound access to memory}} } -void test_assume_after_access(unsigned long x) { - int buf[100]; - buf[x] = 1; - clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} -} - // Don't warn when indexing below the start of a symbolic region's whose // base extent we don't know. int *get_symbolic(void); @@ -180,12 +172,6 @@ void test_extern_void(void) { p[1] = 42; // no-warning } -void test_assume_after_access2(unsigned long x) { - char buf[100]; - buf[x] = 1; - clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} -} - struct incomplete; char test_comparison_with_extent_symbol(struct incomplete *p) { // Previously this was reported as a (false positive) overflow error because