1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,security.ArrayBound,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=false -verify %s
// When the checker security.ArrayBound encounters an array subscript operation
// that _may be_ in bounds, it assumes that indexing _is_ in bound. This test
// file validates these assumptions.
void clang_analyzer_value(int);
// Simple case: memory area with a static extent.
extern int FiveInts[5];
void int_plus_one(int len) {
(void)FiveInts[len + 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}}
}
void int_neutral(int len) {
(void)FiveInts[len]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
}
void int_minus_one(int len) {
(void)FiveInts[len - 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
}
void unsigned_plus_one(unsigned len) {
(void)FiveInts[len + 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}}
}
void unsigned_neutral(unsigned len) {
(void)FiveInts[len]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
}
void unsigned_minus_one(unsigned len) {
(void)FiveInts[len - 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
}
void ll_plus_one(long long len) {
(void)FiveInts[len + 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}}
}
void ll_neutral(long long len) {
(void)FiveInts[len]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
}
void ll_minus_one(long long len) {
(void)FiveInts[len - 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
}
void ull_plus_one(unsigned long long len) {
(void)FiveInts[len + 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}}
}
void ull_neutral(unsigned long long len) {
(void)FiveInts[len]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
}
void ull_minus_one(unsigned long long len) {
(void)FiveInts[len - 1]; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
}
// Also try the same with a dynamically allocated memory block, because in the
// past there were issues with the type/signedness of dynamic extent symbols.
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
void free(void *);
void dyn_int_plus_one(int len) {
char *p = malloc(5);
p[len + 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}}
free(p);
}
void dyn_int_neutral(int len) {
char *p = malloc(5);
p[len] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
free(p);
}
void dyn_int_minus_one(int len) {
char *p = malloc(5);
p[len - 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
free(p);
}
void dyn_unsigned_plus_one(unsigned len) {
char *p = malloc(5);
p[len + 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}}
free(p);
}
void dyn_unsigned_neutral(unsigned len) {
char *p = malloc(5);
p[len] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
free(p);
}
void dyn_unsigned_minus_one(unsigned len) {
char *p = malloc(5);
p[len - 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
free(p);
}
void dyn_ll_plus_one(long long len) {
char *p = malloc(5);
p[len + 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}}
free(p);
}
void dyn_ll_neutral(long long len) {
char *p = malloc(5);
p[len] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
free(p);
}
void dyn_ll_minus_one(long long len) {
char *p = malloc(5);
p[len - 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
free(p);
}
void dyn_ull_plus_one(unsigned long long len) {
char *p = malloc(5);
p[len + 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}}
free(p);
}
void dyn_ull_neutral(unsigned long long len) {
char *p = malloc(5);
p[len] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}}
free(p);
}
void dyn_ull_minus_one(unsigned long long len) {
char *p = malloc(5);
p[len - 1] = 1; // no-warning
clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}}
free(p);
}
|