Print this page
12724 update smatch to 0.6.1-rc1-il-5
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_capped.c
+++ new/usr/src/tools/smatch/src/smatch_capped.c
1 1 /*
2 2 * Copyright (C) 2011 Oracle. All rights reserved.
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 /*
19 19 * This is trying to make a list of the variables which
20 20 * have capped values. Sometimes we don't know what the
21 21 * cap is, for example if we are comparing variables but
22 22 * we don't know the values of the variables. In that
23 23 * case we only know that our variable is capped and we
24 24 * sort that information here.
25 25 */
26 26
27 27 #include "smatch.h"
28 28 #include "smatch_slist.h"
29 29 #include "smatch_extra.h"
30 30
31 31 static int my_id;
32 32
33 33 STATE(capped);
34 34 STATE(uncapped);
35 35
36 36 static void set_uncapped(struct sm_state *sm, struct expression *mod_expr)
37 37 {
38 38 set_state(my_id, sm->name, sm->sym, &uncapped);
39 39 }
40 40
41 41 static struct smatch_state *unmatched_state(struct sm_state *sm)
42 42 {
43 43 struct smatch_state *state;
44 44
45 45 state = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
46 46 if (state && !estate_is_whole(state))
47 47 return &capped;
48 48 return &uncapped;
49 49 }
50 50
51 51 static int is_capped_macro(struct expression *expr)
52 52 {
53 53 char *name;
54 54
55 55 name = get_macro_name(expr->pos);
56 56 if (!name)
57 57 return 0;
58 58
59 59 if (strcmp(name, "min") == 0)
60 60 return 1;
61 61 if (strcmp(name, "MIN") == 0)
62 62 return 1;
63 63 if (strcmp(name, "min_t") == 0)
64 64 return 1;
65 65
66 66 return 0;
67 67 }
68 68
69 69 int is_capped(struct expression *expr)
70 70 {
71 71 struct symbol *type;
72 72 sval_t dummy;
73 73
74 74 expr = strip_expr(expr);
75 75 while (expr && expr->type == EXPR_POSTOP) {
76 76 expr = strip_expr(expr->unop);
77 77 }
78 78 if (!expr)
79 79 return 0;
80 80
81 81 type = get_type(expr);
82 82 if (is_ptr_type(type))
83 83 return 0;
84 84 if (type == &bool_ctype)
85 85 return 0;
86 86 if (type_bits(type) >= 0 && type_bits(type) <= 2)
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
87 87 return 0;
88 88
89 89 if (get_hard_max(expr, &dummy))
90 90 return 1;
91 91
92 92 if (is_capped_macro(expr))
93 93 return 1;
94 94
95 95 if (expr->type == EXPR_BINOP) {
96 96 struct range_list *left_rl, *right_rl;
97 + sval_t sval;
97 98
98 - if (expr->op == '&')
99 + if (expr->op == '&' && !get_value(expr->right, &sval))
99 100 return 1;
100 101 if (expr->op == SPECIAL_RIGHTSHIFT)
102 + return 0;
103 + if (expr->op == '%' &&
104 + !get_value(expr->right, &sval) && is_capped(expr->right))
101 105 return 1;
102 - if (expr->op == '%' && is_capped(expr->right))
103 - return 1;
104 106 if (!is_capped(expr->left))
105 107 return 0;
106 108 if (expr->op == '/')
107 109 return 1;
108 110 if (!is_capped(expr->right))
109 111 return 0;
110 112 if (expr->op == '*') {
111 113 get_absolute_rl(expr->left, &left_rl);
112 114 get_absolute_rl(expr->right, &right_rl);
113 115 if (sval_is_negative(rl_min(left_rl)) ||
114 116 sval_is_negative(rl_min(right_rl)))
115 117 return 0;
116 118 }
117 119 return 1;
118 120 }
119 121 if (get_state_expr(my_id, expr) == &capped)
120 122 return 1;
121 123 return 0;
122 124 }
123 125
124 126 int is_capped_var_sym(const char *name, struct symbol *sym)
125 127 {
126 128 if (get_state(my_id, name, sym) == &capped)
127 129 return 1;
128 130 return 0;
129 131 }
130 132
131 133 void set_param_capped_data(const char *name, struct symbol *sym, char *key, char *value)
132 134 {
133 135 char fullname[256];
134 136
135 137 if (strncmp(key, "$", 1))
136 138 return;
137 139 snprintf(fullname, 256, "%s%s", name, key + 1);
138 140 set_state(my_id, fullname, sym, &capped);
139 141 }
140 142
141 143 static void match_condition(struct expression *expr)
142 144 {
143 145 struct expression *left, *right;
144 146 struct smatch_state *left_true = NULL;
145 147 struct smatch_state *left_false = NULL;
146 148 struct smatch_state *right_true = NULL;
147 149 struct smatch_state *right_false = NULL;
148 150 sval_t sval;
149 151
150 152
151 153 if (expr->type != EXPR_COMPARE)
152 154 return;
153 155
154 156 left = strip_expr(expr->left);
155 157 right = strip_expr(expr->right);
156 158
157 159 while (left->type == EXPR_ASSIGNMENT)
158 160 left = strip_expr(left->left);
159 161
160 162 /* If we're dealing with known expressions, that's for smatch_extra.c */
161 163 if (get_implied_value(left, &sval) ||
162 164 get_implied_value(right, &sval))
163 165 return;
164 166
165 167 switch (expr->op) {
166 168 case '<':
167 169 case SPECIAL_LTE:
168 170 case SPECIAL_UNSIGNED_LT:
169 171 case SPECIAL_UNSIGNED_LTE:
170 172 left_true = &capped;
171 173 right_false = &capped;
172 174 break;
173 175 case '>':
174 176 case SPECIAL_GTE:
175 177 case SPECIAL_UNSIGNED_GT:
176 178 case SPECIAL_UNSIGNED_GTE:
177 179 left_false = &capped;
178 180 right_true = &capped;
179 181 break;
180 182 case SPECIAL_EQUAL:
181 183 left_true = &capped;
182 184 right_true = &capped;
183 185 break;
184 186 case SPECIAL_NOTEQUAL:
185 187 left_false = &capped;
186 188 right_false = &capped;
187 189 break;
188 190
189 191 default:
190 192 return;
191 193 }
192 194
193 195 set_true_false_states_expr(my_id, left, left_true, left_false);
194 196 set_true_false_states_expr(my_id, right, right_true, right_false);
195 197 }
196 198
197 199 static void match_assign(struct expression *expr)
198 200 {
199 201 struct symbol *type;
200 202
201 203 type = get_type(expr);
202 204 if (is_ptr_type(type))
203 205 return;
204 206 if (type == &bool_ctype)
205 207 return;
206 208 if (type_bits(type) >= 0 && type_bits(type) <= 2)
207 209 return;
208 210
209 211 if (is_capped(expr->right)) {
210 212 set_state_expr(my_id, expr->left, &capped);
211 213 } else {
212 214 if (get_state_expr(my_id, expr->left))
213 215 set_state_expr(my_id, expr->left, &uncapped);
214 216 }
215 217 }
216 218
217 219 static void match_caller_info(struct expression *expr)
218 220 {
219 221 struct expression *tmp;
220 222 sval_t sval;
221 223 int i;
222 224
223 225 i = -1;
224 226 FOR_EACH_PTR(expr->args, tmp) {
225 227 i++;
226 228 if (get_implied_value(tmp, &sval))
227 229 continue;
228 230 if (!is_capped(tmp))
229 231 continue;
230 232 sql_insert_caller_info(expr, CAPPED_DATA, i, "$", "1");
231 233 } END_FOR_EACH_PTR(tmp);
232 234 }
233 235
234 236 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
235 237 {
236 238 struct smatch_state *estate;
237 239 sval_t sval;
238 240
239 241 if (sm->state != &capped)
240 242 return;
241 243 estate = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
242 244 if (estate_get_single_value(estate, &sval))
243 245 return;
244 246 sql_insert_caller_info(call, CAPPED_DATA, param, printed_name, "1");
245 247 }
246 248
247 249 static void print_return_implies_capped(int return_id, char *return_ranges, struct expression *expr)
248 250 {
249 251 struct smatch_state *orig, *estate;
250 252 struct sm_state *sm;
251 253 struct symbol *ret_sym;
252 254 const char *param_name;
253 255 char *return_str;
254 256 int param;
255 257 sval_t sval;
256 258 bool return_found = false;
257 259
258 260 expr = strip_expr(expr);
259 261 return_str = expr_to_str(expr);
260 262 ret_sym = expr_to_sym(expr);
261 263
262 264 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
263 265 if (sm->state != &capped)
264 266 continue;
265 267
266 268 param = get_param_num_from_sym(sm->sym);
267 269 if (param < 0)
268 270 continue;
269 271
270 272 estate = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
271 273 if (estate_get_single_value(estate, &sval))
272 274 continue;
273 275
274 276 orig = get_state_stree(get_start_states(), my_id, sm->name, sm->sym);
275 277 if (orig == &capped && !param_was_set_var_sym(sm->name, sm->sym))
276 278 continue;
277 279
278 280 param_name = get_param_name(sm);
279 281 if (!param_name)
280 282 continue;
281 283
282 284 sql_insert_return_states(return_id, return_ranges, CAPPED_DATA,
283 285 param, param_name, "1");
284 286 } END_FOR_EACH_SM(sm);
285 287
286 288 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
287 289 if (!ret_sym)
288 290 break;
289 291 if (sm->state != &capped)
290 292 continue;
291 293 if (ret_sym != sm->sym)
292 294 continue;
293 295
294 296 estate = __get_state(SMATCH_EXTRA, sm->name, sm->sym);
295 297 if (estate_get_single_value(estate, &sval))
296 298 continue;
297 299
298 300 param_name = state_name_to_param_name(sm->name, return_str);
299 301 if (!param_name)
300 302 continue;
301 303 if (strcmp(param_name, "$") == 0)
302 304 return_found = true;
303 305 sql_insert_return_states(return_id, return_ranges, CAPPED_DATA,
304 306 -1, param_name, "1");
305 307 } END_FOR_EACH_SM(sm);
306 308
307 309 if (return_found)
308 310 goto free_string;
309 311
310 312 if (option_project == PROJ_KERNEL && get_function() &&
311 313 strstr(get_function(), "nla_get_"))
312 314 sql_insert_return_states(return_id, return_ranges, CAPPED_DATA,
313 315 -1, "$", "1");
314 316
315 317 free_string:
316 318 free_string(return_str);
317 319 }
318 320
319 321 static void db_return_states_capped(struct expression *expr, int param, char *key, char *value)
320 322 {
321 323 char *name;
322 324 struct symbol *sym;
323 325
324 326 name = return_state_to_var_sym(expr, param, key, &sym);
325 327 if (!name || !sym)
326 328 goto free;
327 329
328 330 set_state(my_id, name, sym, &capped);
329 331 free:
330 332 free_string(name);
331 333 }
332 334
333 335 void register_capped(int id)
334 336 {
335 337 my_id = id;
336 338
337 339 add_unmatched_state_hook(my_id, &unmatched_state);
338 340 select_caller_info_hook(set_param_capped_data, CAPPED_DATA);
339 341 add_hook(&match_condition, CONDITION_HOOK);
340 342 add_hook(&match_assign, ASSIGNMENT_HOOK);
341 343 add_modification_hook(my_id, &set_uncapped);
342 344
343 345 add_hook(&match_caller_info, FUNCTION_CALL_HOOK);
344 346 add_member_info_callback(my_id, struct_member_callback);
345 347
346 348 add_split_return_callback(print_return_implies_capped);
347 349 select_return_states_hook(CAPPED_DATA, &db_return_states_capped);
348 350 }
↓ open down ↓ |
235 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX