1 // RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core,alpha.security.ArrayBoundV2 -verify %s
2 
3 // Tests doing an out-of-bounds access after the end of an array using:
4 // - constant integer index
5 // - constant integer size for buffer
test1(int x)6 void test1(int x) {
7   int buf[100];
8   buf[100] = 1; // expected-warning{{Out of bound memory access}}
9 }
10 
test1_ok(int x)11 void test1_ok(int x) {
12   int buf[100];
13   buf[99] = 1; // no-warning
14 }
15 
test1_strings_underrun(int x)16 const char test1_strings_underrun(int x) {
17   const char *mystr = "mary had a little lamb";
18   return mystr[-1]; // expected-warning{{Out of bound memory access}}
19 }
20 
test1_strings_overrun(int x)21 const char test1_strings_overrun(int x) {
22   const char *mystr = "mary had a little lamb";
23   return mystr[1000];  // expected-warning{{Out of bound memory access}}
24 }
25 
test1_strings_ok(int x)26 const char test1_strings_ok(int x) {
27   const char *mystr = "mary had a little lamb";
28   return mystr[5]; // no-warning
29 }
30 
31 // Tests doing an out-of-bounds access after the end of an array using:
32 // - indirect pointer to buffer
33 // - constant integer index
34 // - constant integer size for buffer
test1_ptr(int x)35 void test1_ptr(int x) {
36   int buf[100];
37   int *p = buf;
38   p[101] = 1; // expected-warning{{Out of bound memory access}}
39 }
40 
test1_ptr_ok(int x)41 void test1_ptr_ok(int x) {
42   int buf[100];
43   int *p = buf;
44   p[99] = 1; // no-warning
45 }
46 
47 // Tests doing an out-of-bounds access before the start of an array using:
48 // - indirect pointer to buffer, manipulated using simple pointer arithmetic
49 // - constant integer index
50 // - constant integer size for buffer
test1_ptr_arith(int x)51 void test1_ptr_arith(int x) {
52   int buf[100];
53   int *p = buf;
54   p = p + 100;
55   p[0] = 1; // expected-warning{{Out of bound memory access}}
56 }
57 
test1_ptr_arith_ok(int x)58 void test1_ptr_arith_ok(int x) {
59   int buf[100];
60   int *p = buf;
61   p = p + 99;
62   p[0] = 1; // no-warning
63 }
64 
test1_ptr_arith_bad(int x)65 void test1_ptr_arith_bad(int x) {
66   int buf[100];
67   int *p = buf;
68   p = p + 99;
69   p[1] = 1; // expected-warning{{Out of bound memory access}}
70 }
71 
test1_ptr_arith_ok2(int x)72 void test1_ptr_arith_ok2(int x) {
73   int buf[100];
74   int *p = buf;
75   p = p + 99;
76   p[-1] = 1; // no-warning
77 }
78 
79 // Tests doing an out-of-bounds access before the start of an array using:
80 // - constant integer index
81 // - constant integer size for buffer
test2(int x)82 void test2(int x) {
83   int buf[100];
84   buf[-1] = 1; // expected-warning{{Out of bound memory access}}
85 }
86 
87 // Tests doing an out-of-bounds access before the start of an array using:
88 // - indirect pointer to buffer
89 // - constant integer index
90 // - constant integer size for buffer
test2_ptr(int x)91 void test2_ptr(int x) {
92   int buf[100];
93   int *p = buf;
94   p[-1] = 1; // expected-warning{{Out of bound memory access}}
95 }
96 
97 // Tests doing an out-of-bounds access before the start of an array using:
98 // - indirect pointer to buffer, manipulated using simple pointer arithmetic
99 // - constant integer index
100 // - constant integer size for buffer
test2_ptr_arith(int x)101 void test2_ptr_arith(int x) {
102   int buf[100];
103   int *p = buf;
104   --p;
105   p[0] = 1; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
106 }
107 
108 // Tests doing an out-of-bounds access before the start of a multi-dimensional
109 // array using:
110 // - constant integer indices
111 // - constant integer sizes for the array
test2_multi(int x)112 void test2_multi(int x) {
113   int buf[100][100];
114   buf[0][-1] = 1; // expected-warning{{Out of bound memory access}}
115 }
116 
117 // Tests doing an out-of-bounds access before the start of a multi-dimensional
118 // array using:
119 // - constant integer indices
120 // - constant integer sizes for the array
test2_multi_b(int x)121 void test2_multi_b(int x) {
122   int buf[100][100];
123   buf[-1][0] = 1; // expected-warning{{Out of bound memory access}}
124 }
125 
test2_multi_ok(int x)126 void test2_multi_ok(int x) {
127   int buf[100][100];
128   buf[0][0] = 1; // no-warning
129 }
130 
131 // *** FIXME ***
132 // We don't get a warning here yet because our symbolic constraint solving
133 // doesn't handle:  (symbol * constant) < constant
test3(int x)134 void test3(int x) {
135   int buf[100];
136   if (x < 0)
137     buf[x] = 1;
138 }
139 
140 // *** FIXME ***
141 // We don't get a warning here yet because our symbolic constraint solving
142 // doesn't handle:  (symbol * constant) < constant
test4(int x)143 void test4(int x) {
144   int buf[100];
145   if (x > 99)
146     buf[x] = 1;
147 }
148 
149 // Don't warn when indexing below the start of a symbolic region's whose
150 // base extent we don't know.
151 int *get_symbolic();
test_index_below_symboloc()152 void test_index_below_symboloc() {
153   int *buf = get_symbolic();
154   buf[-1] = 0; // no-warning;
155 }
156 
test_incomplete_struct()157 void test_incomplete_struct() {
158   extern struct incomplete incomplete;
159   int *p = (int *)&incomplete;
160   p[1] = 42; // no-warning
161 }
162 
test_extern_void()163 void test_extern_void() {
164   extern void v;
165   int *p = (int *)&v;
166   p[1] = 42; // no-warning
167 }
168 
169