
Size-type inconsistency (signedness) causes confusion and even bugs. For example when signed compared to unsigned the result might not be expected. Summary of this commit: Related APIs changes: 1. getDynamicExtent() returns signed version of extent; 2. Add getDynamicElementCountWithOffset() for offset version of element count; 3. getElementExtent() could be 0, add defensive checking for getDynamicElementCount(), if element is of zero-length, try ConstantArrayType::getSize() as element count; Related checker changes: 1. ArrayBoundCheckerV2: add testcase for signed <-> unsigned comparison from type-inconsistency results by getDynamicExtent() 2. ExprInspection: use more general API to report more results Fixes https://github.com/llvm/llvm-project/issues/64920 Reviewed By: donat.nagy, steakhal Differential Revision: https://reviews.llvm.org/D158499
113 lines
4.4 KiB
C
113 lines
4.4 KiB
C
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,alpha.security.ArrayBoundV2,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}}
|
|
}
|
|
|
|
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}}
|
|
}
|