check_memory: only load kernel.frees_argument when checking the kernel
[smatch.git] / smatch_extra.c
blob425838a2163025f026a7de47eec88d10957053bc
1 /*
2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * smatch_extra.c is supposed to track the value of every variable.
14 #include <stdlib.h>
15 #ifndef __USE_ISOC99
16 #define __USE_ISOC99
17 #endif
18 #include <limits.h>
19 #include "parse.h"
20 #include "smatch.h"
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
24 static int my_id;
26 static struct symbol *cur_func;
28 struct data_range whole_range = {
29 .min = LLONG_MIN,
30 .max = LLONG_MAX,
33 static struct smatch_state *alloc_extra_state_empty(void)
35 struct smatch_state *state;
36 struct data_info *dinfo;
38 dinfo = __alloc_data_info(0);
39 dinfo->type = DATA_RANGE;
40 dinfo->value_ranges = NULL;
41 state = __alloc_smatch_state(0);
42 state->data = dinfo;
43 return state;
46 static struct smatch_state *alloc_extra_state_no_name(int val)
48 struct smatch_state *state;
50 state = __alloc_smatch_state(0);
51 state->data = (void *)alloc_dinfo_range(val, val);
52 return state;
55 /* We do this because ->value_ranges is a list */
56 struct smatch_state *extra_undefined(void)
58 struct data_info *dinfo;
59 static struct smatch_state *ret;
60 static struct symbol *prev_func;
62 if (prev_func == cur_func)
63 return ret;
64 prev_func = cur_func;
66 dinfo = alloc_dinfo_range(whole_range.min, whole_range.max);
67 ret = __alloc_smatch_state(0);
68 ret->name = "unknown";
69 ret->data = dinfo;
70 return ret;
73 struct smatch_state *alloc_extra_state(int val)
75 struct smatch_state *state;
77 state = alloc_extra_state_no_name(val);
78 state->name = show_ranges(get_dinfo(state)->value_ranges);
79 return state;
82 struct smatch_state *alloc_extra_state_range(long long min, long long max)
84 struct smatch_state *state;
86 if (min == whole_range.min && max == whole_range.max)
87 return extra_undefined();
88 state = __alloc_smatch_state(0);
89 state->data = (void *)alloc_dinfo_range(min, max);
90 state->name = show_ranges(get_dinfo(state)->value_ranges);
91 return state;
94 struct smatch_state *alloc_extra_state_range_list(struct range_list *rl)
96 struct smatch_state *state;
98 state = __alloc_smatch_state(0);
99 state->data = (void *)alloc_dinfo_range_list(rl);
100 state->name = show_ranges(get_dinfo(state)->value_ranges);
101 return state;
104 struct data_info *get_dinfo(struct smatch_state *state)
106 if (!state)
107 return NULL;
108 return (struct data_info *)state->data;
112 struct smatch_state *filter_range(struct smatch_state *orig,
113 long long filter_min, long long filter_max)
115 struct smatch_state *ret;
116 struct data_info *orig_info;
117 struct data_info *ret_info;
119 if (!orig)
120 orig = extra_undefined();
121 orig_info = get_dinfo(orig);
122 ret = alloc_extra_state_empty();
123 ret_info = get_dinfo(ret);
124 ret_info->value_ranges = remove_range(orig_info->value_ranges, filter_min, filter_max);
125 ret->name = show_ranges(ret_info->value_ranges);
126 return ret;
129 struct smatch_state *add_filter(struct smatch_state *orig, long long num)
131 return filter_range(orig, num, num);
134 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
135 struct smatch_state *s1,
136 struct smatch_state *s2)
138 struct data_info *info1 = get_dinfo(s1);
139 struct data_info *info2 = get_dinfo(s2);
140 struct data_info *ret_info;
141 struct smatch_state *tmp;
142 struct range_list *value_ranges;
144 value_ranges = range_list_union(info1->value_ranges, info2->value_ranges);
145 tmp = alloc_extra_state_empty();
146 ret_info = get_dinfo(tmp);
147 ret_info->value_ranges = value_ranges;
148 tmp->name = show_ranges(ret_info->value_ranges);
149 return tmp;
152 struct sm_state *__extra_pre_loop_hook_before(struct statement *iterator_pre_statement)
154 struct expression *expr;
155 char *name;
156 struct symbol *sym;
157 struct sm_state *ret = NULL;
159 if (!iterator_pre_statement)
160 return NULL;
161 if (iterator_pre_statement->type != STMT_EXPRESSION)
162 return NULL;
163 expr = iterator_pre_statement->expression;
164 if (expr->type != EXPR_ASSIGNMENT)
165 return NULL;
166 name = get_variable_from_expr(expr->left, &sym);
167 if (!name || !sym)
168 goto free;
169 ret = get_sm_state(my_id, name, sym);
170 free:
171 free_string(name);
172 return ret;
175 int __iterator_unchanged(struct sm_state *sm, struct statement *iterator)
177 struct expression *iter_expr;
178 char *name;
179 struct symbol *sym;
180 int ret = 0;
182 if (!iterator)
183 return 0;
184 if (iterator->type != STMT_EXPRESSION)
185 return 0;
186 iter_expr = iterator->expression;
187 if (iter_expr->op != SPECIAL_INCREMENT && iter_expr->op != SPECIAL_DECREMENT)
188 return 0;
189 name = get_variable_from_expr(iter_expr->unop, &sym);
190 if (!name || !sym)
191 goto free;
192 if (get_sm_state(my_id, name, sym) == sm)
193 ret = 1;
194 free:
195 free_string(name);
196 return ret;
199 void __extra_pre_loop_hook_after(struct sm_state *sm,
200 struct statement *iterator,
201 struct expression *condition)
203 struct expression *iter_expr;
204 char *name;
205 struct symbol *sym;
206 long long value;
207 int left = 0;
208 struct smatch_state *state;
209 struct data_info *dinfo;
210 long long min, max;
212 iter_expr = iterator->expression;
214 if (condition->type != EXPR_COMPARE)
215 return;
216 if (!get_value(condition->left, &value)) {
217 if (!get_value(condition->right, &value))
218 return;
219 left = 1;
221 if (left)
222 name = get_variable_from_expr(condition->left, &sym);
223 else
224 name = get_variable_from_expr(condition->right, &sym);
225 if (!name || !sym)
226 goto free;
227 if (sym != sm->sym || strcmp(name, sm->name))
228 goto free;
229 state = get_state(my_id, name, sym);
230 dinfo = get_dinfo(state);
231 min = get_dinfo_min(dinfo);
232 max = get_dinfo_max(dinfo);
233 if (iter_expr->op == SPECIAL_INCREMENT && min != whole_range.min && max == whole_range.max) {
234 set_state(my_id, name, sym, alloc_extra_state(min));
235 } else if (min == whole_range.min && max != whole_range.max) {
236 set_state(my_id, name, sym, alloc_extra_state(max));
238 free:
239 free_string(name);
240 return;
243 static struct smatch_state *unmatched_state(struct sm_state *sm)
245 return extra_undefined();
248 static void match_function_call(struct expression *expr)
250 struct expression *tmp;
251 struct symbol *sym;
252 char *name;
253 int i = 0;
255 FOR_EACH_PTR(expr->args, tmp) {
256 if (tmp->type == EXPR_PREOP && tmp->op == '&') {
257 name = get_variable_from_expr(tmp->unop, &sym);
258 if (name) {
259 set_state(my_id, name, sym, extra_undefined());
261 free_string(name);
263 i++;
264 } END_FOR_EACH_PTR(tmp);
267 static void match_assign(struct expression *expr)
269 struct expression *left;
270 struct expression *right;
271 struct symbol *sym;
272 char *name;
273 long long value;
274 int known;
275 long long min = whole_range.min;
276 long long max = whole_range.max;
277 long long tmp;
278 struct range_list *rl = NULL;
280 left = strip_expr(expr->left);
281 name = get_variable_from_expr(left, &sym);
282 if (!name)
283 return;
284 right = strip_expr(expr->right);
285 while (right->type == EXPR_ASSIGNMENT && right->op == '=')
286 right = strip_expr(right->left);
288 known = get_implied_range_list(right, &rl);
289 if (expr->op == '=') {
290 if (known)
291 set_state(my_id, name, sym, alloc_extra_state_range_list(rl));
292 else
293 set_state(my_id, name, sym, extra_undefined());
294 goto free;
297 known = get_implied_value(right, &value);
298 if (expr->op == SPECIAL_ADD_ASSIGN) {
299 if (get_implied_min(left, &tmp)) {
300 if (known)
301 min = tmp + value;
302 else
303 min = tmp;
307 if (expr->op == SPECIAL_SUB_ASSIGN) {
308 if (get_implied_max(left, &tmp)) {
309 if (known)
310 max = tmp - value;
311 else
312 max = tmp;
316 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
317 free:
318 free_string(name);
321 static void unop_expr(struct expression *expr)
323 struct symbol *sym;
324 char *name;
325 long long min = whole_range.min;
326 long long max = whole_range.max;
327 long long val;
329 if (expr->op == '*')
330 return;
331 if (expr->op == '(')
332 return;
334 name = get_variable_from_expr(expr->unop, &sym);
335 if (!name)
336 goto free;
337 if (expr->op == SPECIAL_INCREMENT) {
338 if (get_implied_min(expr->unop, &val))
339 min = val + 1;
341 if (expr->op == SPECIAL_DECREMENT) {
342 if (get_implied_max(expr->unop, &val))
343 max = val - 1;
345 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
346 free:
347 free_string(name);
350 static void match_declarations(struct symbol *sym)
352 const char *name;
353 long long val;
355 if (sym->ident) {
356 name = sym->ident->name;
357 if (sym->initializer) {
358 if (get_value(sym->initializer, &val))
359 set_state(my_id, name, sym, alloc_extra_state(val));
360 else
361 set_state(my_id, name, sym, extra_undefined());
362 scoped_state(my_id, name, sym);
363 } else {
364 set_state(my_id, name, sym, extra_undefined());
365 scoped_state(my_id, name, sym);
370 static void match_function_def(struct symbol *sym)
372 struct symbol *arg;
374 cur_func = sym;
375 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
376 if (!arg->ident) {
377 continue;
379 set_state(my_id, arg->ident->name, arg, extra_undefined());
380 } END_FOR_EACH_PTR(arg);
383 #define VAL_SINGLE 0
384 #define VAL_MAX 1
385 #define VAL_MIN 2
387 static int get_implied_value_helper(struct expression *expr, long long *val, int what)
389 struct smatch_state *state;
390 struct symbol *sym;
391 char *name;
393 if (get_value(expr, val))
394 return 1;
396 name = get_variable_from_expr(expr, &sym);
397 if (!name)
398 return 0;
399 state = get_state(my_id, name, sym);
400 free_string(name);
401 if (!state || !state->data)
402 return 0;
403 if (what == VAL_SINGLE)
404 return get_single_value_from_range(get_dinfo(state), val);
405 if (what == VAL_MAX) {
406 *val = get_dinfo_max(get_dinfo(state));
407 if (*val == whole_range.max) /* this means just guessing */
408 return 0;
409 return 1;
411 *val = get_dinfo_min(get_dinfo(state));
412 if (*val == whole_range.min)
413 return 0;
414 return 1;
417 int get_implied_single_val(struct expression *expr, long long *val)
419 return get_implied_value_helper(expr, val, VAL_SINGLE);
422 int get_implied_max(struct expression *expr, long long *val)
424 return get_implied_value_helper(expr, val, VAL_MAX);
427 int get_implied_min(struct expression *expr, long long *val)
429 return get_implied_value_helper(expr, val, VAL_MIN);
432 int get_implied_single_fuzzy_max(struct expression *expr, long long *max)
434 struct sm_state *sm;
435 struct sm_state *tmp;
437 if (get_implied_max(expr, max))
438 return 1;
440 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
441 if (!sm)
442 return 0;
444 *max = whole_range.min;
445 FOR_EACH_PTR(sm->possible, tmp) {
446 long long new_min;
448 new_min = get_dinfo_min(get_dinfo(tmp->state));
449 if (new_min > *max)
450 *max = new_min;
451 } END_FOR_EACH_PTR(tmp);
453 if (*max > whole_range.min)
454 return 1;
455 return 0;
458 static int last_stmt_val(struct statement *stmt, long long *val)
460 struct expression *expr;
462 if (!stmt)
463 return 0;
465 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
466 if (stmt->type != STMT_EXPRESSION)
467 return 0;
468 expr = stmt->expression;
469 return get_value(expr, val);
472 static void match_comparison(struct expression *expr)
474 long long fixed;
475 char *name = NULL;
476 struct symbol *sym;
477 struct smatch_state *one_state;
478 struct smatch_state *two_state;
479 struct smatch_state *orig;
480 int left = 0;
481 int comparison = expr->op;
482 struct expression *varies = expr->right;
484 if (!get_value(expr->left, &fixed)) {
485 if (!get_value(expr->right, &fixed))
486 return;
487 varies = expr->left;
488 left = 1;
490 if (varies->op == SPECIAL_INCREMENT || varies->op == SPECIAL_DECREMENT)
491 varies = varies->unop;
492 if (varies->type == EXPR_CALL) {
493 function_comparison(comparison, varies, fixed, left);
494 return;
497 name = get_variable_from_expr(varies, &sym);
498 if (!name || !sym)
499 goto free;
501 orig = get_state(my_id, name, sym);
502 if (!orig)
503 orig = extra_undefined();
505 switch (comparison) {
506 case '<':
507 case SPECIAL_UNSIGNED_LT:
508 one_state = filter_range(orig, whole_range.min, fixed - 1);
509 two_state = filter_range(orig, fixed, whole_range.max);
510 if (left)
511 set_true_false_states(my_id, name, sym, two_state, one_state);
512 else
513 set_true_false_states(my_id, name, sym, one_state, two_state);
514 return;
515 case SPECIAL_UNSIGNED_LTE:
516 case SPECIAL_LTE:
517 one_state = filter_range(orig, whole_range.min, fixed);
518 two_state = filter_range(orig, fixed + 1, whole_range.max);
519 if (left)
520 set_true_false_states(my_id, name, sym, two_state, one_state);
521 else
522 set_true_false_states(my_id, name, sym, one_state, two_state);
523 return;
524 case SPECIAL_EQUAL:
525 // todo. print a warning here for impossible conditions.
526 one_state = alloc_extra_state(fixed);
527 two_state = filter_range(orig, fixed, fixed);
528 set_true_false_states(my_id, name, sym, one_state, two_state);
529 return;
530 case SPECIAL_UNSIGNED_GTE:
531 case SPECIAL_GTE:
532 one_state = filter_range(orig, whole_range.min, fixed - 1);
533 two_state = filter_range(orig, fixed, whole_range.max);
534 if (left)
535 set_true_false_states(my_id, name, sym, one_state, two_state);
536 else
537 set_true_false_states(my_id, name, sym, two_state, one_state);
538 return;
539 case '>':
540 case SPECIAL_UNSIGNED_GT:
541 one_state = filter_range(orig, whole_range.min, fixed);
542 two_state = filter_range(orig, fixed + 1, whole_range.max);
543 if (left)
544 set_true_false_states(my_id, name, sym, one_state, two_state);
545 else
546 set_true_false_states(my_id, name, sym, two_state, one_state);
547 return;
548 case SPECIAL_NOTEQUAL:
549 one_state = alloc_extra_state(fixed);
550 two_state = filter_range(orig, fixed, fixed);
551 set_true_false_states(my_id, name, sym, two_state, one_state);
552 return;
553 default:
554 sm_msg("unhandled comparison %d\n", comparison);
555 return;
557 return;
558 free:
559 free_string(name);
562 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
563 void __extra_match_condition(struct expression *expr)
565 struct symbol *sym;
566 char *name;
567 struct smatch_state *pre_state;
568 struct smatch_state *true_state;
569 struct smatch_state *false_state;
571 expr = strip_expr(expr);
572 switch (expr->type) {
573 case EXPR_CALL:
574 function_comparison(SPECIAL_NOTEQUAL, expr, 0, 1);
575 return;
576 case EXPR_PREOP:
577 case EXPR_SYMBOL:
578 case EXPR_DEREF:
579 name = get_variable_from_expr(expr, &sym);
580 if (!name)
581 return;
582 pre_state = get_state(my_id, name, sym);
583 true_state = add_filter(pre_state, 0);
584 false_state = alloc_extra_state(0);
585 set_true_false_states(my_id, name, sym, true_state, false_state);
586 free_string(name);
587 return;
588 case EXPR_COMPARE:
589 match_comparison(expr);
590 return;
591 case EXPR_ASSIGNMENT:
592 __extra_match_condition(expr->left);
593 return;
597 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
598 int implied_not_equal(struct expression *expr, long long val)
600 char *name;
601 struct symbol *sym;
602 struct smatch_state *state;
603 int ret = 0;
605 name = get_variable_from_expr(expr, &sym);
606 if (!name || !sym)
607 goto exit;
608 state = get_state(my_id, name, sym);
609 if (!state || !state->data)
610 goto exit;
611 ret = !possibly_false(SPECIAL_NOTEQUAL, get_dinfo(state), val, 1);
612 exit:
613 free_string(name);
614 return ret;
617 int known_condition_true(struct expression *expr)
619 long long tmp;
621 if (!expr)
622 return 0;
624 if (get_value(expr, &tmp) && tmp)
625 return 1;
627 expr = strip_expr(expr);
628 switch (expr->type) {
629 case EXPR_PREOP:
630 if (expr->op == '!') {
631 if (known_condition_false(expr->unop))
632 return 1;
633 break;
635 break;
636 default:
637 break;
639 return 0;
642 int known_condition_false(struct expression *expr)
644 if (!expr)
645 return 0;
647 if (is_zero(expr))
648 return 1;
650 switch (expr->type) {
651 case EXPR_PREOP:
652 if (expr->op == '!') {
653 if (known_condition_true(expr->unop))
654 return 1;
655 break;
657 break;
658 default:
659 break;
661 return 0;
664 static int do_comparison_range(struct expression *expr)
666 struct symbol *sym;
667 char *name;
668 struct smatch_state *state;
669 long long value;
670 int left = 0;
671 int poss_true, poss_false;
673 if (!get_value(expr->left, &value)) {
674 if (!get_value(expr->right, &value))
675 return 3;
676 left = 1;
678 if (left)
679 name = get_variable_from_expr(expr->left, &sym);
680 else
681 name = get_variable_from_expr(expr->right, &sym);
682 if (!name || !sym)
683 goto free;
684 state = get_state(SMATCH_EXTRA, name, sym);
685 if (!state)
686 goto free;
687 poss_true = possibly_true(expr->op, get_dinfo(state), value, left);
688 poss_false = possibly_false(expr->op, get_dinfo(state), value, left);
689 if (!poss_true && !poss_false)
690 return 0;
691 if (poss_true && !poss_false)
692 return 1;
693 if (!poss_true && poss_false)
694 return 2;
695 if (poss_true && poss_false)
696 return 3;
697 free:
698 free_string(name);
699 return 3;
702 int implied_condition_true(struct expression *expr)
704 struct statement *stmt;
705 long long tmp;
706 long long val;
708 if (!expr)
709 return 0;
711 if (get_value(expr, &tmp) && tmp)
712 return 1;
714 expr = strip_expr(expr);
715 switch (expr->type) {
716 case EXPR_COMPARE:
717 if (do_comparison_range(expr) == 1)
718 return 1;
719 break;
720 case EXPR_PREOP:
721 if (expr->op == '!') {
722 if (implied_condition_false(expr->unop))
723 return 1;
724 break;
726 stmt = get_block_thing(expr);
727 if (last_stmt_val(stmt, &val) && val == 1)
728 return 1;
729 break;
730 default:
731 if (implied_not_equal(expr, 0) == 1)
732 return 1;
733 break;
735 return 0;
738 int implied_condition_false(struct expression *expr)
740 struct statement *stmt;
741 struct expression *tmp;
742 long long val;
744 if (!expr)
745 return 0;
747 if (is_zero(expr))
748 return 1;
750 switch (expr->type) {
751 case EXPR_COMPARE:
752 if (do_comparison_range(expr) == 2)
753 return 1;
754 case EXPR_PREOP:
755 if (expr->op == '!') {
756 if (implied_condition_true(expr->unop))
757 return 1;
758 break;
760 stmt = get_block_thing(expr);
761 if (last_stmt_val(stmt, &val) && val == 0)
762 return 1;
763 tmp = strip_expr(expr);
764 if (tmp != expr)
765 return implied_condition_false(tmp);
766 break;
767 default:
768 if (get_implied_value(expr, &val) && val == 0)
769 return 1;
770 break;
772 return 0;
775 int get_implied_range_list(struct expression *expr, struct range_list **rl)
777 long long val;
778 struct smatch_state *state;
780 expr = strip_expr(expr);
782 state = get_state_expr(my_id, expr);
783 if (state) {
784 *rl = clone_range_list(get_dinfo(state)->value_ranges);
785 return 1;
788 if (get_implied_value(expr, &val)) {
789 *rl = NULL;
790 add_range(rl, val, val);
791 return 1;
794 if (expr->type == EXPR_BINOP && expr->op == '%') {
795 if (!get_implied_value(expr->right, &val))
796 return 0;
797 *rl = NULL;
798 add_range(rl, 0, val - 1);
799 return 1;
802 return 0;
805 void register_smatch_extra(int id)
807 my_id = id;
808 add_merge_hook(my_id, &merge_func);
809 add_unmatched_state_hook(my_id, &unmatched_state);
810 add_hook(&unop_expr, OP_HOOK);
811 add_hook(&match_function_def, FUNC_DEF_HOOK);
812 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
813 add_hook(&match_assign, ASSIGNMENT_HOOK);
814 add_hook(&match_declarations, DECLARATION_HOOK);
816 if (option_project == PROJ_KERNEL) {
817 /* I don't know how to test for the ATTRIB_NORET attribute. :( */
818 add_function_hook("panic", &__match_nullify_path_hook, NULL);
819 add_function_hook("do_exit", &__match_nullify_path_hook, NULL);
820 add_function_hook("complete_and_exit", &__match_nullify_path_hook, NULL);
821 add_function_hook("__module_put_and_exit", &__match_nullify_path_hook, NULL);
822 add_function_hook("do_group_exit", &__match_nullify_path_hook, NULL);