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 |
8 | void test1(int x) { |
9 | int buf[100]; |
10 | buf[100] = 1; // expected-warning{{Out of bound memory access}} |
11 | } |
12 | |
13 | void test1_ok(int x) { |
14 | int buf[100]; |
15 | buf[99] = 1; // no-warning |
16 | } |
17 | |
18 | const char test1_strings_underrun(int x) { |
19 | const char *mystr = "mary had a little lamb"; |
20 | return mystr[-1]; // expected-warning{{Out of bound memory access}} |
21 | } |
22 | |
23 | const char test1_strings_overrun(int x) { |
24 | const char *mystr = "mary had a little lamb"; |
25 | return mystr[1000]; // expected-warning{{Out of bound memory access}} |
26 | } |
27 | |
28 | const 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 |
37 | void test1_ptr(int x) { |
38 | int buf[100]; |
39 | int *p = buf; |
40 | p[101] = 1; // expected-warning{{Out of bound memory access}} |
41 | } |
42 | |
43 | void 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 |
53 | void 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 memory access}} |
58 | } |
59 | |
60 | void 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 | |
67 | void 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 memory access}} |
72 | } |
73 | |
74 | void 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 |
84 | void test2(int x) { |
85 | int buf[100]; |
86 | buf[-1] = 1; // expected-warning{{Out of bound memory access}} |
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 |
93 | void test2_ptr(int x) { |
94 | int buf[100]; |
95 | int *p = buf; |
96 | p[-1] = 1; // expected-warning{{Out of bound memory access}} |
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 |
103 | void test2_ptr_arith(int x) { |
104 | int buf[100]; |
105 | int *p = buf; |
106 | --p; |
107 | p[0] = 1; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}} |
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 |
114 | void test2_multi(int x) { |
115 | int buf[100][100]; |
116 | buf[0][-1] = 1; // expected-warning{{Out of bound memory access}} |
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 |
123 | void test2_multi_b(int x) { |
124 | int buf[100][100]; |
125 | buf[-1][0] = 1; // expected-warning{{Out of bound memory access}} |
126 | } |
127 | |
128 | void test2_multi_ok(int x) { |
129 | int buf[100][100]; |
130 | buf[0][0] = 1; // no-warning |
131 | } |
132 | |
133 | void test3(int x) { |
134 | int buf[100]; |
135 | if (x < 0) |
136 | buf[x] = 1; // expected-warning{{Out of bound memory access}} |
137 | } |
138 | |
139 | void test4(int x) { |
140 | int buf[100]; |
141 | if (x > 99) |
142 | buf[x] = 1; // expected-warning{{Out of bound memory access}} |
143 | } |
144 | |
145 | void 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(); |
154 | void test_index_below_symboloc() { |
155 | int *buf = get_symbolic(); |
156 | buf[-1] = 0; // no-warning; |
157 | } |
158 | |
159 | void test_incomplete_struct() { |
160 | extern struct incomplete incomplete; |
161 | int *p = (int *)&incomplete; |
162 | p[1] = 42; // no-warning |
163 | } |
164 | |
165 | void test_extern_void() { |
166 | extern void v; |
167 | int *p = (int *)&v; |
168 | p[1] = 42; // no-warning |
169 | } |
170 | |
171 | void test_assume_after_access2(unsigned long x) { |
172 | char buf[100]; |
173 | buf[x] = 1; |
174 | clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} |
175 | } |
176 | |
177 | |