math: handle offset calculation better
[smatch.git] / smatch_extra.c
blob8b87a68597eca5422fc98ebeda7704336c2b21bc
1 /*
2 * Copyright (C) 2008 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * smatch_extra.c is supposed to track the value of every variable.
23 #define _GNU_SOURCE
24 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #ifndef __USE_ISOC99
29 #define __USE_ISOC99
30 #endif
31 #include <limits.h>
32 #include "parse.h"
33 #include "smatch.h"
34 #include "smatch_slist.h"
35 #include "smatch_extra.h"
37 static int my_id;
38 static int link_id;
40 static void match_link_modify(struct sm_state *sm, struct expression *mod_expr);
42 struct string_list *__ignored_macros = NULL;
43 static int in_warn_on_macro(void)
45 struct statement *stmt;
46 char *tmp;
47 char *macro;
49 stmt = get_current_statement();
50 if (!stmt)
51 return 0;
52 macro = get_macro_name(stmt->pos);
53 if (!macro)
54 return 0;
56 FOR_EACH_PTR(__ignored_macros, tmp) {
57 if (!strcmp(tmp, macro))
58 return 1;
59 } END_FOR_EACH_PTR(tmp);
60 return 0;
63 typedef void (mod_hook)(const char *name, struct symbol *sym, struct smatch_state *state);
64 DECLARE_PTR_LIST(void_fn_list, mod_hook *);
65 static struct void_fn_list *extra_mod_hooks;
66 void add_extra_mod_hook(mod_hook *fn)
68 mod_hook **p = malloc(sizeof(mod_hook *));
69 *p = fn;
70 add_ptr_list(&extra_mod_hooks, p);
73 void call_extra_mod_hooks(const char *name, struct symbol *sym, struct smatch_state *state)
75 mod_hook **fn;
77 FOR_EACH_PTR(extra_mod_hooks, fn) {
78 (*fn)(name, sym, state);
79 } END_FOR_EACH_PTR(fn);
82 static bool in_param_set;
83 static void set_extra_mod_helper(const char *name, struct symbol *sym, struct smatch_state *state)
85 remove_from_equiv(name, sym);
86 call_extra_mod_hooks(name, sym, state);
87 if ((__in_fake_assign || in_param_set) &&
88 estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
89 return;
90 set_state(SMATCH_EXTRA, name, sym, state);
93 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
95 struct expression *assigned;
97 if (name[0] != '*')
98 return NULL;
99 if (strcmp(name + 1, sym->ident->name) != 0)
100 return NULL;
102 assigned = get_assigned_expr_name_sym(sym->ident->name, sym);
103 if (!assigned)
104 return NULL;
105 assigned = strip_parens(assigned);
106 if (assigned->type != EXPR_PREOP || assigned->op != '&')
107 return NULL;
109 return expr_to_var_sym(assigned->unop, new_sym);
112 char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
114 struct expression *assigned;
115 char *orig_name = NULL;
116 char buf[256];
117 char *ret = NULL;
118 int skip;
120 *new_sym = NULL;
122 if (!sym || !sym->ident)
123 return NULL;
125 ret = get_pointed_at(name, sym, new_sym);
126 if (ret)
127 return ret;
129 skip = strlen(sym->ident->name);
130 if (name[skip] != '-' || name[skip + 1] != '>')
131 return NULL;
132 skip += 2;
134 assigned = get_assigned_expr_name_sym(sym->ident->name, sym);
135 if (!assigned)
136 return NULL;
137 if (assigned->type == EXPR_CALL)
138 return map_call_to_other_name_sym(name, sym, new_sym);
139 if (assigned->type == EXPR_PREOP || assigned->op == '&') {
141 orig_name = expr_to_var_sym(assigned, new_sym);
142 if (!orig_name || !*new_sym)
143 goto free;
145 snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + skip);
146 ret = alloc_string(buf);
147 free_string(orig_name);
148 return ret;
151 if (assigned->type != EXPR_DEREF)
152 goto free;
154 orig_name = expr_to_var_sym(assigned, new_sym);
155 if (!orig_name || !*new_sym)
156 goto free;
158 snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + skip);
159 ret = alloc_string(buf);
160 free_string(orig_name);
161 return ret;
163 free:
164 free_string(orig_name);
165 return NULL;
168 void set_extra_mod(const char *name, struct symbol *sym, struct smatch_state *state)
170 char *new_name;
171 struct symbol *new_sym;
173 set_extra_mod_helper(name, sym, state);
174 new_name = get_other_name_sym(name, sym, &new_sym);
175 if (new_name && new_sym)
176 set_extra_mod_helper(new_name, new_sym, state);
177 free_string(new_name);
180 static void clear_array_states(struct expression *array)
182 struct sm_state *sm;
184 sm = get_sm_state_expr(link_id, array);
185 if (sm)
186 match_link_modify(sm, NULL);
189 static void set_extra_array_mod(struct expression *expr, struct smatch_state *state)
191 struct expression *array;
192 struct var_sym_list *vsl;
193 struct var_sym *vs;
194 char *name;
195 struct symbol *sym;
197 array = get_array_base(expr);
199 name = expr_to_chunk_sym_vsl(expr, &sym, &vsl);
200 if (!name || !vsl) {
201 clear_array_states(array);
202 goto free;
205 FOR_EACH_PTR(vsl, vs) {
206 store_link(link_id, vs->var, vs->sym, name, sym);
207 } END_FOR_EACH_PTR(vs);
209 call_extra_mod_hooks(name, sym, state);
210 set_state(SMATCH_EXTRA, name, sym, state);
211 free:
212 free_string(name);
215 void set_extra_expr_mod(struct expression *expr, struct smatch_state *state)
217 struct symbol *sym;
218 char *name;
220 if (is_array(expr)) {
221 set_extra_array_mod(expr, state);
222 return;
225 expr = strip_expr(expr);
226 name = expr_to_var_sym(expr, &sym);
227 if (!name || !sym)
228 goto free;
229 set_extra_mod(name, sym, state);
230 free:
231 free_string(name);
234 void set_extra_nomod(const char *name, struct symbol *sym, struct smatch_state *state)
236 char *new_name;
237 struct symbol *new_sym;
238 struct relation *rel;
239 struct smatch_state *orig_state;
241 orig_state = get_state(SMATCH_EXTRA, name, sym);
243 new_name = get_other_name_sym(name, sym, &new_sym);
244 if (new_name && new_sym)
245 set_state(SMATCH_EXTRA, new_name, new_sym, state);
246 free_string(new_name);
248 if (!estate_related(orig_state)) {
249 set_state(SMATCH_EXTRA, name, sym, state);
250 return;
253 set_related(state, estate_related(orig_state));
254 FOR_EACH_PTR(estate_related(orig_state), rel) {
255 struct smatch_state *estate;
257 if (option_debug_related)
258 sm_msg("%s updating related %s to %s", name, rel->name, state->name);
259 estate = get_state(SMATCH_EXTRA, rel->name, rel->sym);
260 if (!estate)
261 continue;
262 set_state(SMATCH_EXTRA, rel->name, rel->sym, clone_estate_cast(estate_type(estate), state));
263 } END_FOR_EACH_PTR(rel);
266 void set_extra_nomod_vsl(const char *name, struct symbol *sym, struct var_sym_list *vsl, struct smatch_state *state)
268 struct var_sym *vs;
270 FOR_EACH_PTR(vsl, vs) {
271 store_link(link_id, vs->var, vs->sym, name, sym);
272 } END_FOR_EACH_PTR(vs);
274 set_extra_nomod(name, sym, state);
278 * This is for return_implies_state() hooks which modify a SMATCH_EXTRA state
280 void set_extra_expr_nomod(struct expression *expr, struct smatch_state *state)
282 struct var_sym_list *vsl;
283 struct var_sym *vs;
284 char *name;
285 struct symbol *sym;
287 name = expr_to_chunk_sym_vsl(expr, &sym, &vsl);
288 if (!name || !vsl)
289 goto free;
290 FOR_EACH_PTR(vsl, vs) {
291 store_link(link_id, vs->var, vs->sym, name, sym);
292 } END_FOR_EACH_PTR(vs);
294 set_extra_nomod(name, sym, state);
295 free:
296 free_string(name);
299 static void set_extra_true_false(const char *name, struct symbol *sym,
300 struct smatch_state *true_state,
301 struct smatch_state *false_state)
303 char *new_name;
304 struct symbol *new_sym;
305 struct relation *rel;
306 struct smatch_state *orig_state;
308 if (!true_state && !false_state)
309 return;
311 if (in_warn_on_macro())
312 return;
314 new_name = get_other_name_sym(name, sym, &new_sym);
315 if (new_name && new_sym)
316 set_true_false_states(SMATCH_EXTRA, new_name, new_sym, true_state, false_state);
317 free_string(new_name);
319 orig_state = get_state(SMATCH_EXTRA, name, sym);
321 if (!estate_related(orig_state)) {
322 set_true_false_states(SMATCH_EXTRA, name, sym, true_state, false_state);
323 return;
326 if (true_state)
327 set_related(true_state, estate_related(orig_state));
328 if (false_state)
329 set_related(false_state, estate_related(orig_state));
331 FOR_EACH_PTR(estate_related(orig_state), rel) {
332 set_true_false_states(SMATCH_EXTRA, rel->name, rel->sym,
333 true_state, false_state);
334 } END_FOR_EACH_PTR(rel);
337 static void set_extra_chunk_true_false(struct expression *expr,
338 struct smatch_state *true_state,
339 struct smatch_state *false_state)
341 struct var_sym_list *vsl;
342 struct var_sym *vs;
343 struct symbol *type;
344 char *name;
345 struct symbol *sym;
347 if (in_warn_on_macro())
348 return;
350 type = get_type(expr);
351 if (!type)
352 return;
354 name = expr_to_chunk_sym_vsl(expr, &sym, &vsl);
355 if (!name || !vsl)
356 goto free;
357 FOR_EACH_PTR(vsl, vs) {
358 store_link(link_id, vs->var, vs->sym, name, sym);
359 } END_FOR_EACH_PTR(vs);
361 set_true_false_states(SMATCH_EXTRA, name, sym,
362 clone_estate(true_state),
363 clone_estate(false_state));
364 free:
365 free_string(name);
368 static void set_extra_expr_true_false(struct expression *expr,
369 struct smatch_state *true_state,
370 struct smatch_state *false_state)
372 char *name;
373 struct symbol *sym;
374 sval_t sval;
376 if (!true_state && !false_state)
377 return;
379 if (get_value(expr, &sval))
380 return;
382 expr = strip_expr(expr);
383 name = expr_to_var_sym(expr, &sym);
384 if (!name || !sym) {
385 free_string(name);
386 set_extra_chunk_true_false(expr, true_state, false_state);
387 return;
389 set_extra_true_false(name, sym, true_state, false_state);
390 free_string(name);
393 static struct sm_state *handle_canonical_while_count_down(struct statement *loop)
395 struct expression *iter_var;
396 struct expression *condition;
397 struct sm_state *sm;
398 struct smatch_state *estate;
399 sval_t start;
401 condition = strip_expr(loop->iterator_pre_condition);
402 if (!condition)
403 return NULL;
404 if (condition->type != EXPR_PREOP && condition->type != EXPR_POSTOP)
405 return NULL;
406 if (condition->op != SPECIAL_DECREMENT)
407 return NULL;
409 iter_var = condition->unop;
410 sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
411 if (!sm)
412 return NULL;
413 if (sval_cmp_val(estate_min(sm->state), 0) < 0)
414 return NULL;
415 start = estate_max(sm->state);
416 if (sval_cmp_val(start, 0) <= 0)
417 return NULL;
418 if (!sval_is_max(start))
419 start.value--;
421 if (condition->type == EXPR_PREOP) {
422 estate = alloc_estate_range(sval_type_val(start.type, 1), start);
423 if (estate_has_hard_max(sm->state))
424 estate_set_hard_max(estate);
425 estate_copy_fuzzy_max(estate, sm->state);
426 set_extra_expr_mod(iter_var, estate);
428 if (condition->type == EXPR_POSTOP) {
429 estate = alloc_estate_range(sval_type_val(start.type, 0), start);
430 if (estate_has_hard_max(sm->state))
431 estate_set_hard_max(estate);
432 estate_copy_fuzzy_max(estate, sm->state);
433 set_extra_expr_mod(iter_var, estate);
435 return get_sm_state_expr(SMATCH_EXTRA, iter_var);
438 static struct sm_state *handle_canonical_for_inc(struct expression *iter_expr,
439 struct expression *condition)
441 struct expression *iter_var;
442 struct sm_state *sm;
443 struct smatch_state *estate;
444 sval_t start, end, max;
446 iter_var = iter_expr->unop;
447 sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
448 if (!sm)
449 return NULL;
450 if (!estate_get_single_value(sm->state, &start))
451 return NULL;
452 if (get_implied_max(condition->right, &end))
453 end = sval_cast(get_type(iter_var), end);
454 else
455 end = sval_type_max(get_type(iter_var));
457 if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
458 return NULL;
460 switch (condition->op) {
461 case SPECIAL_UNSIGNED_LT:
462 case SPECIAL_NOTEQUAL:
463 case '<':
464 if (!sval_is_min(end))
465 end.value--;
466 break;
467 case SPECIAL_UNSIGNED_LTE:
468 case SPECIAL_LTE:
469 break;
470 default:
471 return NULL;
473 if (sval_cmp(end, start) < 0)
474 return NULL;
475 estate = alloc_estate_range(start, end);
476 if (get_hard_max(condition->right, &max)) {
477 estate_set_hard_max(estate);
478 if (condition->op == '<' ||
479 condition->op == SPECIAL_UNSIGNED_LT ||
480 condition->op == SPECIAL_NOTEQUAL)
481 max.value--;
482 estate_set_fuzzy_max(estate, max);
484 set_extra_expr_mod(iter_var, estate);
485 return get_sm_state_expr(SMATCH_EXTRA, iter_var);
488 static struct sm_state *handle_canonical_for_dec(struct expression *iter_expr,
489 struct expression *condition)
491 struct expression *iter_var;
492 struct sm_state *sm;
493 struct smatch_state *estate;
494 sval_t start, end;
496 iter_var = iter_expr->unop;
497 sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
498 if (!sm)
499 return NULL;
500 if (!estate_get_single_value(sm->state, &start))
501 return NULL;
502 if (!get_implied_min(condition->right, &end))
503 end = sval_type_min(get_type(iter_var));
504 if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
505 return NULL;
507 switch (condition->op) {
508 case SPECIAL_NOTEQUAL:
509 case '>':
510 if (!sval_is_min(end) && !sval_is_max(end))
511 end.value++;
512 break;
513 case SPECIAL_GTE:
514 break;
515 default:
516 return NULL;
518 if (sval_cmp(end, start) > 0)
519 return NULL;
520 estate = alloc_estate_range(end, start);
521 estate_set_hard_max(estate);
522 estate_set_fuzzy_max(estate, estate_get_fuzzy_max(estate));
523 set_extra_expr_mod(iter_var, estate);
524 return get_sm_state_expr(SMATCH_EXTRA, iter_var);
527 static struct sm_state *handle_canonical_for_loops(struct statement *loop)
529 struct expression *iter_expr;
530 struct expression *condition;
532 if (!loop->iterator_post_statement)
533 return NULL;
534 if (loop->iterator_post_statement->type != STMT_EXPRESSION)
535 return NULL;
536 iter_expr = loop->iterator_post_statement->expression;
537 if (!loop->iterator_pre_condition)
538 return NULL;
539 if (loop->iterator_pre_condition->type != EXPR_COMPARE)
540 return NULL;
541 condition = loop->iterator_pre_condition;
543 if (iter_expr->op == SPECIAL_INCREMENT)
544 return handle_canonical_for_inc(iter_expr, condition);
545 if (iter_expr->op == SPECIAL_DECREMENT)
546 return handle_canonical_for_dec(iter_expr, condition);
547 return NULL;
550 struct sm_state *__extra_handle_canonical_loops(struct statement *loop, struct stree **stree)
552 struct sm_state *ret;
554 __push_fake_cur_stree();
555 if (!loop->iterator_post_statement)
556 ret = handle_canonical_while_count_down(loop);
557 else
558 ret = handle_canonical_for_loops(loop);
559 *stree = __pop_fake_cur_stree();
560 return ret;
563 int __iterator_unchanged(struct sm_state *sm)
565 if (!sm)
566 return 0;
567 if (get_sm_state(my_id, sm->name, sm->sym) == sm)
568 return 1;
569 return 0;
572 static void while_count_down_after(struct sm_state *sm, struct expression *condition)
574 sval_t after_value;
576 /* paranoid checking. prolly not needed */
577 condition = strip_expr(condition);
578 if (!condition)
579 return;
580 if (condition->type != EXPR_PREOP && condition->type != EXPR_POSTOP)
581 return;
582 if (condition->op != SPECIAL_DECREMENT)
583 return;
584 after_value = estate_min(sm->state);
585 after_value.value--;
586 set_extra_mod(sm->name, sm->sym, alloc_estate_sval(after_value));
589 void __extra_pre_loop_hook_after(struct sm_state *sm,
590 struct statement *iterator,
591 struct expression *condition)
593 struct expression *iter_expr;
594 sval_t limit;
595 struct smatch_state *state;
597 if (!iterator) {
598 while_count_down_after(sm, condition);
599 return;
602 iter_expr = iterator->expression;
604 if (condition->type != EXPR_COMPARE)
605 return;
606 if (iter_expr->op == SPECIAL_INCREMENT) {
607 limit = sval_binop(estate_max(sm->state), '+',
608 sval_type_val(estate_type(sm->state), 1));
609 } else {
610 limit = sval_binop(estate_min(sm->state), '-',
611 sval_type_val(estate_type(sm->state), 1));
613 if (!estate_has_hard_max(sm->state) && !__has_breaks()) {
614 if (iter_expr->op == SPECIAL_INCREMENT)
615 state = alloc_estate_range(estate_min(sm->state), limit);
616 else
617 state = alloc_estate_range(limit, estate_max(sm->state));
618 } else {
619 state = alloc_estate_sval(limit);
621 if (!estate_has_hard_max(sm->state)) {
622 estate_clear_hard_max(state);
624 if (estate_has_fuzzy_max(sm->state)) {
625 sval_t hmax = estate_get_fuzzy_max(sm->state);
626 sval_t max = estate_max(sm->state);
628 if (sval_cmp(hmax, max) != 0)
629 estate_clear_fuzzy_max(state);
630 } else if (!estate_has_fuzzy_max(sm->state)) {
631 estate_clear_fuzzy_max(state);
634 set_extra_mod(sm->name, sm->sym, state);
637 static struct stree *unmatched_stree;
638 static struct smatch_state *unmatched_state(struct sm_state *sm)
640 struct smatch_state *state;
642 if (unmatched_stree) {
643 state = get_state_stree(unmatched_stree, SMATCH_EXTRA, sm->name, sm->sym);
644 if (state)
645 return state;
647 if (parent_is_gone_var_sym(sm->name, sm->sym))
648 return alloc_estate_empty();
649 return alloc_estate_whole(estate_type(sm->state));
652 static void clear_the_pointed_at(struct expression *expr)
654 struct stree *stree;
655 char *name;
656 struct symbol *sym;
657 struct sm_state *tmp;
659 name = expr_to_var_sym(expr, &sym);
660 if (!name || !sym)
661 goto free;
663 stree = __get_cur_stree();
664 FOR_EACH_MY_SM(SMATCH_EXTRA, stree, tmp) {
665 if (tmp->name[0] != '*')
666 continue;
667 if (tmp->sym != sym)
668 continue;
669 if (strcmp(tmp->name + 1, name) != 0)
670 continue;
671 set_extra_mod(tmp->name, tmp->sym, alloc_estate_whole(estate_type(tmp->state)));
672 } END_FOR_EACH_SM(tmp);
674 free:
675 free_string(name);
678 static void match_function_call(struct expression *expr)
680 struct expression *arg;
681 struct expression *tmp;
683 /* if we have the db this is handled in smatch_function_hooks.c */
684 if (!option_no_db)
685 return;
686 if (inlinable(expr->fn))
687 return;
689 FOR_EACH_PTR(expr->args, arg) {
690 tmp = strip_expr(arg);
691 if (tmp->type == EXPR_PREOP && tmp->op == '&')
692 set_extra_expr_mod(tmp->unop, alloc_estate_whole(get_type(tmp->unop)));
693 else
694 clear_the_pointed_at(tmp);
695 } END_FOR_EACH_PTR(arg);
698 static int values_fit_type(struct expression *left, struct expression *right)
700 struct range_list *rl;
701 struct symbol *type;
703 type = get_type(left);
704 if (!type)
705 return 0;
706 get_absolute_rl(right, &rl);
707 if (type_unsigned(type) && sval_is_negative(rl_min(rl)))
708 return 0;
709 if (sval_cmp(sval_type_min(type), rl_min(rl)) > 0)
710 return 0;
711 if (sval_cmp(sval_type_max(type), rl_max(rl)) < 0)
712 return 0;
713 return 1;
716 static void save_chunk_info(struct expression *left, struct expression *right)
718 struct var_sym_list *vsl;
719 struct var_sym *vs;
720 struct expression *add_expr;
721 struct symbol *type;
722 sval_t sval;
723 char *name;
724 struct symbol *sym;
726 if (right->type != EXPR_BINOP || right->op != '-')
727 return;
728 if (!get_value(right->left, &sval))
729 return;
730 if (!expr_to_sym(right->right))
731 return;
733 add_expr = binop_expression(left, '+', right->right);
734 type = get_type(add_expr);
735 if (!type)
736 return;
737 name = expr_to_chunk_sym_vsl(add_expr, &sym, &vsl);
738 if (!name || !vsl)
739 goto free;
740 FOR_EACH_PTR(vsl, vs) {
741 store_link(link_id, vs->var, vs->sym, name, sym);
742 } END_FOR_EACH_PTR(vs);
744 set_state(SMATCH_EXTRA, name, sym, alloc_estate_sval(sval_cast(type, sval)));
745 free:
746 free_string(name);
749 static void do_array_assign(struct expression *left, int op, struct expression *right)
751 struct range_list *rl;
753 if (op == '=') {
754 get_absolute_rl(right, &rl);
755 rl = cast_rl(get_type(left), rl);
756 } else {
757 rl = alloc_whole_rl(get_type(left));
760 set_extra_array_mod(left, alloc_estate_rl(rl));
763 static void match_untracked_array(struct expression *call, int param)
765 struct expression *arg;
767 arg = get_argument_from_call_expr(call->args, param);
768 arg = strip_expr(arg);
770 clear_array_states(arg);
773 static void match_vanilla_assign(struct expression *left, struct expression *right)
775 struct range_list *orig_rl = NULL;
776 struct range_list *rl = NULL;
777 struct symbol *right_sym;
778 struct symbol *left_type;
779 struct symbol *right_type;
780 char *right_name = NULL;
781 struct symbol *sym;
782 char *name;
783 sval_t max;
784 struct smatch_state *state;
785 int comparison;
787 if (is_struct(left))
788 return;
790 save_chunk_info(left, right);
792 name = expr_to_var_sym(left, &sym);
793 if (!name) {
794 if (is_array(left))
795 do_array_assign(left, '=', right);
796 return;
799 left_type = get_type(left);
800 right_type = get_type(right);
802 right_name = expr_to_var_sym(right, &right_sym);
804 if (!__in_fake_assign &&
805 !(right->type == EXPR_PREOP && right->op == '&') &&
806 right_name && right_sym &&
807 values_fit_type(left, right) &&
808 !has_symbol(right, sym)) {
809 set_equiv(left, right);
810 goto free;
813 if (is_pointer(right) && get_address_rl(right, &rl)) {
814 state = alloc_estate_rl(rl);
815 goto done;
818 if (__in_fake_assign) {
819 struct smatch_state *right_state;
820 sval_t sval;
822 if (get_value(right, &sval)) {
823 sval = sval_cast(left_type, sval);
824 state = alloc_estate_sval(sval);
825 goto done;
828 right_state = get_state(SMATCH_EXTRA, right_name, right_sym);
829 if (right_state) {
830 /* simple assignment */
831 state = clone_estate(right_state);
832 goto done;
835 state = alloc_estate_rl(alloc_whole_rl(left_type));
836 goto done;
839 comparison = get_comparison(left, right);
840 if (comparison) {
841 comparison = flip_comparison(comparison);
842 get_implied_rl(left, &orig_rl);
845 if (get_implied_rl(right, &rl)) {
846 rl = cast_rl(left_type, rl);
847 if (orig_rl)
848 filter_by_comparison(&rl, comparison, orig_rl);
849 state = alloc_estate_rl(rl);
850 if (get_hard_max(right, &max)) {
851 estate_set_hard_max(state);
852 estate_set_fuzzy_max(state, max);
854 } else {
855 rl = alloc_whole_rl(right_type);
856 rl = cast_rl(left_type, rl);
857 if (orig_rl)
858 filter_by_comparison(&rl, comparison, orig_rl);
859 state = alloc_estate_rl(rl);
862 done:
863 set_extra_mod(name, sym, state);
864 free:
865 free_string(right_name);
868 static int op_remove_assign(int op)
870 switch (op) {
871 case SPECIAL_ADD_ASSIGN:
872 return '+';
873 case SPECIAL_SUB_ASSIGN:
874 return '-';
875 case SPECIAL_MUL_ASSIGN:
876 return '*';
877 case SPECIAL_DIV_ASSIGN:
878 return '/';
879 case SPECIAL_MOD_ASSIGN:
880 return '%';
881 case SPECIAL_AND_ASSIGN:
882 return '&';
883 case SPECIAL_OR_ASSIGN:
884 return '|';
885 case SPECIAL_XOR_ASSIGN:
886 return '^';
887 case SPECIAL_SHL_ASSIGN:
888 return SPECIAL_LEFTSHIFT;
889 case SPECIAL_SHR_ASSIGN:
890 return SPECIAL_RIGHTSHIFT;
891 default:
892 return op;
896 static void match_assign(struct expression *expr)
898 struct range_list *rl = NULL;
899 struct expression *left;
900 struct expression *right;
901 struct expression *binop_expr;
902 struct symbol *left_type;
903 struct symbol *sym;
904 char *name;
905 sval_t left_min, left_max;
906 sval_t right_min, right_max;
907 sval_t res_min, res_max;
909 left = strip_expr(expr->left);
911 right = strip_parens(expr->right);
912 if (right->type == EXPR_CALL && sym_name_is("__builtin_expect", right->fn))
913 right = get_argument_from_call_expr(right->args, 0);
914 while (right->type == EXPR_ASSIGNMENT && right->op == '=')
915 right = strip_parens(right->left);
917 if (expr->op == '=' && is_condition(expr->right))
918 return; /* handled in smatch_condition.c */
919 if (expr->op == '=' && right->type == EXPR_CALL)
920 return; /* handled in smatch_function_hooks.c */
921 if (expr->op == '=') {
922 match_vanilla_assign(left, right);
923 return;
926 name = expr_to_var_sym(left, &sym);
927 if (!name)
928 return;
930 left_type = get_type(left);
932 res_min = sval_type_min(left_type);
933 res_max = sval_type_max(left_type);
935 switch (expr->op) {
936 case SPECIAL_ADD_ASSIGN:
937 get_absolute_max(left, &left_max);
938 get_absolute_max(right, &right_max);
939 if (sval_binop_overflows(left_max, '+', sval_cast(left_type, right_max)))
940 break;
941 if (get_implied_min(left, &left_min) &&
942 !sval_is_negative_min(left_min) &&
943 get_implied_min(right, &right_min) &&
944 !sval_is_negative_min(right_min)) {
945 res_min = sval_binop(left_min, '+', right_min);
946 res_min = sval_cast(left_type, res_min);
948 if (inside_loop()) /* we are assuming loops don't lead to wrapping */
949 break;
950 res_max = sval_binop(left_max, '+', right_max);
951 res_max = sval_cast(left_type, res_max);
952 break;
953 case SPECIAL_SUB_ASSIGN:
954 if (get_implied_max(left, &left_max) &&
955 !sval_is_max(left_max) &&
956 get_implied_min(right, &right_min) &&
957 !sval_is_min(right_min)) {
958 res_max = sval_binop(left_max, '-', right_min);
959 res_max = sval_cast(left_type, res_max);
961 if (inside_loop())
962 break;
963 if (get_implied_min(left, &left_min) &&
964 !sval_is_min(left_min) &&
965 get_implied_max(right, &right_max) &&
966 !sval_is_max(right_max) &&
967 sval_cmp(left_min, right_max) > 0) {
968 res_min = sval_binop(left_min, '-', right_max);
969 res_min = sval_cast(left_type, res_min);
971 break;
972 case SPECIAL_AND_ASSIGN:
973 case SPECIAL_MOD_ASSIGN:
974 case SPECIAL_SHL_ASSIGN:
975 case SPECIAL_SHR_ASSIGN:
976 case SPECIAL_OR_ASSIGN:
977 case SPECIAL_XOR_ASSIGN:
978 case SPECIAL_MUL_ASSIGN:
979 case SPECIAL_DIV_ASSIGN:
980 binop_expr = binop_expression(expr->left,
981 op_remove_assign(expr->op),
982 expr->right);
983 if (get_absolute_rl(binop_expr, &rl)) {
984 rl = cast_rl(left_type, rl);
985 set_extra_mod(name, sym, alloc_estate_rl(rl));
986 goto free;
988 break;
990 rl = cast_rl(left_type, alloc_rl(res_min, res_max));
991 set_extra_mod(name, sym, alloc_estate_rl(rl));
992 free:
993 free_string(name);
996 static struct smatch_state *increment_state(struct smatch_state *state)
998 sval_t min = estate_min(state);
999 sval_t max = estate_max(state);
1001 if (!estate_rl(state))
1002 return NULL;
1004 if (inside_loop())
1005 max = sval_type_max(max.type);
1007 if (!sval_is_min(min) && !sval_is_max(min))
1008 min.value++;
1009 if (!sval_is_min(max) && !sval_is_max(max))
1010 max.value++;
1011 return alloc_estate_range(min, max);
1014 static struct smatch_state *decrement_state(struct smatch_state *state)
1016 sval_t min = estate_min(state);
1017 sval_t max = estate_max(state);
1019 if (!estate_rl(state))
1020 return NULL;
1022 if (inside_loop())
1023 min = sval_type_min(min.type);
1025 if (!sval_is_min(min) && !sval_is_max(min))
1026 min.value--;
1027 if (!sval_is_min(max) && !sval_is_max(max))
1028 max.value--;
1029 return alloc_estate_range(min, max);
1032 static void clear_pointed_at_state(struct expression *expr)
1034 struct symbol *type;
1037 * ALERT: This is sort of a mess. If it's is a struct assigment like
1038 * "foo = bar;", then that's handled by smatch_struct_assignment.c.
1039 * the same thing for p++ where "p" is a struct. Most modifications
1040 * are handled by the assignment hook or the db. Smatch_extra.c doesn't
1041 * use smatch_modification.c because we have to get the ordering right
1042 * or something. So if you have p++ where p is a pointer to a standard
1043 * c type then we handle that here. What a mess.
1046 type = get_type(expr);
1047 if (!type || type->type != SYM_PTR)
1048 return;
1049 type = get_real_base_type(type);
1050 if (!type || type->type != SYM_BASETYPE)
1051 return;
1052 set_extra_expr_mod(deref_expression(expr), alloc_estate_whole(type));
1055 static void unop_expr(struct expression *expr)
1057 struct smatch_state *state;
1059 if (expr->smatch_flags & Handled)
1060 return;
1062 switch (expr->op) {
1063 case SPECIAL_INCREMENT:
1064 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1065 state = increment_state(state);
1066 if (!state)
1067 state = alloc_estate_whole(get_type(expr));
1068 set_extra_expr_mod(expr->unop, state);
1069 clear_pointed_at_state(expr->unop);
1070 break;
1071 case SPECIAL_DECREMENT:
1072 state = get_state_expr(SMATCH_EXTRA, expr->unop);
1073 state = decrement_state(state);
1074 if (!state)
1075 state = alloc_estate_whole(get_type(expr));
1076 set_extra_expr_mod(expr->unop, state);
1077 clear_pointed_at_state(expr->unop);
1078 break;
1079 default:
1080 return;
1084 static void asm_expr(struct statement *stmt)
1087 struct expression *expr;
1088 struct symbol *type;
1089 int state = 0;
1091 FOR_EACH_PTR(stmt->asm_outputs, expr) {
1092 switch (state) {
1093 case 0: /* identifier */
1094 case 1: /* constraint */
1095 state++;
1096 continue;
1097 case 2: /* expression */
1098 state = 0;
1099 type = get_type(strip_expr(expr));
1100 set_extra_expr_mod(expr, alloc_estate_whole(type));
1101 continue;
1103 } END_FOR_EACH_PTR(expr);
1106 static void check_dereference(struct expression *expr)
1108 if (__in_fake_assign)
1109 return;
1110 if (outside_of_function())
1111 return;
1112 if (implied_not_equal(expr, 0))
1113 return;
1114 set_extra_expr_nomod(expr, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
1117 static void match_dereferences(struct expression *expr)
1119 if (expr->type != EXPR_PREOP)
1120 return;
1121 /* it's saying that foo[1] = bar dereferences foo[1] */
1122 if (is_array(expr))
1123 return;
1124 check_dereference(expr->unop);
1127 static void match_pointer_as_array(struct expression *expr)
1129 if (!is_array(expr))
1130 return;
1131 check_dereference(get_array_base(expr));
1134 static void find_dereferences(struct expression *expr)
1136 while (expr->type == EXPR_PREOP) {
1137 if (expr->op == '*')
1138 check_dereference(expr->unop);
1139 expr = strip_expr(expr->unop);
1143 static void set_param_dereferenced(struct expression *arg, char *key, char *unused)
1145 struct symbol *sym;
1146 char *name;
1148 name = get_variable_from_key(arg, key, &sym);
1149 if (name && sym)
1150 set_extra_nomod(name, sym, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
1151 free_string(name);
1153 find_dereferences(arg);
1156 static sval_t add_one(sval_t sval)
1158 sval.value++;
1159 return sval;
1162 static int handle_postop_inc(struct expression *left, int op, struct expression *right)
1164 struct statement *stmt;
1165 struct expression *cond;
1166 struct smatch_state *true_state, *false_state;
1167 sval_t start;
1168 sval_t limit;
1171 * If we're decrementing here then that's a canonical while count down
1172 * so it's handled already. We're only handling loops like:
1173 * i = 0;
1174 * do { ... } while (i++ < 3);
1177 if (left->type != EXPR_POSTOP || left->op != SPECIAL_INCREMENT)
1178 return 0;
1180 stmt = __cur_stmt->parent;
1181 if (!stmt)
1182 return 0;
1183 if (stmt->type == STMT_COMPOUND)
1184 stmt = stmt->parent;
1185 if (!stmt || stmt->type != STMT_ITERATOR || !stmt->iterator_post_condition)
1186 return 0;
1188 cond = strip_expr(stmt->iterator_post_condition);
1189 if (cond->type != EXPR_COMPARE || cond->op != op)
1190 return 0;
1191 if (left != strip_expr(cond->left) || right != strip_expr(cond->right))
1192 return 0;
1194 if (!get_implied_value(left->unop, &start))
1195 return 0;
1196 if (!get_implied_value(right, &limit))
1197 return 0;
1199 if (sval_cmp(start, limit) > 0)
1200 return 0;
1202 switch (op) {
1203 case '<':
1204 case SPECIAL_UNSIGNED_LT:
1205 break;
1206 case SPECIAL_LTE:
1207 case SPECIAL_UNSIGNED_LTE:
1208 limit = add_one(limit);
1209 default:
1210 return 0;
1214 true_state = alloc_estate_range(add_one(start), limit);
1215 false_state = alloc_estate_range(add_one(limit), add_one(limit));
1217 /* Currently we just discard the false state but when two passes is
1218 * implimented correctly then it will use it.
1221 set_extra_expr_true_false(left->unop, true_state, false_state);
1223 return 1;
1226 static void handle_comparison(struct symbol *type, struct expression *left, int op, struct expression *right)
1228 struct range_list *left_orig;
1229 struct range_list *left_true;
1230 struct range_list *left_false;
1231 struct range_list *right_orig;
1232 struct range_list *right_true;
1233 struct range_list *right_false;
1234 struct smatch_state *left_true_state;
1235 struct smatch_state *left_false_state;
1236 struct smatch_state *right_true_state;
1237 struct smatch_state *right_false_state;
1238 sval_t dummy, hard_max;
1239 int left_postop = 0;
1240 int right_postop = 0;
1242 if (left->op == SPECIAL_INCREMENT || left->op == SPECIAL_DECREMENT) {
1243 if (left->type == EXPR_POSTOP) {
1244 left->smatch_flags |= Handled;
1245 left_postop = left->op;
1246 if (handle_postop_inc(left, op, right))
1247 return;
1249 left = strip_parens(left->unop);
1251 while (left->type == EXPR_ASSIGNMENT)
1252 left = strip_parens(left->left);
1254 if (right->op == SPECIAL_INCREMENT || right->op == SPECIAL_DECREMENT) {
1255 if (right->type == EXPR_POSTOP) {
1256 right->smatch_flags |= Handled;
1257 right_postop = right->op;
1259 right = strip_parens(right->unop);
1262 get_real_absolute_rl(left, &left_orig);
1263 left_orig = cast_rl(type, left_orig);
1265 get_real_absolute_rl(right, &right_orig);
1266 right_orig = cast_rl(type, right_orig);
1268 split_comparison_rl(left_orig, op, right_orig, &left_true, &left_false, &right_true, &right_false);
1270 left_true = rl_truncate_cast(get_type(strip_expr(left)), left_true);
1271 left_false = rl_truncate_cast(get_type(strip_expr(left)), left_false);
1272 right_true = rl_truncate_cast(get_type(strip_expr(right)), right_true);
1273 right_false = rl_truncate_cast(get_type(strip_expr(right)), right_false);
1275 if (!left_true || !left_false) {
1276 struct range_list *tmp_true, *tmp_false;
1278 split_comparison_rl(alloc_whole_rl(type), op, right_orig, &tmp_true, &tmp_false, NULL, NULL);
1279 tmp_true = rl_truncate_cast(get_type(strip_expr(left)), tmp_true);
1280 tmp_false = rl_truncate_cast(get_type(strip_expr(left)), tmp_false);
1281 if (tmp_true && tmp_false)
1282 __save_imaginary_state(left, tmp_true, tmp_false);
1285 if (!right_true || !right_false) {
1286 struct range_list *tmp_true, *tmp_false;
1288 split_comparison_rl(alloc_whole_rl(type), op, right_orig, NULL, NULL, &tmp_true, &tmp_false);
1289 tmp_true = rl_truncate_cast(get_type(strip_expr(right)), tmp_true);
1290 tmp_false = rl_truncate_cast(get_type(strip_expr(right)), tmp_false);
1291 if (tmp_true && tmp_false)
1292 __save_imaginary_state(right, tmp_true, tmp_false);
1295 left_true_state = alloc_estate_rl(left_true);
1296 left_false_state = alloc_estate_rl(left_false);
1297 right_true_state = alloc_estate_rl(right_true);
1298 right_false_state = alloc_estate_rl(right_false);
1300 switch (op) {
1301 case '<':
1302 case SPECIAL_UNSIGNED_LT:
1303 case SPECIAL_UNSIGNED_LTE:
1304 case SPECIAL_LTE:
1305 if (get_hard_max(right, &dummy))
1306 estate_set_hard_max(left_true_state);
1307 if (get_hard_max(left, &dummy))
1308 estate_set_hard_max(right_false_state);
1309 break;
1310 case '>':
1311 case SPECIAL_UNSIGNED_GT:
1312 case SPECIAL_UNSIGNED_GTE:
1313 case SPECIAL_GTE:
1314 if (get_hard_max(left, &dummy))
1315 estate_set_hard_max(right_true_state);
1316 if (get_hard_max(right, &dummy))
1317 estate_set_hard_max(left_false_state);
1318 break;
1321 switch (op) {
1322 case '<':
1323 case SPECIAL_UNSIGNED_LT:
1324 case SPECIAL_UNSIGNED_LTE:
1325 case SPECIAL_LTE:
1326 if (get_hard_max(right, &hard_max)) {
1327 if (op == '<' || op == SPECIAL_UNSIGNED_LT)
1328 hard_max.value--;
1329 estate_set_fuzzy_max(left_true_state, hard_max);
1331 if (get_implied_value(right, &hard_max)) {
1332 if (op == SPECIAL_UNSIGNED_LTE ||
1333 op == SPECIAL_LTE)
1334 hard_max.value++;
1335 estate_set_fuzzy_max(left_false_state, hard_max);
1337 if (get_hard_max(left, &hard_max)) {
1338 if (op == SPECIAL_UNSIGNED_LTE ||
1339 op == SPECIAL_LTE)
1340 hard_max.value--;
1341 estate_set_fuzzy_max(right_false_state, hard_max);
1343 if (get_implied_value(left, &hard_max)) {
1344 if (op == '<' || op == SPECIAL_UNSIGNED_LT)
1345 hard_max.value++;
1346 estate_set_fuzzy_max(right_true_state, hard_max);
1348 break;
1349 case '>':
1350 case SPECIAL_UNSIGNED_GT:
1351 case SPECIAL_UNSIGNED_GTE:
1352 case SPECIAL_GTE:
1353 if (get_hard_max(left, &hard_max)) {
1354 if (op == '>' || op == SPECIAL_UNSIGNED_GT)
1355 hard_max.value--;
1356 estate_set_fuzzy_max(right_true_state, hard_max);
1358 if (get_implied_value(left, &hard_max)) {
1359 if (op == SPECIAL_UNSIGNED_GTE ||
1360 op == SPECIAL_GTE)
1361 hard_max.value++;
1362 estate_set_fuzzy_max(right_false_state, hard_max);
1364 if (get_hard_max(right, &hard_max)) {
1365 if (op == SPECIAL_UNSIGNED_LTE ||
1366 op == SPECIAL_LTE)
1367 hard_max.value--;
1368 estate_set_fuzzy_max(left_false_state, hard_max);
1370 if (get_implied_value(right, &hard_max)) {
1371 if (op == '>' ||
1372 op == SPECIAL_UNSIGNED_GT)
1373 hard_max.value++;
1374 estate_set_fuzzy_max(left_true_state, hard_max);
1376 break;
1377 case SPECIAL_EQUAL:
1378 if (get_hard_max(left, &hard_max))
1379 estate_set_fuzzy_max(right_true_state, hard_max);
1380 if (get_hard_max(right, &hard_max))
1381 estate_set_fuzzy_max(left_true_state, hard_max);
1382 break;
1385 if (get_hard_max(left, &hard_max)) {
1386 estate_set_hard_max(left_true_state);
1387 estate_set_hard_max(left_false_state);
1389 if (get_hard_max(right, &hard_max)) {
1390 estate_set_hard_max(right_true_state);
1391 estate_set_hard_max(right_false_state);
1394 if (left_postop == SPECIAL_INCREMENT) {
1395 left_true_state = increment_state(left_true_state);
1396 left_false_state = increment_state(left_false_state);
1398 if (left_postop == SPECIAL_DECREMENT) {
1399 left_true_state = decrement_state(left_true_state);
1400 left_false_state = decrement_state(left_false_state);
1402 if (right_postop == SPECIAL_INCREMENT) {
1403 right_true_state = increment_state(right_true_state);
1404 right_false_state = increment_state(right_false_state);
1406 if (right_postop == SPECIAL_DECREMENT) {
1407 right_true_state = decrement_state(right_true_state);
1408 right_false_state = decrement_state(right_false_state);
1411 if (estate_rl(left_true_state) && estates_equiv(left_true_state, left_false_state)) {
1412 left_true_state = NULL;
1413 left_false_state = NULL;
1416 if (estate_rl(right_true_state) && estates_equiv(right_true_state, right_false_state)) {
1417 right_true_state = NULL;
1418 right_false_state = NULL;
1421 set_extra_expr_true_false(left, left_true_state, left_false_state);
1422 set_extra_expr_true_false(right, right_true_state, right_false_state);
1425 static int is_simple_math(struct expression *expr)
1427 if (!expr)
1428 return 0;
1429 if (expr->type != EXPR_BINOP)
1430 return 0;
1431 switch (expr->op) {
1432 case '+':
1433 case '-':
1434 case '*':
1435 return 1;
1437 return 0;
1440 static void move_known_values(struct expression **left_p, struct expression **right_p)
1442 struct expression *left = *left_p;
1443 struct expression *right = *right_p;
1444 sval_t sval, dummy;
1446 if (get_implied_value(left, &sval)) {
1447 if (!is_simple_math(right))
1448 return;
1449 if (get_implied_value(right, &dummy))
1450 return;
1451 if (right->op == '*') {
1452 sval_t divisor;
1454 if (!get_value(right->right, &divisor))
1455 return;
1456 if (divisor.value == 0 && sval.value % divisor.value)
1457 return;
1458 *left_p = binop_expression(left, invert_op(right->op), right->right);
1459 *right_p = right->left;
1460 return;
1462 if (right->op == '+' && get_value(right->left, &sval)) {
1463 *left_p = binop_expression(left, invert_op(right->op), right->left);
1464 *right_p = right->right;
1465 return;
1467 if (get_value(right->right, &sval)) {
1468 *left_p = binop_expression(left, invert_op(right->op), right->right);
1469 *right_p = right->left;
1470 return;
1472 return;
1474 if (get_implied_value(right, &sval)) {
1475 if (!is_simple_math(left))
1476 return;
1477 if (get_implied_value(left, &dummy))
1478 return;
1479 if (left->op == '*') {
1480 sval_t divisor;
1482 if (!get_value(left->right, &divisor))
1483 return;
1484 if (divisor.value == 0 && sval.value % divisor.value)
1485 return;
1486 *right_p = binop_expression(right, invert_op(left->op), left->right);
1487 *left_p = left->left;
1488 return;
1490 if (left->op == '+' && get_value(left->left, &sval)) {
1491 *right_p = binop_expression(right, invert_op(left->op), left->left);
1492 *left_p = left->right;
1493 return;
1496 if (get_value(left->right, &sval)) {
1497 *right_p = binop_expression(right, invert_op(left->op), left->right);
1498 *left_p = left->left;
1499 return;
1501 return;
1505 static int match_func_comparison(struct expression *expr)
1507 struct expression *left = strip_expr(expr->left);
1508 struct expression *right = strip_expr(expr->right);
1509 sval_t sval;
1512 * fixme: think about this harder. We should always be trying to limit
1513 * the non-call side as well. If we can't determine the limitter does
1514 * that mean we aren't querying the database and are missing important
1515 * information?
1518 if (left->type == EXPR_CALL) {
1519 if (get_implied_value(left, &sval)) {
1520 handle_comparison(get_type(expr), left, expr->op, right);
1521 return 1;
1523 function_comparison(left, expr->op, right);
1524 return 1;
1527 if (right->type == EXPR_CALL) {
1528 if (get_implied_value(right, &sval)) {
1529 handle_comparison(get_type(expr), left, expr->op, right);
1530 return 1;
1532 function_comparison(left, expr->op, right);
1533 return 1;
1536 return 0;
1539 /* Handle conditions like "if (foo + bar < foo) {" */
1540 static int handle_integer_overflow_test(struct expression *expr)
1542 struct expression *left, *right;
1543 struct symbol *type;
1544 sval_t left_min, right_min, min, max;
1546 if (expr->op != '<' && expr->op != SPECIAL_UNSIGNED_LT)
1547 return 0;
1549 left = strip_parens(expr->left);
1550 right = strip_parens(expr->right);
1552 if (left->op != '+')
1553 return 0;
1555 type = get_type(expr);
1556 if (!type)
1557 return 0;
1558 if (type_positive_bits(type) == 32) {
1559 max.type = &uint_ctype;
1560 max.uvalue = (unsigned int)-1;
1561 } else if (type_positive_bits(type) == 64) {
1562 max.type = &ulong_ctype;
1563 max.value = (unsigned long long)-1;
1564 } else {
1565 return 0;
1568 if (!expr_equiv(left->left, right) && !expr_equiv(left->right, right))
1569 return 0;
1571 get_absolute_min(left->left, &left_min);
1572 get_absolute_min(left->right, &right_min);
1573 min = sval_binop(left_min, '+', right_min);
1575 set_extra_chunk_true_false(left, NULL, alloc_estate_range(min, max));
1576 return 1;
1579 static void match_comparison(struct expression *expr)
1581 struct expression *left_orig = strip_parens(expr->left);
1582 struct expression *right_orig = strip_parens(expr->right);
1583 struct expression *left, *right;
1584 struct expression *prev;
1585 struct symbol *type;
1587 if (match_func_comparison(expr))
1588 return;
1590 type = get_type(expr);
1591 if (!type)
1592 type = &llong_ctype;
1594 if (handle_integer_overflow_test(expr))
1595 return;
1597 left = left_orig;
1598 right = right_orig;
1599 move_known_values(&left, &right);
1600 handle_comparison(type, left, expr->op, right);
1602 prev = get_assigned_expr(left_orig);
1603 if (is_simple_math(prev) && has_variable(prev, left_orig) == 0) {
1604 left = prev;
1605 right = right_orig;
1606 move_known_values(&left, &right);
1607 handle_comparison(type, left, expr->op, right);
1610 prev = get_assigned_expr(right_orig);
1611 if (is_simple_math(prev) && has_variable(prev, right_orig) == 0) {
1612 left = left_orig;
1613 right = prev;
1614 move_known_values(&left, &right);
1615 handle_comparison(type, left, expr->op, right);
1619 static sval_t get_high_mask(sval_t known)
1621 sval_t ret;
1622 int i;
1624 ret = known;
1625 ret.value = 0;
1627 for (i = type_bits(known.type) - 1; i >= 0; i--) {
1628 if (known.uvalue & (1ULL << i))
1629 ret.uvalue |= (1ULL << i);
1630 else
1631 return ret;
1634 return ret;
1637 static void handle_AND_condition(struct expression *expr)
1639 struct range_list *orig_rl;
1640 struct range_list *true_rl = NULL;
1641 struct range_list *false_rl = NULL;
1642 sval_t known;
1643 int bit;
1645 if (get_implied_value(expr->left, &known)) {
1646 sval_t low_mask = known;
1647 sval_t high_mask;
1649 if (known.value > 0) {
1650 bit = ffsll(known.value) - 1;
1651 low_mask.uvalue = (1ULL << bit) - 1;
1652 get_absolute_rl(expr->right, &orig_rl);
1653 true_rl = remove_range(orig_rl, sval_type_val(known.type, 0), low_mask);
1655 high_mask = get_high_mask(known);
1656 if (high_mask.value) {
1657 bit = ffsll(high_mask.value) - 1;
1658 low_mask.uvalue = (1ULL << bit) - 1;
1660 get_absolute_rl(expr->left, &orig_rl);
1661 if (sval_is_negative(rl_min(orig_rl)))
1662 orig_rl = remove_range(orig_rl, sval_type_min(known.type), sval_type_val(known.type, -1));
1663 false_rl = remove_range(orig_rl, low_mask, sval_type_max(known.type));
1664 if (type_signed(high_mask.type) && type_unsigned(rl_type(false_rl))) {
1665 false_rl = remove_range(false_rl,
1666 sval_type_val(rl_type(false_rl), sval_type_max(known.type).uvalue),
1667 sval_type_val(rl_type(false_rl), -1));
1670 set_extra_expr_true_false(expr->right,
1671 true_rl ? alloc_estate_rl(true_rl) : NULL,
1672 false_rl ? alloc_estate_rl(false_rl) : NULL);
1674 return;
1677 if (get_implied_value(expr->right, &known)) {
1678 sval_t low_mask = known;
1679 sval_t high_mask;
1681 if (known.value > 0) {
1682 bit = ffsll(known.value) - 1;
1683 low_mask.uvalue = (1ULL << bit) - 1;
1684 get_absolute_rl(expr->left, &orig_rl);
1685 true_rl = remove_range(orig_rl, sval_type_val(known.type, 0), low_mask);
1687 high_mask = get_high_mask(known);
1688 if (high_mask.value) {
1689 bit = ffsll(high_mask.value) - 1;
1690 low_mask.uvalue = (1ULL << bit) - 1;
1692 get_absolute_rl(expr->left, &orig_rl);
1693 if (sval_is_negative(rl_min(orig_rl)))
1694 orig_rl = remove_range(orig_rl, sval_type_min(known.type), sval_type_val(known.type, -1));
1695 false_rl = remove_range(orig_rl, low_mask, sval_type_max(known.type));
1696 if (type_signed(high_mask.type) && type_unsigned(rl_type(false_rl))) {
1697 false_rl = remove_range(false_rl,
1698 sval_type_val(rl_type(false_rl), sval_type_max(known.type).uvalue),
1699 sval_type_val(rl_type(false_rl), -1));
1702 set_extra_expr_true_false(expr->left,
1703 true_rl ? alloc_estate_rl(true_rl) : NULL,
1704 false_rl ? alloc_estate_rl(false_rl) : NULL);
1705 return;
1709 static void handle_MOD_condition(struct expression *expr)
1711 struct range_list *orig_rl;
1712 struct range_list *true_rl;
1713 struct range_list *false_rl = NULL;
1714 sval_t right;
1715 sval_t zero = {
1716 .value = 0,
1719 if (!get_implied_value(expr->right, &right) || right.value == 0)
1720 return;
1721 get_absolute_rl(expr->left, &orig_rl);
1723 zero.type = rl_type(orig_rl);
1725 /* We're basically dorking around the min and max here */
1726 true_rl = remove_range(orig_rl, zero, zero);
1727 if (!sval_is_max(rl_max(true_rl)) &&
1728 !(rl_max(true_rl).value % right.value))
1729 true_rl = remove_range(true_rl, rl_max(true_rl), rl_max(true_rl));
1731 if (rl_equiv(true_rl, orig_rl))
1732 true_rl = NULL;
1734 if (sval_is_positive(rl_min(orig_rl)) &&
1735 (rl_max(orig_rl).value - rl_min(orig_rl).value) / right.value < 5) {
1736 sval_t add;
1737 int i;
1739 add = rl_min(orig_rl);
1740 add.value += right.value - (add.value % right.value);
1741 add.value -= right.value;
1743 for (i = 0; i < 5; i++) {
1744 add.value += right.value;
1745 if (add.value > rl_max(orig_rl).value)
1746 break;
1747 add_range(&false_rl, add, add);
1749 } else {
1750 if (rl_min(orig_rl).uvalue != 0 &&
1751 rl_min(orig_rl).uvalue < right.uvalue) {
1752 sval_t chop = right;
1753 chop.value--;
1754 false_rl = remove_range(orig_rl, zero, chop);
1757 if (!sval_is_max(rl_max(orig_rl)) &&
1758 (rl_max(orig_rl).value % right.value)) {
1759 sval_t chop = rl_max(orig_rl);
1760 chop.value -= chop.value % right.value;
1761 chop.value++;
1762 if (!false_rl)
1763 false_rl = clone_rl(orig_rl);
1764 false_rl = remove_range(false_rl, chop, rl_max(orig_rl));
1768 set_extra_expr_true_false(expr->left,
1769 true_rl ? alloc_estate_rl(true_rl) : NULL,
1770 false_rl ? alloc_estate_rl(false_rl) : NULL);
1773 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
1774 void __extra_match_condition(struct expression *expr)
1776 struct smatch_state *pre_state;
1777 struct smatch_state *true_state;
1778 struct smatch_state *false_state;
1780 expr = strip_expr(expr);
1781 switch (expr->type) {
1782 case EXPR_CALL:
1783 function_comparison(expr, SPECIAL_NOTEQUAL, zero_expr());
1784 return;
1785 case EXPR_PREOP:
1786 case EXPR_SYMBOL:
1787 case EXPR_DEREF: {
1788 sval_t zero;
1790 zero = sval_blank(expr);
1791 zero.value = 0;
1793 pre_state = get_extra_state(expr);
1794 true_state = estate_filter_sval(pre_state, zero);
1795 if (possibly_true(expr, SPECIAL_EQUAL, zero_expr()))
1796 false_state = alloc_estate_sval(zero);
1797 else
1798 false_state = alloc_estate_empty();
1799 set_extra_expr_true_false(expr, true_state, false_state);
1800 return;
1802 case EXPR_COMPARE:
1803 match_comparison(expr);
1804 return;
1805 case EXPR_ASSIGNMENT:
1806 __extra_match_condition(expr->left);
1807 return;
1808 case EXPR_BINOP:
1809 if (expr->op == '&')
1810 handle_AND_condition(expr);
1811 if (expr->op == '%')
1812 handle_MOD_condition(expr);
1813 return;
1817 static void assume_indexes_are_valid(struct expression *expr)
1819 struct expression *array_expr;
1820 int array_size;
1821 struct expression *offset;
1822 struct symbol *offset_type;
1823 struct range_list *rl_before;
1824 struct range_list *rl_after;
1825 struct range_list *filter = NULL;
1826 sval_t size;
1828 expr = strip_expr(expr);
1829 if (!is_array(expr))
1830 return;
1832 offset = get_array_offset(expr);
1833 offset_type = get_type(offset);
1834 if (offset_type && type_signed(offset_type)) {
1835 filter = alloc_rl(sval_type_min(offset_type),
1836 sval_type_val(offset_type, -1));
1839 array_expr = get_array_base(expr);
1840 array_size = get_real_array_size(array_expr);
1841 if (array_size > 1) {
1842 size = sval_type_val(offset_type, array_size);
1843 add_range(&filter, size, sval_type_max(offset_type));
1846 if (!filter)
1847 return;
1848 get_absolute_rl(offset, &rl_before);
1849 rl_after = rl_filter(rl_before, filter);
1850 if (rl_equiv(rl_before, rl_after))
1851 return;
1852 set_extra_expr_nomod(offset, alloc_estate_rl(rl_after));
1855 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
1856 int implied_not_equal(struct expression *expr, long long val)
1858 return !possibly_false(expr, SPECIAL_NOTEQUAL, value_expr(val));
1861 int implied_not_equal_name_sym(char *name, struct symbol *sym, long long val)
1863 struct smatch_state *estate;
1865 estate = get_state(SMATCH_EXTRA, name, sym);
1866 if (!estate)
1867 return 0;
1868 if (!rl_has_sval(estate_rl(estate), sval_type_val(estate_type(estate), 0)))
1869 return 1;
1870 return 0;
1873 int parent_is_null_var_sym(const char *name, struct symbol *sym)
1875 char buf[256];
1876 char *start;
1877 char *end;
1878 struct smatch_state *state;
1880 strncpy(buf, name, sizeof(buf) - 1);
1881 buf[sizeof(buf) - 1] = '\0';
1883 start = &buf[0];
1884 while (*start == '*') {
1885 start++;
1886 state = get_state(SMATCH_EXTRA, start, sym);
1887 if (!state)
1888 continue;
1889 if (!estate_rl(state))
1890 return 1;
1891 if (estate_min(state).value == 0 &&
1892 estate_max(state).value == 0)
1893 return 1;
1896 start = &buf[0];
1897 while (*start == '&')
1898 start++;
1900 while ((end = strrchr(start, '-'))) {
1901 *end = '\0';
1902 state = get_state(SMATCH_EXTRA, start, sym);
1903 if (!state)
1904 continue;
1905 if (estate_min(state).value == 0 &&
1906 estate_max(state).value == 0)
1907 return 1;
1909 return 0;
1912 int parent_is_null(struct expression *expr)
1914 struct symbol *sym;
1915 char *var;
1916 int ret = 0;
1918 expr = strip_expr(expr);
1919 var = expr_to_var_sym(expr, &sym);
1920 if (!var || !sym)
1921 goto free;
1922 ret = parent_is_null_var_sym(var, sym);
1923 free:
1924 free_string(var);
1925 return ret;
1928 static int param_used_callback(void *found, int argc, char **argv, char **azColName)
1930 *(int *)found = 1;
1931 return 0;
1934 static int filter_unused_kzalloc_info(struct expression *call, int param, char *printed_name, struct sm_state *sm)
1936 sval_t sval;
1937 int found = 0;
1939 /* for function pointers assume everything is used */
1940 if (call->fn->type != EXPR_SYMBOL)
1941 return 0;
1944 * kzalloc() information is treated as special because so there is just
1945 * a lot of stuff initialized to zero and it makes building the database
1946 * take hours and hours.
1948 * In theory, we should just remove this line and not pass any unused
1949 * information, but I'm not sure enough that this code works so I want
1950 * to hold off on that for now.
1952 if (!estate_get_single_value(sm->state, &sval) || sval.value != 0)
1953 return 0;
1955 run_sql(&param_used_callback, &found,
1956 "select * from call_implies where %s and type = %d and parameter = %d and key = '%s';",
1957 get_static_filter(call->fn->symbol), PARAM_USED, param, printed_name);
1958 if (found)
1959 return 0;
1961 /* If the database is not built yet, then assume everything is used */
1962 run_sql(&param_used_callback, &found,
1963 "select * from call_implies where %s and type = %d;",
1964 get_static_filter(call->fn->symbol), PARAM_USED);
1965 if (!found)
1966 return 0;
1968 return 1;
1971 struct range_list *intersect_with_real_abs_var_sym(const char *name, struct symbol *sym, struct range_list *start)
1973 struct smatch_state *state;
1976 * Here is the difference between implied value and real absolute, say
1977 * you have:
1979 * int a = (u8)x;
1981 * Then you know that a is 0-255. That's real absolute. But you don't
1982 * know for sure that it actually goes up to 255. So it's not implied.
1983 * Implied indicates a degree of certainty.
1985 * But then say you cap "a" at 8. That means you know it goes up to
1986 * 8. So now the implied value is s32min-8. But you can combine it
1987 * with the real absolute to say that actually it's 0-8.
1989 * We are combining it here. But now that I think about it, this is
1990 * probably not the ideal place to combine it because it should proably
1991 * be done earlier. Oh well, this is an improvement on what was there
1992 * before so I'm going to commit this code.
1996 state = get_real_absolute_state_var_sym(name, sym);
1997 if (!state || !estate_rl(state))
1998 return start;
2000 return rl_intersection(estate_rl(state), start);
2003 struct range_list *intersect_with_real_abs_expr(struct expression *expr, struct range_list *start)
2005 struct smatch_state *state;
2007 state = get_real_absolute_state(expr);
2008 if (!state || !estate_rl(state))
2009 return start;
2011 return rl_intersection(estate_rl(state), start);
2014 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
2016 struct range_list *rl;
2018 if (estate_is_whole(sm->state))
2019 return;
2020 if (filter_unused_kzalloc_info(call, param, printed_name, sm))
2021 return;
2022 rl = estate_rl(sm->state);
2023 rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
2024 sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
2025 if (estate_has_fuzzy_max(sm->state))
2026 sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
2027 sval_to_str(estate_get_fuzzy_max(sm->state)));
2030 static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2032 struct symbol *returned_sym;
2033 struct sm_state *sm;
2034 const char *param_name;
2035 char *compare_str;
2036 char buf[256];
2038 returned_sym = expr_to_sym(expr);
2039 if (!returned_sym)
2040 return;
2042 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
2043 if (!estate_rl(sm->state))
2044 continue;
2045 if (returned_sym != sm->sym)
2046 continue;
2048 param_name = get_param_name(sm);
2049 if (!param_name)
2050 continue;
2051 if (strcmp(param_name, "$") == 0)
2052 continue;
2053 compare_str = name_sym_to_param_comparison(sm->name, sm->sym);
2054 if (!compare_str && estate_is_whole(sm->state))
2055 continue;
2056 snprintf(buf, sizeof(buf), "%s%s", sm->state->name, compare_str ?: "");
2058 sql_insert_return_states(return_id, return_ranges, PARAM_VALUE,
2059 -1, param_name, buf);
2060 } END_FOR_EACH_SM(sm);
2063 static void db_limited_before(void)
2065 unmatched_stree = clone_stree(__get_cur_stree());
2068 static void db_limited_after(void)
2070 free_stree(&unmatched_stree);
2073 static int rl_fits_in_type(struct range_list *rl, struct symbol *type)
2075 if (type_bits(rl_type(rl)) <= type_bits(type))
2076 return 1;
2077 if (sval_cmp(rl_max(rl), sval_type_max(type)) > 0)
2078 return 0;
2079 if (sval_is_negative(rl_min(rl)) &&
2080 sval_cmp(rl_min(rl), sval_type_min(type)) < 0)
2081 return 0;
2082 return 1;
2085 static int basically_the_same(struct range_list *orig, struct range_list *new)
2087 if (rl_equiv(orig, new))
2088 return 1;
2091 * The whole range is essentially the same as 0,4096-27777777777 so
2092 * don't overwrite the implications just to store that.
2095 if (rl_type(orig)->type == SYM_PTR &&
2096 is_whole_rl(orig) &&
2097 rl_min(new).value == 0 &&
2098 rl_max(new).value == valid_ptr_max)
2099 return 1;
2100 return 0;
2103 static void db_param_limit_filter(struct expression *expr, int param, char *key, char *value, enum info_type op)
2105 struct expression *arg;
2106 char *name;
2107 struct symbol *sym;
2108 struct var_sym_list *vsl = NULL;
2109 struct sm_state *sm;
2110 struct symbol *compare_type, *var_type;
2111 struct range_list *rl;
2112 struct range_list *limit;
2113 struct range_list *new;
2115 while (expr->type == EXPR_ASSIGNMENT)
2116 expr = strip_expr(expr->right);
2117 if (expr->type != EXPR_CALL)
2118 return;
2120 arg = get_argument_from_call_expr(expr->args, param);
2121 if (!arg)
2122 return;
2124 name = get_chunk_from_key(arg, key, &sym, &vsl);
2125 if (!name)
2126 return;
2127 if (op != PARAM_LIMIT && !sym)
2128 goto free;
2130 if (strcmp(key, "$") == 0)
2131 compare_type = get_arg_type(expr->fn, param);
2132 else
2133 compare_type = get_member_type_from_key(arg, key);
2135 sm = get_sm_state(SMATCH_EXTRA, name, sym);
2136 if (sm)
2137 rl = estate_rl(sm->state);
2138 else
2139 rl = alloc_whole_rl(compare_type);
2141 if (op == PARAM_LIMIT && !rl_fits_in_type(rl, compare_type))
2142 goto free;
2144 call_results_to_rl(expr, compare_type, value, &limit);
2145 new = rl_intersection(rl, limit);
2147 var_type = get_member_type_from_key(arg, key);
2148 new = cast_rl(var_type, new);
2150 /* We want to preserve the implications here */
2151 if (sm && basically_the_same(estate_rl(sm->state), new))
2152 __set_sm(sm); /* FIXME: Is this really necessary? */
2153 else {
2154 char *tmp_name;
2155 struct symbol *tmp_sym;
2157 tmp_name = map_long_to_short_name_sym(name, sym, &tmp_sym);
2158 if (tmp_name && tmp_sym) {
2159 free_string(name);
2160 name = tmp_name;
2161 sym = tmp_sym;
2164 if (op == PARAM_LIMIT)
2165 set_extra_nomod_vsl(name, sym, vsl, alloc_estate_rl(new));
2166 else
2167 set_extra_mod(name, sym, alloc_estate_rl(new));
2170 free:
2171 free_string(name);
2174 static void db_param_limit(struct expression *expr, int param, char *key, char *value)
2176 db_param_limit_filter(expr, param, key, value, PARAM_LIMIT);
2179 static void db_param_filter(struct expression *expr, int param, char *key, char *value)
2181 db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
2184 static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
2186 struct expression *arg;
2187 char *name, *tmp_name;
2188 struct symbol *sym, *tmp_sym;
2189 struct symbol *type;
2190 struct smatch_state *state;
2191 struct range_list *new = NULL;
2192 struct range_list *added = NULL;
2194 while (expr->type == EXPR_ASSIGNMENT)
2195 expr = strip_expr(expr->right);
2196 if (expr->type != EXPR_CALL)
2197 return;
2199 arg = get_argument_from_call_expr(expr->args, param);
2200 if (!arg)
2201 return;
2202 type = get_member_type_from_key(arg, key);
2203 name = get_variable_from_key(arg, key, &sym);
2204 if (!name || !sym)
2205 goto free;
2207 state = get_state(SMATCH_EXTRA, name, sym);
2208 if (state)
2209 new = estate_rl(state);
2211 call_results_to_rl(expr, type, value, &added);
2213 if (op == PARAM_SET)
2214 new = added;
2215 else
2216 new = rl_union(new, added);
2218 tmp_name = map_long_to_short_name_sym_nostack(name, sym, &tmp_sym);
2219 if (tmp_name && tmp_sym) {
2220 free_string(name);
2221 name = tmp_name;
2222 sym = tmp_sym;
2224 set_extra_mod(name, sym, alloc_estate_rl(new));
2225 free:
2226 free_string(name);
2229 static void db_param_add(struct expression *expr, int param, char *key, char *value)
2231 in_param_set = true;
2232 db_param_add_set(expr, param, key, value, PARAM_ADD);
2233 in_param_set = false;
2236 static void db_param_set(struct expression *expr, int param, char *key, char *value)
2238 in_param_set = true;
2239 db_param_add_set(expr, param, key, value, PARAM_SET);
2240 in_param_set = false;
2243 static void db_param_value(struct expression *expr, int param, char *key, char *value)
2245 struct expression *call;
2246 char *name;
2247 struct symbol *sym;
2248 struct symbol *type;
2249 struct range_list *rl = NULL;
2251 if (param != -1)
2252 return;
2254 call = expr;
2255 while (call->type == EXPR_ASSIGNMENT)
2256 call = strip_expr(call->right);
2257 if (call->type != EXPR_CALL)
2258 return;
2260 type = get_member_type_from_key(expr->left, key);
2261 name = get_variable_from_key(expr->left, key, &sym);
2262 if (!name || !sym)
2263 goto free;
2265 call_results_to_rl(call, type, value, &rl);
2267 set_extra_mod(name, sym, alloc_estate_rl(rl));
2268 free:
2269 free_string(name);
2272 static void match_call_info(struct expression *expr)
2274 struct smatch_state *state;
2275 struct range_list *rl = NULL;
2276 struct expression *arg;
2277 struct symbol *type;
2278 int i = 0;
2280 FOR_EACH_PTR(expr->args, arg) {
2281 type = get_arg_type(expr->fn, i);
2283 if (get_implied_rl(arg, &rl))
2284 rl = cast_rl(type, rl);
2285 else
2286 rl = cast_rl(type, alloc_whole_rl(get_type(arg)));
2288 if (!is_whole_rl(rl)) {
2289 rl = intersect_with_real_abs_expr(arg, rl);
2290 sql_insert_caller_info(expr, PARAM_VALUE, i, "$", show_rl(rl));
2292 state = get_state_expr(SMATCH_EXTRA, arg);
2293 if (estate_has_fuzzy_max(state)) {
2294 sql_insert_caller_info(expr, FUZZY_MAX, i, "$",
2295 sval_to_str(estate_get_fuzzy_max(state)));
2297 i++;
2298 } END_FOR_EACH_PTR(arg);
2301 static void set_param_value(const char *name, struct symbol *sym, char *key, char *value)
2303 struct range_list *rl = NULL;
2304 struct smatch_state *state;
2305 struct symbol *type;
2306 char fullname[256];
2307 sval_t dummy;
2309 if (strcmp(key, "*$") == 0)
2310 snprintf(fullname, sizeof(fullname), "*%s", name);
2311 else if (strncmp(key, "$", 1) == 0)
2312 snprintf(fullname, 256, "%s%s", name, key + 1);
2313 else
2314 return;
2316 type = get_member_type_from_key(symbol_expression(sym), key);
2317 str_to_rl(type, value, &rl);
2318 state = alloc_estate_rl(rl);
2319 if (estate_get_single_value(state, &dummy))
2320 estate_set_hard_max(state);
2321 set_state(SMATCH_EXTRA, fullname, sym, state);
2324 static void set_param_hard_max(const char *name, struct symbol *sym, char *key, char *value)
2326 struct range_list *rl = NULL;
2327 struct smatch_state *state;
2328 struct symbol *type;
2329 char fullname[256];
2330 sval_t max;
2332 if (strcmp(key, "*$") == 0)
2333 snprintf(fullname, sizeof(fullname), "*%s", name);
2334 else if (strncmp(key, "$", 1) == 0)
2335 snprintf(fullname, 256, "%s%s", name, key + 1);
2336 else
2337 return;
2339 state = get_state(SMATCH_EXTRA, fullname, sym);
2340 if (!state)
2341 return;
2342 type = get_member_type_from_key(symbol_expression(sym), key);
2343 str_to_rl(type, value, &rl);
2344 if (!rl_to_sval(rl, &max))
2345 return;
2346 estate_set_fuzzy_max(state, max);
2349 struct smatch_state *get_extra_state(struct expression *expr)
2351 char *name;
2352 struct symbol *sym;
2353 struct smatch_state *ret = NULL;
2354 struct range_list *rl;
2356 if (is_pointer(expr) && get_address_rl(expr, &rl))
2357 return alloc_estate_rl(rl);
2359 name = expr_to_known_chunk_sym(expr, &sym);
2360 if (!name)
2361 goto free;
2363 ret = get_state(SMATCH_EXTRA, name, sym);
2364 free:
2365 free_string(name);
2366 return ret;
2369 void register_smatch_extra(int id)
2371 my_id = id;
2373 add_merge_hook(my_id, &merge_estates);
2374 add_unmatched_state_hook(my_id, &unmatched_state);
2375 select_caller_info_hook(set_param_value, PARAM_VALUE);
2376 select_caller_info_hook(set_param_hard_max, FUZZY_MAX);
2377 select_return_states_before(&db_limited_before);
2378 select_return_states_hook(PARAM_LIMIT, &db_param_limit);
2379 select_return_states_hook(PARAM_FILTER, &db_param_filter);
2380 select_return_states_hook(PARAM_ADD, &db_param_add);
2381 select_return_states_hook(PARAM_SET, &db_param_set);
2382 select_return_states_hook(PARAM_VALUE, &db_param_value);
2383 select_return_states_after(&db_limited_after);
2386 static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
2388 struct var_sym_list *links;
2389 struct var_sym *tmp;
2390 struct smatch_state *state;
2392 links = sm->state->data;
2394 FOR_EACH_PTR(links, tmp) {
2395 if (sm->sym == tmp->sym &&
2396 strcmp(sm->name, tmp->var) == 0)
2397 continue;
2398 state = get_state(SMATCH_EXTRA, tmp->var, tmp->sym);
2399 if (!state)
2400 continue;
2401 set_state(SMATCH_EXTRA, tmp->var, tmp->sym, alloc_estate_whole(estate_type(state)));
2402 } END_FOR_EACH_PTR(tmp);
2403 set_state(link_id, sm->name, sm->sym, &undefined);
2406 void register_smatch_extra_links(int id)
2408 link_id = id;
2411 void register_smatch_extra_late(int id)
2413 add_merge_hook(link_id, &merge_link_states);
2414 add_modification_hook(link_id, &match_link_modify);
2415 add_hook(&match_dereferences, DEREF_HOOK);
2416 add_hook(&match_pointer_as_array, OP_HOOK);
2417 select_call_implies_hook(DEREFERENCE, &set_param_dereferenced);
2418 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
2419 add_hook(&match_assign, ASSIGNMENT_HOOK);
2420 add_hook(&match_assign, GLOBAL_ASSIGNMENT_HOOK);
2421 add_hook(&unop_expr, OP_HOOK);
2422 add_hook(&asm_expr, ASM_HOOK);
2423 add_untracked_param_hook(&match_untracked_array);
2425 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2426 add_member_info_callback(my_id, struct_member_callback);
2427 add_split_return_callback(&returned_struct_members);
2429 add_hook(&assume_indexes_are_valid, OP_HOOK);