blob: 1970cd658c42737f4e88bb138e6d4ca963243220 [file] [log] [blame]
// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,alpha.security.ArrayBoundV2,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
// Tests doing an out-of-bounds access after the end of an array using:
// - constant integer index
// - constant integer size for buffer
void test1(int x) {
int buf[100];
buf[100] = 1; // expected-warning{{Out of bound memory access}}
}
void test1_ok(int x) {
int buf[100];
buf[99] = 1; // no-warning
}
const char test1_strings_underrun(int x) {
const char *mystr = "mary had a little lamb";
return mystr[-1]; // expected-warning{{Out of bound memory access}}
}
const char test1_strings_overrun(int x) {
const char *mystr = "mary had a little lamb";
return mystr[1000]; // expected-warning{{Out of bound memory access}}
}
const char test1_strings_ok(int x) {
const char *mystr = "mary had a little lamb";
return mystr[5]; // no-warning
}
// Tests doing an out-of-bounds access after the end of an array using:
// - indirect pointer to buffer
// - constant integer index
// - constant integer size for buffer
void test1_ptr(int x) {
int buf[100];
int *p = buf;
p[101] = 1; // expected-warning{{Out of bound memory access}}
}
void test1_ptr_ok(int x) {
int buf[100];
int *p = buf;
p[99] = 1; // no-warning
}
// Tests doing an out-of-bounds access before the start of an array using:
// - indirect pointer to buffer, manipulated using simple pointer arithmetic
// - constant integer index
// - constant integer size for buffer
void test1_ptr_arith(int x) {
int buf[100];
int *p = buf;
p = p + 100;
p[0] = 1; // expected-warning{{Out of bound memory access}}
}
void test1_ptr_arith_ok(int x) {
int buf[100];
int *p = buf;
p = p + 99;
p[0] = 1; // no-warning
}
void test1_ptr_arith_bad(int x) {
int buf[100];
int *p = buf;
p = p + 99;
p[1] = 1; // expected-warning{{Out of bound memory access}}
}
void test1_ptr_arith_ok2(int x) {
int buf[100];
int *p = buf;
p = p + 99;
p[-1] = 1; // no-warning
}
// Tests doing an out-of-bounds access before the start of an array using:
// - constant integer index
// - constant integer size for buffer
void test2(int x) {
int buf[100];
buf[-1] = 1; // expected-warning{{Out of bound memory access}}
}
// Tests doing an out-of-bounds access before the start of an array using:
// - indirect pointer to buffer
// - constant integer index
// - constant integer size for buffer
void test2_ptr(int x) {
int buf[100];
int *p = buf;
p[-1] = 1; // expected-warning{{Out of bound memory access}}
}
// Tests doing an out-of-bounds access before the start of an array using:
// - indirect pointer to buffer, manipulated using simple pointer arithmetic
// - constant integer index
// - constant integer size for buffer
void test2_ptr_arith(int x) {
int buf[100];
int *p = buf;
--p;
p[0] = 1; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
}
// Tests doing an out-of-bounds access before the start of a multi-dimensional
// array using:
// - constant integer indices
// - constant integer sizes for the array
void test2_multi(int x) {
int buf[100][100];
buf[0][-1] = 1; // expected-warning{{Out of bound memory access}}
}
// Tests doing an out-of-bounds access before the start of a multi-dimensional
// array using:
// - constant integer indices
// - constant integer sizes for the array
void test2_multi_b(int x) {
int buf[100][100];
buf[-1][0] = 1; // expected-warning{{Out of bound memory access}}
}
void test2_multi_ok(int x) {
int buf[100][100];
buf[0][0] = 1; // no-warning
}
void test3(int x) {
int buf[100];
if (x < 0)
buf[x] = 1; // expected-warning{{Out of bound memory access}}
}
void test4(int x) {
int buf[100];
if (x > 99)
buf[x] = 1; // expected-warning{{Out of bound memory access}}
}
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 test_index_below_symboloc() {
int *buf = get_symbolic();
buf[-1] = 0; // no-warning;
}
void test_incomplete_struct() {
extern struct incomplete incomplete;
int *p = (int *)&incomplete;
p[1] = 42; // no-warning
}
void test_extern_void() {
extern void v;
int *p = (int *)&v;
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}}
}