Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_address.c
+++ new/usr/src/tools/smatch/src/smatch_address.c
1 1 /*
2 2 * Copyright (C) 2015 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 #include "smatch.h"
19 19 #include "smatch_slist.h"
20 20 #include "smatch_extra.h"
21 21
22 22 static bool is_non_null_array(struct expression *expr)
23 23 {
24 24 struct symbol *type;
25 25 struct symbol *sym;
26 26 struct symbol *tmp;
27 27 int i;
28 28
29 29 type = get_type(expr);
30 30 if (!type || type->type != SYM_ARRAY)
31 31 return 0;
32 32 if (expr->type == EXPR_SYMBOL)
33 33 return 1;
34 34 if (implied_not_equal(expr, 0))
35 35 return 1;
36 36
37 37 /* verify that it's not the first member of the struct */
38 38 if (expr->type != EXPR_DEREF || !expr->member)
39 39 return 0;
40 40 sym = expr_to_sym(expr);
41 41 if (!sym)
42 42 return 0;
43 43 type = get_real_base_type(sym);
44 44 if (!type || type->type != SYM_PTR)
45 45 return 0;
46 46 type = get_real_base_type(type);
47 47 if (type->type != SYM_STRUCT)
48 48 return 0;
49 49
50 50 i = 0;
51 51 FOR_EACH_PTR(type->symbol_list, tmp) {
52 52 i++;
53 53 if (!tmp->ident)
54 54 continue;
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
55 55 if (strcmp(expr->member->name, tmp->ident->name) == 0) {
56 56 if (i == 1)
57 57 return 0;
58 58 return 1;
59 59 }
60 60 } END_FOR_EACH_PTR(tmp);
61 61
62 62 return 0;
63 63 }
64 64
65 +static bool matches_anonymous_union(struct symbol *sym, const char *member_name)
66 +{
67 + struct symbol *type, *tmp;
68 +
69 + if (sym->ident)
70 + return false;
71 + type = get_real_base_type(sym);
72 + if (!type || type->type != SYM_UNION)
73 + return false;
74 +
75 + FOR_EACH_PTR(type->symbol_list, tmp) {
76 + if (tmp->ident &&
77 + strcmp(member_name, tmp->ident->name) == 0) {
78 + return true;
79 + }
80 + } END_FOR_EACH_PTR(tmp);
81 +
82 + return false;
83 +}
84 +
65 85 int get_member_offset(struct symbol *type, const char *member_name)
66 86 {
67 87 struct symbol *tmp;
68 88 int offset;
89 + int bits;
69 90
70 91 if (!type || type->type != SYM_STRUCT)
71 92 return -1;
72 93
94 + bits = 0;
73 95 offset = 0;
74 96 FOR_EACH_PTR(type->symbol_list, tmp) {
97 + if (bits_to_bytes(bits + type_bits(tmp)) > tmp->ctype.alignment) {
98 + offset += bits_to_bytes(bits);
99 + bits = 0;
100 + }
75 101 offset = ALIGN(offset, tmp->ctype.alignment);
76 102 if (tmp->ident &&
77 103 strcmp(member_name, tmp->ident->name) == 0) {
78 104 return offset;
79 105 }
80 - offset += type_bytes(tmp);
106 + if (matches_anonymous_union(tmp, member_name))
107 + return offset;
108 + if (!(type_bits(tmp) % 8) && type_bits(tmp) / 8 == type_bytes(tmp))
109 + offset += type_bytes(tmp);
110 + else
111 + bits += type_bits(tmp);
81 112 } END_FOR_EACH_PTR(tmp);
82 113 return -1;
83 114 }
84 115
85 116 int get_member_offset_from_deref(struct expression *expr)
86 117 {
87 118 struct symbol *type;
88 119 struct ident *member;
89 120 int offset;
90 121
91 122 if (expr->type != EXPR_DEREF) /* hopefully, this doesn't happen */
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
92 123 return -1;
93 124
94 125 if (expr->member_offset >= 0)
95 126 return expr->member_offset;
96 127
97 128 member = expr->member;
98 129 if (!member)
99 130 return -1;
100 131
101 132 type = get_type(expr->deref);
133 + if (type_is_ptr(type))
134 + type = get_real_base_type(type);
102 135 if (!type || type->type != SYM_STRUCT)
103 136 return -1;
104 137
105 138 offset = get_member_offset(type, member->name);
106 139 if (offset >= 0)
107 140 expr->member_offset = offset;
108 141 return offset;
109 142 }
110 143
111 -static struct range_list *filter_unknown_negatives(struct range_list *rl)
112 -{
113 - struct data_range *first;
114 - struct range_list *filter = NULL;
115 -
116 - first = first_ptr_list((struct ptr_list *)rl);
117 -
118 - if (sval_is_min(first->min) &&
119 - sval_is_negative(first->max) &&
120 - first->max.value == -1) {
121 - add_ptr_list(&filter, first);
122 - return rl_filter(rl, filter);
123 - }
124 -
125 - return rl;
126 -}
127 -
128 144 static void add_offset_to_pointer(struct range_list **rl, int offset)
129 145 {
130 146 sval_t min, max, remove, sval;
131 147 struct range_list *orig = *rl;
132 148
133 149 /*
134 150 * Ha ha. Treating zero as a special case means I'm correct at least a
135 151 * tiny fraction of the time. Which is better than nothing.
136 152 *
137 153 */
138 154 if (offset == 0)
139 155 return;
140 156
157 + if (is_unknown_ptr(orig))
158 + return;
159 +
141 160 /*
142 161 * This function doesn't necessarily work how you might expect...
143 162 *
144 163 * Say you have s64min-(-1),1-s64max and you add 8 then I guess what
145 164 * we want to say is maybe something like 9-s64max. This shows that the
146 165 * min it could be is 9 which is potentially useful information. But
147 166 * if we start with (-12),5000000-57777777 and we add 8 then we'd want
148 167 * the result to be (-4),5000008-57777777 but (-4),5000000-57777777 is
149 168 * also probably acceptable. If you start with s64min-s64max then the
150 169 * result should be 8-s64max.
151 170 *
152 171 */
153 172
154 173 /* We do the math on void pointer type, because this isn't "&v + 16" it
155 174 * is &v->sixteenth_byte.
156 175 */
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
157 176 orig = cast_rl(&ptr_ctype, orig);
158 177 min = sval_type_min(&ptr_ctype);
159 178 min.value = offset;
160 179 max = sval_type_max(&ptr_ctype);
161 180
162 181 if (!orig || is_whole_rl(orig)) {
163 182 *rl = alloc_rl(min, max);
164 183 return;
165 184 }
166 185
167 - orig = filter_unknown_negatives(orig);
168 - /*
169 - * FIXME: This is not really accurate but we're a bit screwed anyway
170 - * when we start doing pointer math with error pointers so it's probably
171 - * not important.
172 - *
173 - */
174 - if (sval_is_negative(rl_min(orig)))
175 - return;
176 -
177 186 /* no wrap around */
178 187 max.uvalue = rl_max(orig).uvalue;
179 188 if (max.uvalue > sval_type_max(&ptr_ctype).uvalue - offset) {
180 189 remove = sval_type_max(&ptr_ctype);
181 190 remove.uvalue -= offset;
182 191 orig = remove_range(orig, remove, max);
183 192 }
184 193
185 194 sval.type = &int_ctype;
186 195 sval.value = offset;
187 196
188 197 *rl = rl_binop(orig, '+', alloc_rl(sval, sval));
189 198 }
190 199
191 200 static struct range_list *where_allocated_rl(struct symbol *sym)
192 201 {
193 202 if (!sym)
194 203 return NULL;
195 204
196 - if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_STATIC)) {
197 - if (sym->initializer)
198 - return alloc_rl(data_seg_min, data_seg_max);
199 - else
200 - return alloc_rl(bss_seg_min, bss_seg_max);
201 - }
202 - return alloc_rl(stack_seg_min, stack_seg_max);
205 + return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
203 206 }
204 207
205 208 int get_address_rl(struct expression *expr, struct range_list **rl)
206 209 {
210 + struct expression *unop;
211 +
207 212 expr = strip_expr(expr);
208 213 if (!expr)
209 214 return 0;
210 215
211 216 if (expr->type == EXPR_STRING) {
212 - *rl = alloc_rl(text_seg_min, text_seg_max);
217 + *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
213 218 return 1;
214 219 }
215 220
216 - if (expr->type == EXPR_PREOP && expr->op == '&') {
217 - struct expression *unop;
221 + if (expr->type == EXPR_PREOP && expr->op == '&')
222 + expr = strip_expr(expr->unop);
223 + else {
224 + struct symbol *type;
218 225
219 - unop = strip_expr(expr->unop);
220 - if (unop->type == EXPR_SYMBOL) {
221 - *rl = where_allocated_rl(unop->symbol);
226 + type = get_type(expr);
227 + if (!type || type->type != SYM_ARRAY)
228 + return 0;
229 + }
230 +
231 + if (expr->type == EXPR_SYMBOL) {
232 + *rl = where_allocated_rl(expr->symbol);
233 + return 1;
234 + }
235 +
236 + if (is_array(expr)) {
237 + struct expression *array;
238 + struct expression *offset_expr;
239 + struct range_list *array_rl, *offset_rl, *bytes_rl, *res;
240 + struct symbol *type;
241 + sval_t bytes;
242 +
243 + array = get_array_base(expr);
244 + offset_expr = get_array_offset(expr);
245 +
246 + type = get_type(array);
247 + type = get_real_base_type(type);
248 + bytes.type = ssize_t_ctype;
249 + bytes.uvalue = type_bytes(type);
250 + bytes_rl = alloc_rl(bytes, bytes);
251 +
252 + get_absolute_rl(array, &array_rl);
253 + get_absolute_rl(offset_expr, &offset_rl);
254 +
255 + if (type_bytes(type)) {
256 + res = rl_binop(offset_rl, '*', bytes_rl);
257 + res = rl_binop(res, '+', array_rl);
258 + *rl = res;
259 + return true;
260 + }
261 +
262 + if (implied_not_equal(array, 0) ||
263 + implied_not_equal(offset_expr, 0)) {
264 + *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
222 265 return 1;
223 266 }
224 267
225 - if (unop->type == EXPR_DEREF) {
226 - int offset = get_member_offset_from_deref(unop);
268 + return 0;
269 + }
227 270
271 + if (expr->type == EXPR_DEREF && expr->member) {
272 + struct range_list *unop_rl;
273 + int offset;
274 +
275 + offset = get_member_offset_from_deref(expr);
276 + unop = strip_expr(expr->unop);
277 + if (unop->type == EXPR_PREOP && unop->op == '*')
228 278 unop = strip_expr(unop->unop);
229 - if (unop->type == EXPR_SYMBOL) {
230 - *rl = where_allocated_rl(unop->symbol);
231 - } else if (unop->type == EXPR_PREOP && unop->op == '*') {
232 - unop = strip_expr(unop->unop);
233 - get_absolute_rl(unop, rl);
234 - } else {
235 - return 0;
236 - }
237 279
280 + if (offset >= 0 &&
281 + get_implied_rl(unop, &unop_rl) &&
282 + !is_whole_rl(unop_rl)) {
283 + *rl = unop_rl;
238 284 add_offset_to_pointer(rl, offset);
239 285 return 1;
240 286 }
287 +
288 + if (implied_not_equal(unop, 0) || offset > 0) {
289 + *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
290 + return 1;
291 + }
241 292
242 293 return 0;
243 294 }
244 295
245 296 if (is_non_null_array(expr)) {
246 297 *rl = alloc_rl(array_min_sval, array_max_sval);
247 298 return 1;
248 299 }
249 300
250 301 return 0;
251 302 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX