1 // RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,alpha.security.ArrayBoundV2,debug.ExprInspection -verify %s 2 3 void clang_analyzer_eval(int); 4 5 // Tests doing an out-of-bounds access after the end of an array using: 6 // - constant integer index 7 // - constant integer size for buffer test1(int x)8void test1(int x) { 9 int buf[100]; 10 buf[100] = 1; // expected-warning{{Out of bound access to memory}} 11 } 12 test1_ok(int x)13void test1_ok(int x) { 14 int buf[100]; 15 buf[99] = 1; // no-warning 16 } 17 test1_strings_underrun(int x)18const char test1_strings_underrun(int x) { 19 const char *mystr = "mary had a little lamb"; 20 return mystr[-1]; // expected-warning{{Out of bound access to memory}} 21 } 22 test1_strings_overrun(int x)23const char test1_strings_overrun(int x) { 24 const char *mystr = "mary had a little lamb"; 25 return mystr[1000]; // expected-warning{{Out of bound access to memory}} 26 } 27 test1_strings_ok(int x)28const char test1_strings_ok(int x) { 29 const char *mystr = "mary had a little lamb"; 30 return mystr[5]; // no-warning 31 } 32 33 // Tests doing an out-of-bounds access after the end of an array using: 34 // - indirect pointer to buffer 35 // - constant integer index 36 // - constant integer size for buffer test1_ptr(int x)37void test1_ptr(int x) { 38 int buf[100]; 39 int *p = buf; 40 p[101] = 1; // expected-warning{{Out of bound access to memory}} 41 } 42 test1_ptr_ok(int x)43void test1_ptr_ok(int x) { 44 int buf[100]; 45 int *p = buf; 46 p[99] = 1; // no-warning 47 } 48 49 // Tests doing an out-of-bounds access before the start of an array using: 50 // - indirect pointer to buffer, manipulated using simple pointer arithmetic 51 // - constant integer index 52 // - constant integer size for buffer test1_ptr_arith(int x)53void test1_ptr_arith(int x) { 54 int buf[100]; 55 int *p = buf; 56 p = p + 100; 57 p[0] = 1; // expected-warning{{Out of bound access to memory}} 58 } 59 test1_ptr_arith_ok(int x)60void test1_ptr_arith_ok(int x) { 61 int buf[100]; 62 int *p = buf; 63 p = p + 99; 64 p[0] = 1; // no-warning 65 } 66 test1_ptr_arith_bad(int x)67void test1_ptr_arith_bad(int x) { 68 int buf[100]; 69 int *p = buf; 70 p = p + 99; 71 p[1] = 1; // expected-warning{{Out of bound access to memory}} 72 } 73 test1_ptr_arith_ok2(int x)74void test1_ptr_arith_ok2(int x) { 75 int buf[100]; 76 int *p = buf; 77 p = p + 99; 78 p[-1] = 1; // no-warning 79 } 80 81 // Tests doing an out-of-bounds access before the start of an array using: 82 // - constant integer index 83 // - constant integer size for buffer test2(int x)84void test2(int x) { 85 int buf[100]; 86 buf[-1] = 1; // expected-warning{{Out of bound access to memory}} 87 } 88 89 // Tests doing an out-of-bounds access before the start of an array using: 90 // - indirect pointer to buffer 91 // - constant integer index 92 // - constant integer size for buffer test2_ptr(int x)93void test2_ptr(int x) { 94 int buf[100]; 95 int *p = buf; 96 p[-1] = 1; // expected-warning{{Out of bound access to memory}} 97 } 98 99 // Tests doing an out-of-bounds access before the start of an array using: 100 // - indirect pointer to buffer, manipulated using simple pointer arithmetic 101 // - constant integer index 102 // - constant integer size for buffer test2_ptr_arith(int x)103void test2_ptr_arith(int x) { 104 int buf[100]; 105 int *p = buf; 106 --p; 107 p[0] = 1; // expected-warning {{Out of bound access to memory preceding}} 108 } 109 110 // Tests doing an out-of-bounds access before the start of a multi-dimensional 111 // array using: 112 // - constant integer indices 113 // - constant integer sizes for the array test2_multi(int x)114void test2_multi(int x) { 115 int buf[100][100]; 116 buf[0][-1] = 1; // expected-warning{{Out of bound access to memory}} 117 } 118 119 // Tests doing an out-of-bounds access before the start of a multi-dimensional 120 // array using: 121 // - constant integer indices 122 // - constant integer sizes for the array test2_multi_b(int x)123void test2_multi_b(int x) { 124 int buf[100][100]; 125 buf[-1][0] = 1; // expected-warning{{Out of bound access to memory}} 126 } 127 test2_multi_ok(int x)128void test2_multi_ok(int x) { 129 int buf[100][100]; 130 buf[0][0] = 1; // no-warning 131 } 132 test3(int x)133void test3(int x) { 134 int buf[100]; 135 if (x < 0) 136 buf[x] = 1; // expected-warning{{Out of bound access to memory}} 137 } 138 test4(int x)139void test4(int x) { 140 int buf[100]; 141 if (x > 99) 142 buf[x] = 1; // expected-warning{{Out of bound access to memory}} 143 } 144 test_assume_after_access(unsigned long x)145void test_assume_after_access(unsigned long x) { 146 int buf[100]; 147 buf[x] = 1; 148 clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} 149 } 150 151 // Don't warn when indexing below the start of a symbolic region's whose 152 // base extent we don't know. 153 int *get_symbolic(void); test_underflow_symbolic(void)154void test_underflow_symbolic(void) { 155 int *buf = get_symbolic(); 156 buf[-1] = 0; // no-warning; 157 } 158 159 // But warn if we understand the internal memory layout of a symbolic region. 160 typedef struct { 161 int id; 162 char name[256]; 163 } user_t; 164 165 user_t *get_symbolic_user(void); test_underflow_symbolic_2()166char test_underflow_symbolic_2() { 167 user_t *user = get_symbolic_user(); 168 return user->name[-1]; // expected-warning{{Out of bound access to memory}} 169 } 170 test_incomplete_struct(void)171void test_incomplete_struct(void) { 172 extern struct incomplete incomplete; 173 int *p = (int *)&incomplete; 174 p[1] = 42; // no-warning 175 } 176 test_extern_void(void)177void test_extern_void(void) { 178 extern void v; 179 int *p = (int *)&v; 180 p[1] = 42; // no-warning 181 } 182 test_assume_after_access2(unsigned long x)183void test_assume_after_access2(unsigned long x) { 184 char buf[100]; 185 buf[x] = 1; 186 clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} 187 } 188 189 struct incomplete; test_comparison_with_extent_symbol(struct incomplete * p)190char test_comparison_with_extent_symbol(struct incomplete *p) { 191 // Previously this was reported as a (false positive) overflow error because 192 // the extent symbol of the area pointed by `p` was an unsigned and the '-1' 193 // was converted to its type by `evalBinOpNN`. 194 return ((char *)p)[-1]; // no-warning 195 } 196 197