Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_stored_conditions.c
+++ new/usr/src/tools/smatch/src/smatch_stored_conditions.c
1 1 /*
2 2 * Copyright (C) 2014 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 /*
19 19 * Keep a record of all the things we have tested for so that we know when we
20 20 * test for it again. For example, if we have code like this:
21 21 *
22 22 * if (foo & FLAG)
23 23 * lock();
24 24 *
25 25 * ...
26 26 *
27 27 * if (foo & FLAG)
28 28 * unlock();
29 29 *
30 30 * That's the end goal at least. But actually implementing the flow of that
31 31 * requires quite a bit of work because if "foo" changes the condition needs to
32 32 * be retested and smatch_implications.c needs to be updated.
33 33 *
34 34 * For now, I just record the conditions and use it to see if we test for NULL
35 35 * twice.
36 36 *
37 37 */
38 38
39 39 #include "smatch.h"
40 40 #include "smatch_slist.h"
41 41
42 42 static int my_id;
43 43 static int link_id;
44 44
45 45 static struct smatch_state *alloc_link_state(struct expression_list *expr_list)
46 46 {
47 47 struct expression *tmp;
48 48 struct smatch_state *state;
49 49 static char buf[256];
50 50 char *name;
51 51 int i;
52 52
53 53 state = __alloc_smatch_state(0);
54 54
55 55 i = 0;
56 56 FOR_EACH_PTR(expr_list, tmp) {
57 57 name = expr_to_str(tmp);
58 58 if (!i++) {
59 59 snprintf(buf, sizeof(buf), "%s", name);
60 60 } else {
61 61 append(buf, ", ", sizeof(buf));
62 62 append(buf, name, sizeof(buf));
63 63 }
64 64 free_string(name);
65 65 } END_FOR_EACH_PTR(tmp);
66 66
67 67 state->name = alloc_sname(buf);
68 68 state->data = expr_list;
69 69 return state;
70 70 }
71 71
72 72 static struct expression_list *clone_expression_list(struct expression_list *list)
73 73 {
74 74 struct expression_list *ret = NULL;
75 75 struct expression *expr;
76 76
77 77 FOR_EACH_PTR(list, expr) {
78 78 add_ptr_list(&ret, expr);
79 79 } END_FOR_EACH_PTR(expr);
80 80
81 81 return ret;
82 82 }
83 83
84 84 static void insert_expression(struct expression_list **list, struct expression *expr)
85 85 {
86 86 struct expression *tmp;
87 87
88 88 FOR_EACH_PTR(*list, tmp) {
89 89 if (tmp == expr)
90 90 return;
91 91 } END_FOR_EACH_PTR(tmp);
92 92
93 93 add_ptr_list(list, expr);
94 94 }
95 95
96 96 static struct smatch_state *merge_links(struct smatch_state *s1, struct smatch_state *s2)
97 97 {
98 98 struct expression_list *list, *expr_list;
99 99 struct expression *expr;
100 100
101 101 expr_list = clone_expression_list(s1->data);
102 102
103 103 list = s2->data;
104 104 FOR_EACH_PTR(list, expr) {
105 105 insert_expression(&expr_list, expr);
106 106 } END_FOR_EACH_PTR(expr);
107 107
108 108 return alloc_link_state(expr_list);
109 109 }
110 110
111 111 static void save_link_var_sym(const char *var, struct symbol *sym, struct expression *condition)
112 112 {
113 113 struct smatch_state *old_state, *new_state;
114 114 struct expression_list *expr_list;
115 115
116 116 old_state = get_state(link_id, var, sym);
117 117 expr_list = clone_expression_list(old_state ? old_state->data : NULL);
118 118
119 119 insert_expression(&expr_list, condition);
120 120
121 121 new_state = alloc_link_state(expr_list);
122 122 set_state(link_id, var, sym, new_state);
123 123 }
124 124
125 125 static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
126 126 {
127 127 struct expression_list *expr_list;
128 128 struct expression *tmp;
129 129 char *name;
130 130
131 131 expr_list = sm->state->data;
132 132
133 133 FOR_EACH_PTR(expr_list, tmp) {
134 134 name = expr_to_str(tmp);
135 135 set_state(my_id, name, NULL, &undefined);
136 136 free_string(name);
137 137 } END_FOR_EACH_PTR(tmp);
138 138 set_state(link_id, sm->name, sm->sym, &undefined);
139 139 }
140 140
141 141 static struct smatch_state *alloc_state(struct expression *expr, int is_true)
142 142 {
143 143 struct smatch_state *state;
144 144
145 145 state = __alloc_smatch_state(0);
146 146 if (is_true)
147 147 state->name = alloc_sname("true");
148 148 else
149 149 state->name = alloc_sname("false");
150 150 state->data = expr;
151 151 return state;
152 152 }
153 153
154 154 static void store_all_links(struct expression *expr, struct expression *condition)
155 155 {
156 156 char *var;
157 157 struct symbol *sym;
158 158
159 159 expr = strip_expr(expr);
160 160
161 161 if (is_array(expr)) {
162 162 var = expr_to_known_chunk_sym(expr, &sym);
163 163 if (var)
164 164 save_link_var_sym(var, sym, condition);
165 165 }
166 166
167 167 switch (expr->type) {
168 168 case EXPR_COMPARE:
169 169 case EXPR_BINOP:
170 170 store_all_links(expr->left, condition);
171 171 store_all_links(expr->right, condition);
172 172 return;
173 173 case EXPR_VALUE:
174 174 return;
175 175 }
176 176
177 177 var = expr_to_var_sym(expr, &sym);
178 178 if (!var || !sym)
179 179 goto free;
180 180 save_link_var_sym(var, sym, condition);
181 181 free:
182 182 free_string(var);
183 183 }
184 184
185 185 static int condition_too_complicated(struct expression *expr)
186 186 {
187 187 if (get_complication_score(expr) > 2)
188 188 return 1;
189 189 return 0;
190 190 }
191 191
192 192 void __stored_condition(struct expression *expr)
193 193 {
194 194 struct smatch_state *true_state, *false_state;
195 195 char *name;
196 196 sval_t val;
197 197
198 198 if (get_value(expr, &val))
199 199 return;
200 200
201 201 if (condition_too_complicated(expr))
202 202 return;
203 203
204 204 name = expr_to_str(expr);
205 205 if (!name)
206 206 return;
207 207 true_state = alloc_state(expr, TRUE);
208 208 false_state = alloc_state(expr, FALSE);
209 209 set_true_false_states(my_id, name, NULL, true_state, false_state);
210 210 store_all_links(expr, expr);
211 211 free_string(name);
212 212 }
213 213
214 214 struct smatch_state *get_stored_condition(struct expression *expr)
215 215 {
216 216 struct smatch_state *state;
217 217 char *name;
218 218
219 219 name = expr_to_str(expr);
220 220 if (!name)
221 221 return NULL;
222 222
223 223 state = get_state(my_id, name, NULL);
224 224 free_string(name);
225 225 return state;
226 226 }
227 227
228 228 struct expression_list *get_conditions(struct expression *expr)
229 229 {
230 230 struct smatch_state *state;
↓ open down ↓ |
230 lines elided |
↑ open up ↑ |
231 231
232 232 state = get_state_expr(link_id, expr);
233 233 if (!state)
234 234 return NULL;
235 235 return state->data;
236 236 }
237 237
238 238 void register_stored_conditions(int id)
239 239 {
240 240 my_id = id;
241 + set_dynamic_states(my_id);
241 242 }
242 243
243 244 void register_stored_conditions_links(int id)
244 245 {
245 246 link_id = id;
247 + db_ignore_states(link_id);
248 + set_dynamic_states(link_id);
246 249 add_merge_hook(link_id, &merge_links);
247 250 add_modification_hook(link_id, &match_link_modify);
248 251 }
249 252
250 253 #define RECURSE_LIMIT 50
251 254
252 255 static void filter_by_sm(struct sm_state *sm,
253 256 struct state_list **true_stack,
254 257 struct state_list **false_stack,
255 258 int *recurse_cnt)
256 259 {
257 260 if (!sm)
258 261 return;
259 262
260 263 if ((*recurse_cnt)++ > RECURSE_LIMIT)
261 264 return;
262 265
263 266 if (strcmp(sm->state->name, "true") == 0) {
264 267 add_ptr_list(true_stack, sm);
265 268 } else if (strcmp(sm->state->name, "false") == 0) {
266 269 add_ptr_list(false_stack, sm);
267 270 }
268 271
269 272 if (sm->merged) {
270 273 filter_by_sm(sm->left, true_stack, false_stack, recurse_cnt);
271 274 filter_by_sm(sm->right, true_stack, false_stack, recurse_cnt);
272 275 }
273 276 }
274 277
275 278 struct sm_state *stored_condition_implication_hook(struct expression *expr,
276 279 struct state_list **true_stack,
277 280 struct state_list **false_stack)
278 281 {
279 282 struct sm_state *sm;
280 283 char *name;
281 284 int recurse_cnt = 0;
282 285 struct state_list *tmp_true = NULL;
283 286 struct state_list *tmp_false = NULL;
284 287 struct sm_state *tmp;
285 288
286 289 expr = strip_expr(expr);
287 290
288 291 name = expr_to_str(expr);
289 292 if (!name)
290 293 return NULL;
291 294
292 295 sm = get_sm_state(my_id, name, NULL);
293 296 free_string(name);
294 297 if (!sm)
295 298 return NULL;
296 299 if (!sm->merged)
297 300 return NULL;
298 301
299 302 filter_by_sm(sm, &tmp_true, &tmp_false, &recurse_cnt);
300 303 if (!tmp_true && !tmp_false)
301 304 return NULL;
302 305 if (recurse_cnt > RECURSE_LIMIT) {
303 306 sm = NULL;
304 307 goto free;
305 308 }
306 309
307 310 FOR_EACH_PTR(tmp_true, tmp) {
308 311 add_ptr_list(true_stack, tmp);
309 312 } END_FOR_EACH_PTR(tmp);
310 313
311 314 FOR_EACH_PTR(tmp_false, tmp) {
312 315 add_ptr_list(false_stack, tmp);
313 316 } END_FOR_EACH_PTR(tmp);
314 317
315 318 free:
316 319 free_slist(&tmp_true);
317 320 free_slist(&tmp_false);
318 321 return sm;
319 322 }
320 323
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX