82
83 void call_extra_hooks(struct void_fn_list *hooks, const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
84 {
85 mod_hook **fn;
86
87 FOR_EACH_PTR(hooks, fn) {
88 (*fn)(name, sym, expr, state);
89 } END_FOR_EACH_PTR(fn);
90 }
91
92 void call_extra_mod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
93 {
94 call_extra_hooks(extra_mod_hooks, name, sym, expr, state);
95 }
96
97 void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
98 {
99 call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
100 }
101
102 static bool in_param_set;
103 void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
104 {
105 remove_from_equiv(name, sym);
106 call_extra_mod_hooks(name, sym, expr, state);
107 if ((__in_fake_assign || in_param_set) &&
108 estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
109 return;
110 set_state(SMATCH_EXTRA, name, sym, state);
111 }
112
113 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
114 {
115 call_extra_nomod_hooks(name, sym, expr, state);
116 set_state(SMATCH_EXTRA, name, sym, state);
117 }
118
119 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
120 {
121 struct expression *assigned;
122
123 if (name[0] != '*')
124 return NULL;
125 if (strcmp(name + 1, sym->ident->name) != 0)
126 return NULL;
127
155
156 snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + len);
157 ret = alloc_string(buf);
158 free_string(orig_name);
159 return ret;
160 }
161
162 orig_name = expr_to_var_sym(assigned, new_sym);
163 if (!orig_name || !*new_sym)
164 goto free;
165
166 snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
167 ret = alloc_string(buf);
168 free_string(orig_name);
169 return ret;
170 free:
171 free_string(orig_name);
172 return NULL;
173 }
174
175 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
176 {
177 struct expression *tmp;
178 struct sm_state *sm;
179 char buf[256];
180
181 /*
182 * Just prepend the name with a different name/sym and return that.
183 * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
184 * that also clamps "foo->bar->baz".
185 *
186 */
187
188 FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
189 tmp = sm->state->data;
190 if (!tmp || tmp->type != EXPR_SYMBOL)
191 continue;
192 if (tmp->symbol == sym)
193 goto found;
194 } END_FOR_EACH_SM(sm);
195
196 return NULL;
197
198 found:
199 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
200 *new_sym = sm->sym;
201 return alloc_string(buf);
202 }
203
204 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
205 {
206 char buf[256];
207 char *ret;
208 int len;
209
210 *new_sym = NULL;
211
212 if (!sym || !sym->ident)
213 return NULL;
214
215 ret = get_pointed_at(name, sym, new_sym);
216 if (ret)
217 return ret;
218
219 ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
220 if (ret)
221 return ret;
222
223 len = snprintf(buf, sizeof(buf), "%s", name);
224 if (len >= sizeof(buf) - 2)
225 return NULL;
226
227 while (len >= 1) {
228 if (buf[len] == '>' && buf[len - 1] == '-') {
229 len--;
230 buf[len] = '\0';
231 ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
232 if (ret)
233 return ret;
234 }
235 len--;
236 }
237
238 ret = get_long_name_sym(name, sym, new_sym);
239 if (ret)
240 return ret;
241
242 return NULL;
243 }
244
245 char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
246 {
247 return get_other_name_sym_helper(name, sym, new_sym, true);
248 }
249
250 char *get_other_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
251 {
252 return get_other_name_sym_helper(name, sym, new_sym, false);
253 }
254
255 void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
256 {
257 char *new_name;
258 struct symbol *new_sym;
259
260 set_extra_mod_helper(name, sym, expr, state);
261 new_name = get_other_name_sym(name, sym, &new_sym);
262 if (new_name && new_sym)
263 set_extra_mod_helper(new_name, new_sym, expr, state);
264 free_string(new_name);
265 }
266
267 static struct expression *chunk_get_array_base(struct expression *expr)
268 {
269 /*
270 * The problem with is_array() is that it only returns true for things
271 * like foo[1] but not for foo[1].bar.
272 *
273 */
274 expr = strip_expr(expr);
275 while (expr && expr->type == EXPR_DEREF)
276 expr = strip_expr(expr->deref);
277 return get_array_base(expr);
278 }
279
280 static int chunk_has_array(struct expression *expr)
281 {
282 return !!chunk_get_array_base(expr);
283 }
1214 clear_pointed_at_state(expr->unop);
1215 break;
1216 case SPECIAL_DECREMENT:
1217 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1218 state = decrement_state(state);
1219 if (!state)
1220 state = alloc_estate_whole(get_type(expr));
1221 set_extra_expr_mod(expr->unop, state);
1222 clear_pointed_at_state(expr->unop);
1223 break;
1224 default:
1225 return;
1226 }
1227 }
1228
1229 static void asm_expr(struct statement *stmt)
1230 {
1231
1232 struct expression *expr;
1233 struct symbol *type;
1234 int state = 0;
1235
1236 FOR_EACH_PTR(stmt->asm_outputs, expr) {
1237 switch (state) {
1238 case 0: /* identifier */
1239 case 1: /* constraint */
1240 state++;
1241 continue;
1242 case 2: /* expression */
1243 state = 0;
1244 type = get_type(strip_expr(expr));
1245 set_extra_expr_mod(expr, alloc_estate_whole(type));
1246 continue;
1247 }
1248 } END_FOR_EACH_PTR(expr);
1249 }
1250
1251 static void check_dereference(struct expression *expr)
1252 {
1253 struct smatch_state *state;
1254
1255 if (__in_fake_assign)
1256 return;
1257 if (outside_of_function())
1258 return;
1259 state = get_extra_state(expr);
1260 if (state) {
1261 struct range_list *rl;
1262
1263 rl = rl_intersection(estate_rl(state), valid_ptr_rl);
1264 if (rl_equiv(rl, estate_rl(state)))
1265 return;
1266 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1267 } else {
1268 struct range_list *rl;
1269
1270 if (get_mtag_rl(expr, &rl))
1271 rl = rl_intersection(rl, valid_ptr_rl);
1272 else
1273 rl = clone_rl(valid_ptr_rl);
1274
1275 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1276 }
1277 }
1278
1279 static void match_dereferences(struct expression *expr)
1280 {
1281 if (expr->type != EXPR_PREOP)
1282 return;
1283 /* it's saying that foo[1] = bar dereferences foo[1] */
1284 if (is_array(expr))
1285 return;
1286 check_dereference(expr->unop);
1287 }
1288
1289 static void match_pointer_as_array(struct expression *expr)
1290 {
1291 if (!is_array(expr))
1292 return;
1293 check_dereference(get_array_base(expr));
1294 }
1295
1296 static void find_dereferences(struct expression *expr)
1297 {
1298 while (expr->type == EXPR_PREOP) {
1299 if (expr->op == '*')
1300 check_dereference(expr->unop);
1301 expr = strip_expr(expr->unop);
1302 }
2186 if (!estate)
2187 return 0;
2188 if (!rl_has_sval(estate_rl(estate), sval_type_val(estate_type(estate), 0)))
2189 return 1;
2190 return 0;
2191 }
2192
2193 int parent_is_null_var_sym(const char *name, struct symbol *sym)
2194 {
2195 char buf[256];
2196 char *start;
2197 char *end;
2198 struct smatch_state *state;
2199
2200 strncpy(buf, name, sizeof(buf) - 1);
2201 buf[sizeof(buf) - 1] = '\0';
2202
2203 start = &buf[0];
2204 while (*start == '*') {
2205 start++;
2206 state = get_state(SMATCH_EXTRA, start, sym);
2207 if (!state)
2208 continue;
2209 if (!estate_rl(state))
2210 return 1;
2211 if (estate_min(state).value == 0 &&
2212 estate_max(state).value == 0)
2213 return 1;
2214 }
2215
2216 start = &buf[0];
2217 while (*start == '&')
2218 start++;
2219
2220 while ((end = strrchr(start, '-'))) {
2221 *end = '\0';
2222 state = __get_state(SMATCH_EXTRA, start, sym);
2223 if (!state)
2224 continue;
2225 if (estate_min(state).value == 0 &&
2226 estate_max(state).value == 0)
2356 }
2357
2358 struct range_list *intersect_with_real_abs_expr(struct expression *expr, struct range_list *start)
2359 {
2360 struct smatch_state *state;
2361 struct range_list *abs_rl;
2362
2363 state = get_real_absolute_state(expr);
2364 if (!state || !estate_rl(state))
2365 return start;
2366
2367 abs_rl = cast_rl(rl_type(start), estate_rl(state));
2368 return rl_intersection(abs_rl, start);
2369 }
2370
2371 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2372 {
2373 struct range_list *rl;
2374 sval_t dummy;
2375
2376 if (estate_is_whole(sm->state))
2377 return;
2378 if (filter_unused_param_value_info(call, param, printed_name, sm))
2379 return;
2380 rl = estate_rl(sm->state);
2381 rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
2382 sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2383 if (!estate_get_single_value(sm->state, &dummy)) {
2384 if (estate_has_hard_max(sm->state))
2385 sql_insert_caller_info(call, HARD_MAX, param, printed_name,
2386 sval_to_str(estate_max(sm->state)));
2387 if (estate_has_fuzzy_max(sm->state))
2388 sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2389 sval_to_str(estate_get_fuzzy_max(sm->state)));
2390 }
2391 }
2392
2393 static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2394 {
2395 struct symbol *returned_sym;
2396 char *returned_name;
2397 struct sm_state *sm;
2398 char *compare_str;
2399 char name_buf[256];
2400 char val_buf[256];
2401 int len;
2552 }
2553
2554 if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
2555 db_param_limit_binops(arg, key, new);
2556 free:
2557 free_string(name);
2558 }
2559
2560 static void db_param_limit(struct expression *expr, int param, char *key, char *value)
2561 {
2562 db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2563 }
2564
2565 static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2566 {
2567 db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2568 }
2569
2570 static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2571 {
2572 struct expression *arg;
2573 char *name;
2574 char *other_name = NULL;
2575 struct symbol *sym, *other_sym;
2576 struct symbol *param_type, *arg_type;
2577 struct smatch_state *state;
2578 struct range_list *new = NULL;
2579 struct range_list *added = NULL;
2580
2581 while (expr->type == EXPR_ASSIGNMENT)
2582 expr = strip_expr(expr->right);
2583 if (expr->type != EXPR_CALL)
2584 return;
2585
2586 arg = get_argument_from_call_expr(expr->args, param);
2587 if (!arg)
2588 return;
2589
2590 arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
2591 param_type = get_member_type_from_key(arg, key);
2592 name = get_variable_from_key(arg, key, &sym);
2593 if (!name || !sym)
2594 goto free;
2595
2596 state = get_state(SMATCH_EXTRA, name, sym);
2597 if (state)
2598 new = estate_rl(state);
2599
2600 call_results_to_rl(expr, arg_type, value, &added);
2601 added = cast_rl(param_type, added);
2602 if (op == PARAM_SET)
2603 new = added;
2604 else
2605 new = rl_union(new, added);
2606
2607 other_name = get_other_name_sym_nostack(name, sym, &other_sym);
2608 set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
2609 if (other_name && other_sym)
2610 set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new));
2611 free:
2612 free_string(other_name);
2613 free_string(name);
2614 }
2615
2616 static void db_param_add(struct expression *expr, int param, char *key, char *value)
2617 {
2618 in_param_set = true;
2619 db_param_add_set(expr, param, key, value, PARAM_ADD);
2620 in_param_set = false;
2621 }
2622
2623 static void db_param_set(struct expression *expr, int param, char *key, char *value)
2624 {
2625 in_param_set = true;
2626 db_param_add_set(expr, param, key, value, PARAM_SET);
2627 in_param_set = false;
2628 }
2629
2630 static void match_lost_param(struct expression *call, int param)
|
82
83 void call_extra_hooks(struct void_fn_list *hooks, const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
84 {
85 mod_hook **fn;
86
87 FOR_EACH_PTR(hooks, fn) {
88 (*fn)(name, sym, expr, state);
89 } END_FOR_EACH_PTR(fn);
90 }
91
92 void call_extra_mod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
93 {
94 call_extra_hooks(extra_mod_hooks, name, sym, expr, state);
95 }
96
97 void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
98 {
99 call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
100 }
101
102 static void set_union_info(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
103 {
104 struct symbol *type, *tmp, *inner_type, *inner, *new_type;
105 struct expression *deref, *member_expr;
106 struct smatch_state *new;
107 int offset, inner_offset;
108 static bool in_recurse;
109 char *member_name;
110
111 if (__in_fake_assign)
112 return;
113
114 if (in_recurse)
115 return;
116 in_recurse = true;
117
118 if (!expr || expr->type != EXPR_DEREF || !expr->member)
119 goto done;
120 offset = get_member_offset_from_deref(expr);
121 if (offset < 0)
122 goto done;
123
124 deref = strip_expr(expr->deref);
125 type = get_type(deref);
126 if (type_is_ptr(type))
127 type = get_real_base_type(type);
128 if (!type || type->type != SYM_STRUCT)
129 goto done;
130
131 FOR_EACH_PTR(type->symbol_list, tmp) {
132 inner_type = get_real_base_type(tmp);
133 if (!inner_type || inner_type->type != SYM_UNION)
134 continue;
135
136 inner = first_ptr_list((struct ptr_list *)inner_type->symbol_list);
137 if (!inner || !inner->ident)
138 continue;
139
140 inner_offset = get_member_offset(type, inner->ident->name);
141 if (inner_offset < offset)
142 continue;
143 if (inner_offset > offset)
144 goto done;
145
146 FOR_EACH_PTR(inner_type->symbol_list, inner) {
147 struct symbol *tmp_type;
148
149 if (!inner->ident || inner->ident == expr->member)
150 continue;
151 tmp_type = get_real_base_type(inner);
152 if (tmp_type && tmp_type->type == SYM_STRUCT)
153 continue;
154 member_expr = deref;
155 if (tmp->ident)
156 member_expr = member_expression(member_expr, '.', tmp->ident);
157 member_expr = member_expression(member_expr, expr->op, inner->ident);
158 member_name = expr_to_var(member_expr);
159 if (!member_name)
160 continue;
161 new_type = get_real_base_type(inner);
162 new = alloc_estate_rl(cast_rl(new_type, estate_rl(state)));
163 set_extra_mod_helper(member_name, sym, member_expr, new);
164 free_string(member_name);
165 } END_FOR_EACH_PTR(inner);
166 } END_FOR_EACH_PTR(tmp);
167
168 done:
169 in_recurse = false;
170 }
171
172 static bool in_param_set;
173 void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
174 {
175 if (!expr)
176 expr = gen_expression_from_name_sym(name, sym);
177 remove_from_equiv(name, sym);
178 set_union_info(name, sym, expr, state);
179 call_extra_mod_hooks(name, sym, expr, state);
180 update_mtag_data(expr, state);
181 if (in_param_set &&
182 estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
183 return;
184 set_state(SMATCH_EXTRA, name, sym, state);
185 }
186
187 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
188 {
189 call_extra_nomod_hooks(name, sym, expr, state);
190 set_state(SMATCH_EXTRA, name, sym, state);
191 }
192
193 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
194 {
195 struct expression *assigned;
196
197 if (name[0] != '*')
198 return NULL;
199 if (strcmp(name + 1, sym->ident->name) != 0)
200 return NULL;
201
229
230 snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + len);
231 ret = alloc_string(buf);
232 free_string(orig_name);
233 return ret;
234 }
235
236 orig_name = expr_to_var_sym(assigned, new_sym);
237 if (!orig_name || !*new_sym)
238 goto free;
239
240 snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
241 ret = alloc_string(buf);
242 free_string(orig_name);
243 return ret;
244 free:
245 free_string(orig_name);
246 return NULL;
247 }
248
249 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
250 {
251 struct expression *tmp;
252 struct sm_state *sm;
253 char buf[256];
254
255 /*
256 * Just prepend the name with a different name/sym and return that.
257 * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
258 * that also clamps "foo->bar->baz".
259 *
260 */
261
262 FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
263 tmp = sm->state->data;
264 if (!tmp || tmp->type != EXPR_SYMBOL)
265 continue;
266 if (tmp->symbol == sym)
267 goto found;
268 } END_FOR_EACH_SM(sm);
269
270 return NULL;
271
272 found:
273 if (!use_stack && name[tmp->symbol->ident->len] != '-')
274 return NULL;
275 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
276 *new_sym = sm->sym;
277 return alloc_string(buf);
278 }
279
280 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
281 {
282 char buf[256];
283 char *ret;
284 int len;
285
286 *new_sym = NULL;
287
288 if (!sym || !sym->ident)
289 return NULL;
290
291 ret = get_pointed_at(name, sym, new_sym);
292 if (ret)
293 return ret;
294
295 ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
296 if (ret)
297 return ret;
298
299 len = snprintf(buf, sizeof(buf), "%s", name);
300 if (len >= sizeof(buf) - 2)
301 return NULL;
302
303 while (use_stack && len >= 1) {
304 if (buf[len] == '>' && buf[len - 1] == '-') {
305 len--;
306 buf[len] = '\0';
307 ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
308 if (ret)
309 return ret;
310 }
311 len--;
312 }
313
314 ret = get_long_name_sym(name, sym, new_sym, use_stack);
315 if (ret)
316 return ret;
317
318 return NULL;
319 }
320
321 char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
322 {
323 return get_other_name_sym_helper(name, sym, new_sym, true);
324 }
325
326 char *get_other_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
327 {
328 return get_other_name_sym_helper(name, sym, new_sym, false);
329 }
330
331 void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
332 {
333 char *new_name;
334 struct symbol *new_sym;
335
336 set_extra_mod_helper(name, sym, expr, state);
337 new_name = get_other_name_sym_nostack(name, sym, &new_sym);
338 if (new_name && new_sym)
339 set_extra_mod_helper(new_name, new_sym, NULL, state);
340 free_string(new_name);
341 }
342
343 static struct expression *chunk_get_array_base(struct expression *expr)
344 {
345 /*
346 * The problem with is_array() is that it only returns true for things
347 * like foo[1] but not for foo[1].bar.
348 *
349 */
350 expr = strip_expr(expr);
351 while (expr && expr->type == EXPR_DEREF)
352 expr = strip_expr(expr->deref);
353 return get_array_base(expr);
354 }
355
356 static int chunk_has_array(struct expression *expr)
357 {
358 return !!chunk_get_array_base(expr);
359 }
1290 clear_pointed_at_state(expr->unop);
1291 break;
1292 case SPECIAL_DECREMENT:
1293 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1294 state = decrement_state(state);
1295 if (!state)
1296 state = alloc_estate_whole(get_type(expr));
1297 set_extra_expr_mod(expr->unop, state);
1298 clear_pointed_at_state(expr->unop);
1299 break;
1300 default:
1301 return;
1302 }
1303 }
1304
1305 static void asm_expr(struct statement *stmt)
1306 {
1307
1308 struct expression *expr;
1309 struct symbol *type;
1310
1311 FOR_EACH_PTR(stmt->asm_outputs, expr) {
1312 if (expr->type != EXPR_ASM_OPERAND) {
1313 sm_perror("unexpected asm param type %d", expr->type);
1314 continue;
1315 }
1316 type = get_type(strip_expr(expr->expr));
1317 set_extra_expr_mod(expr->expr, alloc_estate_whole(type));
1318 } END_FOR_EACH_PTR(expr);
1319 }
1320
1321 static void check_dereference(struct expression *expr)
1322 {
1323 struct smatch_state *state;
1324
1325 if (__in_fake_assign)
1326 return;
1327 if (outside_of_function())
1328 return;
1329 state = get_extra_state(expr);
1330 if (state) {
1331 struct range_list *rl;
1332
1333 rl = rl_intersection(estate_rl(state), valid_ptr_rl);
1334 if (rl_equiv(rl, estate_rl(state)))
1335 return;
1336 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1337 } else {
1338 struct range_list *rl;
1339
1340 if (get_mtag_rl(expr, &rl))
1341 rl = rl_intersection(rl, valid_ptr_rl);
1342 else
1343 rl = clone_rl(valid_ptr_rl);
1344
1345 set_extra_expr_nomod(expr, alloc_estate_rl(rl));
1346 }
1347 }
1348
1349 static void match_dereferences(struct expression *expr)
1350 {
1351 if (expr->type != EXPR_PREOP)
1352 return;
1353 if (getting_address(expr))
1354 return;
1355 /* it's saying that foo[1] = bar dereferences foo[1] */
1356 if (is_array(expr))
1357 return;
1358 check_dereference(expr->unop);
1359 }
1360
1361 static void match_pointer_as_array(struct expression *expr)
1362 {
1363 if (!is_array(expr))
1364 return;
1365 check_dereference(get_array_base(expr));
1366 }
1367
1368 static void find_dereferences(struct expression *expr)
1369 {
1370 while (expr->type == EXPR_PREOP) {
1371 if (expr->op == '*')
1372 check_dereference(expr->unop);
1373 expr = strip_expr(expr->unop);
1374 }
2258 if (!estate)
2259 return 0;
2260 if (!rl_has_sval(estate_rl(estate), sval_type_val(estate_type(estate), 0)))
2261 return 1;
2262 return 0;
2263 }
2264
2265 int parent_is_null_var_sym(const char *name, struct symbol *sym)
2266 {
2267 char buf[256];
2268 char *start;
2269 char *end;
2270 struct smatch_state *state;
2271
2272 strncpy(buf, name, sizeof(buf) - 1);
2273 buf[sizeof(buf) - 1] = '\0';
2274
2275 start = &buf[0];
2276 while (*start == '*') {
2277 start++;
2278 state = __get_state(SMATCH_EXTRA, start, sym);
2279 if (!state)
2280 continue;
2281 if (!estate_rl(state))
2282 return 1;
2283 if (estate_min(state).value == 0 &&
2284 estate_max(state).value == 0)
2285 return 1;
2286 }
2287
2288 start = &buf[0];
2289 while (*start == '&')
2290 start++;
2291
2292 while ((end = strrchr(start, '-'))) {
2293 *end = '\0';
2294 state = __get_state(SMATCH_EXTRA, start, sym);
2295 if (!state)
2296 continue;
2297 if (estate_min(state).value == 0 &&
2298 estate_max(state).value == 0)
2428 }
2429
2430 struct range_list *intersect_with_real_abs_expr(struct expression *expr, struct range_list *start)
2431 {
2432 struct smatch_state *state;
2433 struct range_list *abs_rl;
2434
2435 state = get_real_absolute_state(expr);
2436 if (!state || !estate_rl(state))
2437 return start;
2438
2439 abs_rl = cast_rl(rl_type(start), estate_rl(state));
2440 return rl_intersection(abs_rl, start);
2441 }
2442
2443 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2444 {
2445 struct range_list *rl;
2446 sval_t dummy;
2447
2448 if (estate_is_whole(sm->state) || !estate_rl(sm->state))
2449 return;
2450 if (filter_unused_param_value_info(call, param, printed_name, sm))
2451 return;
2452 rl = estate_rl(sm->state);
2453 rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
2454 if (!rl)
2455 return;
2456 sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2457 if (!estate_get_single_value(sm->state, &dummy)) {
2458 if (estate_has_hard_max(sm->state))
2459 sql_insert_caller_info(call, HARD_MAX, param, printed_name,
2460 sval_to_str(estate_max(sm->state)));
2461 if (estate_has_fuzzy_max(sm->state))
2462 sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2463 sval_to_str(estate_get_fuzzy_max(sm->state)));
2464 }
2465 }
2466
2467 static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2468 {
2469 struct symbol *returned_sym;
2470 char *returned_name;
2471 struct sm_state *sm;
2472 char *compare_str;
2473 char name_buf[256];
2474 char val_buf[256];
2475 int len;
2626 }
2627
2628 if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
2629 db_param_limit_binops(arg, key, new);
2630 free:
2631 free_string(name);
2632 }
2633
2634 static void db_param_limit(struct expression *expr, int param, char *key, char *value)
2635 {
2636 db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2637 }
2638
2639 static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2640 {
2641 db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2642 }
2643
2644 static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2645 {
2646 struct expression *arg, *gen_expr;
2647 char *name;
2648 char *other_name = NULL;
2649 struct symbol *sym, *other_sym;
2650 struct symbol *param_type, *arg_type;
2651 struct smatch_state *state;
2652 struct range_list *new = NULL;
2653 struct range_list *added = NULL;
2654
2655 while (expr->type == EXPR_ASSIGNMENT)
2656 expr = strip_expr(expr->right);
2657 if (expr->type != EXPR_CALL)
2658 return;
2659
2660 arg = get_argument_from_call_expr(expr->args, param);
2661 if (!arg)
2662 return;
2663
2664 arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
2665 param_type = get_member_type_from_key(arg, key);
2666 if (param_type && param_type->type == SYM_STRUCT)
2667 return;
2668 name = get_variable_from_key(arg, key, &sym);
2669 if (!name || !sym)
2670 goto free;
2671 gen_expr = gen_expression_from_key(arg, key);
2672
2673 state = get_state(SMATCH_EXTRA, name, sym);
2674 if (state)
2675 new = estate_rl(state);
2676
2677 call_results_to_rl(expr, arg_type, value, &added);
2678 added = cast_rl(param_type, added);
2679 if (op == PARAM_SET)
2680 new = added;
2681 else
2682 new = rl_union(new, added);
2683
2684 other_name = get_other_name_sym_nostack(name, sym, &other_sym);
2685 set_extra_mod(name, sym, gen_expr, alloc_estate_rl(new));
2686 if (other_name && other_sym)
2687 set_extra_mod(other_name, other_sym, gen_expr, alloc_estate_rl(new));
2688 free:
2689 free_string(other_name);
2690 free_string(name);
2691 }
2692
2693 static void db_param_add(struct expression *expr, int param, char *key, char *value)
2694 {
2695 in_param_set = true;
2696 db_param_add_set(expr, param, key, value, PARAM_ADD);
2697 in_param_set = false;
2698 }
2699
2700 static void db_param_set(struct expression *expr, int param, char *key, char *value)
2701 {
2702 in_param_set = true;
2703 db_param_add_set(expr, param, key, value, PARAM_SET);
2704 in_param_set = false;
2705 }
2706
2707 static void match_lost_param(struct expression *call, int param)
|