smatch_extra: I don't like empty ranges
[smatch.git] / smatch_extra.c
blob7e67afee9f12d54203fdc551b87f6b705d5a66d7
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 #define __USE_ISOC99
16 #include <limits.h>
17 #include "parse.h"
18 #include "smatch.h"
19 #include "smatch_slist.h"
20 #include "smatch_extra.h"
22 static int my_id;
24 static struct symbol *cur_func;
26 struct data_range whole_range = {
27 .min = LLONG_MIN,
28 .max = LLONG_MAX,
31 static struct smatch_state *alloc_extra_state_empty()
33 struct smatch_state *state;
34 struct data_info *dinfo;
36 dinfo = __alloc_data_info(0);
37 dinfo->type = DATA_RANGE;
38 dinfo->value_ranges = NULL;
39 state = __alloc_smatch_state(0);
40 state->data = dinfo;
41 return state;
44 static struct smatch_state *alloc_extra_state_no_name(int val)
46 struct smatch_state *state;
48 state = __alloc_smatch_state(0);
49 state->data = (void *)alloc_dinfo_range(val, val);
50 return state;
53 /* We do this because ->value_ranges is a list */
54 struct smatch_state *extra_undefined()
56 struct data_info *dinfo;
57 static struct smatch_state *ret;
58 static struct symbol *prev_func;
60 if (prev_func == cur_func)
61 return ret;
62 prev_func = cur_func;
64 dinfo = alloc_dinfo_range(whole_range.min, whole_range.max);
65 ret = __alloc_smatch_state(0);
66 ret->name = "unknown";
67 ret->data = dinfo;
68 return ret;
71 struct smatch_state *alloc_extra_state(int val)
73 struct smatch_state *state;
75 state = alloc_extra_state_no_name(val);
76 state->name = show_ranges(((struct data_info *)state->data)->value_ranges);
77 return state;
80 struct smatch_state *alloc_extra_state_range(long long min, long long max)
82 struct smatch_state *state;
84 if (min == whole_range.min && max == whole_range.max)
85 return extra_undefined();
86 state = __alloc_smatch_state(0);
87 state->data = (void *)alloc_dinfo_range(min, max);
88 state->name = show_ranges(((struct data_info *)state->data)->value_ranges);
89 return state;
92 struct smatch_state *alloc_extra_state_range_list(struct range_list *rl)
94 struct smatch_state *state;
96 state = __alloc_smatch_state(0);
97 state->data = (void *)alloc_dinfo_range_list(rl);
98 state->name = show_ranges(((struct data_info *)state->data)->value_ranges);
99 return state;
102 struct smatch_state *filter_range(struct smatch_state *orig,
103 long long filter_min, long long filter_max)
105 struct smatch_state *ret;
106 struct data_info *orig_info;
107 struct data_info *ret_info;
109 if (!orig)
110 orig = extra_undefined();
111 orig_info = (struct data_info *)orig->data;
112 ret = alloc_extra_state_empty();
113 ret_info = (struct data_info *)ret->data;
114 ret_info->value_ranges = remove_range(orig_info->value_ranges, filter_min, filter_max);
115 ret->name = show_ranges(ret_info->value_ranges);
116 return ret;
119 struct smatch_state *add_filter(struct smatch_state *orig, long long num)
121 return filter_range(orig, num, num);
124 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
125 struct smatch_state *s1,
126 struct smatch_state *s2)
128 struct data_info *info1 = (struct data_info *)s1->data;
129 struct data_info *info2 = (struct data_info *)s2->data;
130 struct data_info *ret_info;
131 struct smatch_state *tmp;
132 struct range_list *value_ranges;
134 value_ranges = range_list_union(info1->value_ranges, info2->value_ranges);
135 tmp = alloc_extra_state_empty();
136 ret_info = (struct data_info *)tmp->data;
137 ret_info->value_ranges = value_ranges;
138 tmp->name = show_ranges(ret_info->value_ranges);
139 return tmp;
142 struct sm_state *__extra_pre_loop_hook_before(struct statement *iterator_pre_statement)
144 struct expression *expr;
145 char *name;
146 struct symbol *sym;
147 struct sm_state *ret = NULL;
149 if (!iterator_pre_statement)
150 return NULL;
151 if (iterator_pre_statement->type != STMT_EXPRESSION)
152 return NULL;
153 expr = iterator_pre_statement->expression;
154 if (expr->type != EXPR_ASSIGNMENT)
155 return NULL;
156 name = get_variable_from_expr(expr->left, &sym);
157 if (!name || !sym)
158 goto free;
159 ret = get_sm_state(my_id, name, sym);
160 free:
161 free_string(name);
162 return ret;
165 int __iterator_unchanged(struct sm_state *sm, struct statement *iterator)
167 struct expression *iter_expr;
168 char *name;
169 struct symbol *sym;
170 int ret = 0;
172 if (!iterator)
173 return 0;
174 if (iterator->type != STMT_EXPRESSION)
175 return 0;
176 iter_expr = iterator->expression;
177 if (iter_expr->op != SPECIAL_INCREMENT && iter_expr->op != SPECIAL_DECREMENT)
178 return 0;
179 name = get_variable_from_expr(iter_expr->unop, &sym);
180 if (!name || !sym)
181 goto free;
182 if (get_sm_state(my_id, name, sym) == sm)
183 ret = 1;
184 free:
185 free_string(name);
186 return ret;
189 void __extra_pre_loop_hook_after(struct sm_state *sm,
190 struct statement *iterator,
191 struct expression *condition)
193 struct expression *iter_expr;
194 char *name;
195 struct symbol *sym;
196 long long value;
197 int left = 0;
198 struct smatch_state *state;
199 struct data_info *dinfo;
200 long long min, max;
202 iter_expr = iterator->expression;
204 if (condition->type != EXPR_COMPARE)
205 return;
206 if (!get_value(condition->left, &value)) {
207 if (!get_value(condition->right, &value))
208 return;
209 left = 1;
211 if (left)
212 name = get_variable_from_expr(condition->left, &sym);
213 else
214 name = get_variable_from_expr(condition->right, &sym);
215 if (!name || !sym)
216 goto free;
217 if (sym != sm->sym || strcmp(name, sm->name))
218 goto free;
219 state = get_state(my_id, name, sym);
220 dinfo = (struct data_info *)state->data;
221 min = get_dinfo_min(dinfo);
222 max = get_dinfo_max(dinfo);
223 if (iter_expr->op == SPECIAL_INCREMENT && min != whole_range.min && max == whole_range.max) {
224 set_state(my_id, name, sym, alloc_extra_state(min));
225 } else if (min == whole_range.min && max != whole_range.max) {
226 set_state(my_id, name, sym, alloc_extra_state(max));
228 free:
229 free_string(name);
230 return;
233 static struct smatch_state *unmatched_state(struct sm_state *sm)
235 return extra_undefined();
238 static void match_function_call(struct expression *expr)
240 struct expression *tmp;
241 struct symbol *sym;
242 char *name;
243 int i = 0;
245 FOR_EACH_PTR(expr->args, tmp) {
246 if (tmp->type == EXPR_PREOP && tmp->op == '&') {
247 name = get_variable_from_expr(tmp->unop, &sym);
248 if (name) {
249 set_state(my_id, name, sym, extra_undefined());
251 free_string(name);
253 i++;
254 } END_FOR_EACH_PTR(tmp);
257 static void match_assign(struct expression *expr)
259 struct expression *left;
260 struct expression *right;
261 struct symbol *sym;
262 char *name;
263 long long value;
264 int known;
265 long long min = whole_range.min;
266 long long max = whole_range.max;
267 long long tmp;
268 struct range_list *rl = NULL;
270 left = strip_expr(expr->left);
271 name = get_variable_from_expr(left, &sym);
272 if (!name)
273 return;
274 right = strip_expr(expr->right);
275 while (right->type == EXPR_ASSIGNMENT && right->op == '=')
276 right = strip_expr(right->left);
278 known = get_implied_range_list(right, &rl);
279 if (expr->op == '=') {
280 if (known)
281 set_state(my_id, name, sym, alloc_extra_state_range_list(rl));
282 else
283 set_state(my_id, name, sym, extra_undefined());
284 goto free;
287 known = get_implied_value(right, &value);
288 if (expr->op == SPECIAL_ADD_ASSIGN) {
289 if (get_implied_min(left, &tmp)) {
290 if (known)
291 min = tmp + value;
292 else
293 min = tmp;
297 if (expr->op == SPECIAL_SUB_ASSIGN) {
298 if (get_implied_max(left, &tmp)) {
299 if (known)
300 max = tmp - value;
301 else
302 max = tmp;
306 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
307 free:
308 free_string(name);
311 static void unop_expr(struct expression *expr)
313 struct symbol *sym;
314 char *name;
315 long long min = whole_range.min;
316 long long max = whole_range.max;
317 long long val;
319 if (expr->op == '*')
320 return;
321 if (expr->op == '(')
322 return;
324 name = get_variable_from_expr(expr->unop, &sym);
325 if (!name)
326 goto free;
327 if (expr->op == SPECIAL_INCREMENT) {
328 if (get_implied_min(expr->unop, &val))
329 min = val + 1;
331 if (expr->op == SPECIAL_DECREMENT) {
332 if (get_implied_max(expr->unop, &val))
333 max = val - 1;
335 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
336 free:
337 free_string(name);
340 static void match_declarations(struct symbol *sym)
342 const char *name;
343 long long val;
345 if (sym->ident) {
346 name = sym->ident->name;
347 if (sym->initializer) {
348 if (get_value(sym->initializer, &val))
349 set_state(my_id, name, sym, alloc_extra_state(val));
350 else
351 set_state(my_id, name, sym, extra_undefined());
352 scoped_state(my_id, name, sym);
353 } else {
354 set_state(my_id, name, sym, extra_undefined());
355 scoped_state(my_id, name, sym);
360 static void match_function_def(struct symbol *sym)
362 struct symbol *arg;
364 cur_func = sym;
365 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
366 if (!arg->ident) {
367 continue;
369 set_state(my_id, arg->ident->name, arg, extra_undefined());
370 } END_FOR_EACH_PTR(arg);
373 #define VAL_SINGLE 0
374 #define VAL_MAX 1
375 #define VAL_MIN 2
377 static int get_implied_value_helper(struct expression *expr, long long *val, int what)
379 struct smatch_state *state;
380 struct symbol *sym;
381 char *name;
383 if (get_value(expr, val))
384 return 1;
386 name = get_variable_from_expr(expr, &sym);
387 if (!name)
388 return 0;
389 state = get_state(my_id, name, sym);
390 free_string(name);
391 if (!state || !state->data)
392 return 0;
393 if (what == VAL_SINGLE)
394 return get_single_value_from_range((struct data_info *)state->data, val);
395 if (what == VAL_MAX) {
396 *val = get_dinfo_max((struct data_info *)state->data);
397 if (*val == whole_range.max) /* this means just guessing */
398 return 0;
399 return 1;
401 *val = get_dinfo_min((struct data_info *)state->data);
402 if (*val == whole_range.min)
403 return 0;
404 return 1;
407 int get_implied_single_val(struct expression *expr, long long *val)
409 return get_implied_value_helper(expr, val, VAL_SINGLE);
412 int get_implied_max(struct expression *expr, long long *val)
414 return get_implied_value_helper(expr, val, VAL_MAX);
417 int get_implied_min(struct expression *expr, long long *val)
419 return get_implied_value_helper(expr, val, VAL_MIN);
422 int get_implied_single_fuzzy_max(struct expression *expr, long long *max)
424 struct sm_state *sm;
425 struct sm_state *tmp;
427 if (get_implied_max(expr, max))
428 return 1;
430 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
431 if (!sm)
432 return 0;
434 *max = whole_range.min;
435 FOR_EACH_PTR(sm->possible, tmp) {
436 long long new_min;
438 if (tmp->state == &merged)
439 continue;
440 new_min = get_dinfo_min((struct data_info *)tmp->state->data);
441 if (new_min > *max)
442 *max = new_min;
443 } END_FOR_EACH_PTR(tmp);
445 if (*max > whole_range.min)
446 return 1;
447 return 0;
450 static int last_stmt_val(struct statement *stmt, long long *val)
452 struct expression *expr;
454 if (!stmt)
455 return 0;
457 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
458 if (stmt->type != STMT_EXPRESSION)
459 return 0;
460 expr = stmt->expression;
461 return get_value(expr, val);
464 static void match_comparison(struct expression *expr)
466 long long fixed;
467 char *name = NULL;
468 struct symbol *sym;
469 struct smatch_state *one_state;
470 struct smatch_state *two_state;
471 struct smatch_state *orig;
472 int left = 0;
473 int comparison = expr->op;
474 struct expression *varies = expr->right;
476 if (!get_value(expr->left, &fixed)) {
477 if (!get_value(expr->right, &fixed))
478 return;
479 varies = expr->left;
480 left = 1;
482 if (varies->op == SPECIAL_INCREMENT || varies->op == SPECIAL_DECREMENT)
483 varies = varies->unop;
484 if (varies->type == EXPR_CALL) {
485 function_comparison(comparison, varies, fixed, left);
486 return;
489 name = get_variable_from_expr(varies, &sym);
490 if (!name || !sym)
491 goto free;
493 orig = get_state(my_id, name, sym);
494 if (!orig)
495 orig = extra_undefined();
497 switch(comparison){
498 case '<':
499 case SPECIAL_UNSIGNED_LT:
500 one_state = filter_range(orig, whole_range.min, fixed - 1);
501 two_state = filter_range(orig, fixed, whole_range.max);
502 if (left)
503 set_true_false_states(my_id, name, sym, two_state, one_state);
504 else
505 set_true_false_states(my_id, name, sym, one_state, two_state);
506 return;
507 case SPECIAL_UNSIGNED_LTE:
508 case SPECIAL_LTE:
509 one_state = filter_range(orig, whole_range.min, fixed);
510 two_state = filter_range(orig, fixed + 1, whole_range.max);
511 if (left)
512 set_true_false_states(my_id, name, sym, two_state, one_state);
513 else
514 set_true_false_states(my_id, name, sym, one_state, two_state);
515 return;
516 case SPECIAL_EQUAL:
517 // todo. print a warning here for impossible conditions.
518 one_state = alloc_extra_state(fixed);
519 two_state = filter_range(orig, fixed, fixed);
520 set_true_false_states(my_id, name, sym, one_state, two_state);
521 return;
522 case SPECIAL_UNSIGNED_GTE:
523 case SPECIAL_GTE:
524 one_state = filter_range(orig, whole_range.min, fixed - 1);
525 two_state = filter_range(orig, fixed, whole_range.max);
526 if (left)
527 set_true_false_states(my_id, name, sym, one_state, two_state);
528 else
529 set_true_false_states(my_id, name, sym, two_state, one_state);
530 return;
531 case '>':
532 case SPECIAL_UNSIGNED_GT:
533 one_state = filter_range(orig, whole_range.min, fixed);
534 two_state = filter_range(orig, fixed + 1, whole_range.max);
535 if (left)
536 set_true_false_states(my_id, name, sym, one_state, two_state);
537 else
538 set_true_false_states(my_id, name, sym, two_state, one_state);
539 return;
540 case SPECIAL_NOTEQUAL:
541 one_state = alloc_extra_state(fixed);
542 two_state = filter_range(orig, fixed, fixed);
543 set_true_false_states(my_id, name, sym, two_state, one_state);
544 return;
545 default:
546 sm_msg("unhandled comparison %d\n", comparison);
547 return;
549 return;
550 free:
551 free_string(name);
554 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
555 void __extra_match_condition(struct expression *expr)
557 struct symbol *sym;
558 char *name;
559 struct smatch_state *pre_state;
560 struct smatch_state *true_state;
561 struct smatch_state *false_state;
563 expr = strip_expr(expr);
564 switch(expr->type) {
565 case EXPR_CALL:
566 function_comparison(SPECIAL_NOTEQUAL, expr, 0, 1);
567 return;
568 case EXPR_PREOP:
569 case EXPR_SYMBOL:
570 case EXPR_DEREF:
571 name = get_variable_from_expr(expr, &sym);
572 if (!name)
573 return;
574 pre_state = get_state(my_id, name, sym);
575 true_state = add_filter(pre_state, 0);
576 false_state = alloc_extra_state(0);
577 set_true_false_states(my_id, name, sym, true_state, false_state);
578 free_string(name);
579 return;
580 case EXPR_COMPARE:
581 match_comparison(expr);
582 return;
583 case EXPR_ASSIGNMENT:
584 __extra_match_condition(expr->left);
585 return;
589 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
590 int implied_not_equal(struct expression *expr, long long val)
592 char *name;
593 struct symbol *sym;
594 struct smatch_state *state;
595 int ret = 0;
597 name = get_variable_from_expr(expr, &sym);
598 if (!name || !sym)
599 goto exit;
600 state = get_state(my_id, name, sym);
601 if (!state || !state->data)
602 goto exit;
603 ret = !possibly_false(SPECIAL_NOTEQUAL, (struct data_info *)state->data, val, 1);
604 exit:
605 free_string(name);
606 return ret;
609 int known_condition_true(struct expression *expr)
611 long long tmp;
613 if (!expr)
614 return 0;
616 if (get_value(expr, &tmp) && tmp)
617 return 1;
619 expr = strip_expr(expr);
620 switch(expr->type) {
621 case EXPR_PREOP:
622 if (expr->op == '!') {
623 if (known_condition_false(expr->unop))
624 return 1;
625 break;
627 break;
628 default:
629 break;
631 return 0;
634 int known_condition_false(struct expression *expr)
636 if (!expr)
637 return 0;
639 if (is_zero(expr))
640 return 1;
642 switch(expr->type) {
643 case EXPR_PREOP:
644 if (expr->op == '!') {
645 if (known_condition_true(expr->unop))
646 return 1;
647 break;
649 break;
650 default:
651 break;
653 return 0;
656 static int do_comparison_range(struct expression *expr)
658 struct symbol *sym;
659 char *name;
660 struct smatch_state *state;
661 long long value;
662 int left = 0;
663 int poss_true, poss_false;
665 if (!get_value(expr->left, &value)) {
666 if (!get_value(expr->right, &value))
667 return 3;
668 left = 1;
670 if (left)
671 name = get_variable_from_expr(expr->left, &sym);
672 else
673 name = get_variable_from_expr(expr->right, &sym);
674 if (!name || !sym)
675 goto free;
676 state = get_state(SMATCH_EXTRA, name, sym);
677 if (!state)
678 goto free;
679 poss_true = possibly_true(expr->op, (struct data_info *)state->data, value, left);
680 poss_false = possibly_false(expr->op, (struct data_info *)state->data, value, left);
681 if (!poss_true && !poss_false)
682 return 0;
683 if (poss_true && !poss_false)
684 return 1;
685 if (!poss_true && poss_false)
686 return 2;
687 if (poss_true && poss_false)
688 return 3;
689 free:
690 free_string(name);
691 return 3;
694 int implied_condition_true(struct expression *expr)
696 struct statement *stmt;
697 long long tmp;
698 long long val;
700 if (!expr)
701 return 0;
703 if (get_value(expr, &tmp) && tmp)
704 return 1;
706 expr = strip_expr(expr);
707 switch(expr->type) {
708 case EXPR_COMPARE:
709 if (do_comparison_range(expr) == 1)
710 return 1;
711 break;
712 case EXPR_PREOP:
713 if (expr->op == '!') {
714 if (implied_condition_false(expr->unop))
715 return 1;
716 break;
718 stmt = get_block_thing(expr);
719 if (last_stmt_val(stmt, &val) && val == 1)
720 return 1;
721 break;
722 default:
723 if (implied_not_equal(expr, 0) == 1)
724 return 1;
725 break;
727 return 0;
730 int implied_condition_false(struct expression *expr)
732 struct statement *stmt;
733 struct expression *tmp;
734 long long val;
736 if (!expr)
737 return 0;
739 if (is_zero(expr))
740 return 1;
742 switch(expr->type) {
743 case EXPR_COMPARE:
744 if (do_comparison_range(expr) == 2)
745 return 1;
746 case EXPR_PREOP:
747 if (expr->op == '!') {
748 if (implied_condition_true(expr->unop))
749 return 1;
750 break;
752 stmt = get_block_thing(expr);
753 if (last_stmt_val(stmt, &val) && val == 0)
754 return 1;
755 tmp = strip_expr(expr);
756 if (tmp != expr)
757 return implied_condition_false(tmp);
758 break;
759 default:
760 if (get_implied_value(expr, &val) && val == 0)
761 return 1;
762 break;
764 return 0;
767 int get_implied_range_list(struct expression *expr, struct range_list **rl)
769 long long val;
770 struct smatch_state *state;
772 expr = strip_expr(expr);
774 state = get_state_expr(my_id, expr);
775 if (state) {
776 *rl = clone_range_list(((struct data_info *)state->data)->value_ranges);
777 return 1;
780 if (get_implied_value(expr, &val)) {
781 *rl = NULL;
782 add_range(rl, val, val);
783 return 1;
786 if (expr->type == EXPR_BINOP && expr->op == '%') {
787 if (!get_implied_value(expr->right, &val))
788 return 0;
789 *rl = NULL;
790 add_range(rl, 0, val - 1);
791 return 1;
794 return 0;
797 void register_smatch_extra(int id)
799 my_id = id;
800 add_merge_hook(my_id, &merge_func);
801 add_unmatched_state_hook(my_id, &unmatched_state);
802 add_hook(&unop_expr, OP_HOOK);
803 add_hook(&match_function_def, FUNC_DEF_HOOK);
804 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
805 add_hook(&match_assign, ASSIGNMENT_HOOK);
806 add_hook(&match_declarations, DECLARATION_HOOK);
808 if (option_project == PROJ_KERNEL) {
809 /* I don't know how to test for the ATTRIB_NORET attribute. :( */
810 add_function_hook("panic", &__match_nullify_path_hook, NULL);
811 add_function_hook("do_exit", &__match_nullify_path_hook, NULL);
812 add_function_hook("complete_and_exit", &__match_nullify_path_hook, NULL);
813 add_function_hook("__module_put_and_exit", &__match_nullify_path_hook, NULL);
814 add_function_hook("do_group_exit", &__match_nullify_path_hook, NULL);