Print this page
12724 update smatch to 0.6.1-rc1-il-5

*** 70,79 **** --- 70,81 ---- #define implied_debug 0 #define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0) bool debug_implied(void) { + if (option_debug) + return true; return implied_debug; } /* * tmp_range_list():
*** 89,98 **** --- 91,107 ---- my_range = alloc_range(ll_to_sval(num), ll_to_sval(num)); add_ptr_list(&my_list, my_range); return my_list; } + static const char *show_comparison(int op) + { + if (op == PARAM_LIMIT) + return "<lim>"; + return show_special(op); + } + static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse) { if (!implied_debug && !option_debug) return;
*** 113,122 **** --- 122,143 ---- sm->merged ? "[merged]" : "[leaf]", get_stree_id(sm->pool)); } } + void split_comparison_helper(struct range_list *left_orig, int op, struct range_list *right_orig, + struct range_list **left_true_rl, struct range_list **left_false_rl) + { + if (op == PARAM_LIMIT) { + *left_true_rl = rl_intersection(left_orig, right_orig); + *left_false_rl = rl_filter(left_orig, right_orig); + return; + } + + split_comparison_rl(left_orig, op, right_orig, left_true_rl, left_false_rl, NULL, NULL); + } + static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl) { struct range_list *orig_rl; struct range_list *true_rl, *false_rl; struct stree *true_stree, *false_stree;
*** 129,139 **** return 0; if (!estate_rl(sm->state)) return 0; orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); ! split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL); true_rl = rl_truncate_cast(estate_type(sm->state), true_rl); false_rl = rl_truncate_cast(estate_type(sm->state), false_rl); if (is_whole_rl(true_rl) || is_whole_rl(false_rl) || !true_rl || !false_rl || --- 150,160 ---- return 0; if (!estate_rl(sm->state)) return 0; orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); ! split_comparison_helper(orig_rl, comparison, rl, &true_rl, &false_rl); true_rl = rl_truncate_cast(estate_type(sm->state), true_rl); false_rl = rl_truncate_cast(estate_type(sm->state), false_rl); if (is_whole_rl(true_rl) || is_whole_rl(false_rl) || !true_rl || !false_rl ||
*** 152,162 **** return 0; } if (implied_debug) sm_msg("fake_history: %s vs %s. %s %s %s. --> T: %s F: %s", ! sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl), show_rl(true_rl), show_rl(false_rl)); true_sm = clone_sm(sm); false_sm = clone_sm(sm); --- 173,183 ---- return 0; } if (implied_debug) sm_msg("fake_history: %s vs %s. %s %s %s. --> T: %s F: %s", ! sm->name, show_rl(rl), sm->state->name, show_comparison(comparison), show_rl(rl), show_rl(true_rl), show_rl(false_rl)); true_sm = clone_sm(sm); false_sm = clone_sm(sm);
*** 231,240 **** --- 252,287 ---- } END_FOR_EACH_PTR(tmp); return ret; } + static bool possibly_true_helper(struct range_list *var_rl, int comparison, struct range_list *rl) + { + if (comparison == PARAM_LIMIT) { + struct range_list *intersect; + + intersect = rl_intersection(var_rl, rl); + if (intersect) + return true; + return false; + } + return possibly_true_rl(var_rl, comparison, rl); + } + + static bool possibly_false_helper(struct range_list *var_rl, int comparison, struct range_list *rl) + { + if (comparison == PARAM_LIMIT) { + struct range_list *intersect; + + intersect = rl_intersection(var_rl, rl); + if (!rl_equiv(var_rl, intersect)) + return true; + return false; + } + return possibly_false_rl(var_rl, comparison, rl); + } + /* * If 'foo' == 99 add it that pool to the true pools. If it's false, add it to * the false pools. If we're not sure, then we don't add it to either. */ static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,
*** 250,261 **** if (!sm->pool) return; var_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); ! istrue = !possibly_false_rl(var_rl, comparison, rl); ! isfalse = !possibly_true_rl(var_rl, comparison, rl); print_debug_tf(sm, istrue, isfalse); /* give up if we have borrowed implications (smatch_equiv.c) */ if (sm->sym != gate_sm->sym || --- 297,308 ---- if (!sm->pool) return; var_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); ! istrue = !possibly_false_helper(var_rl, comparison, rl); ! isfalse = !possibly_true_helper(var_rl, comparison, rl); print_debug_tf(sm, istrue, isfalse); /* give up if we have borrowed implications (smatch_equiv.c) */ if (sm->sym != gate_sm->sym ||
*** 313,323 **** gettimeofday(&now, NULL); timersub(&now, start_time, &diff); if (diff.tv_sec >= 1) { if (implied_debug) { sm_msg("debug: %s: implications taking too long. (%s %s %s)", ! __func__, sm->state->name, show_special(comparison), show_rl(rl)); } if (mixed) *mixed = 1; } --- 360,370 ---- gettimeofday(&now, NULL); timersub(&now, start_time, &diff); if (diff.tv_sec >= 1) { if (implied_debug) { sm_msg("debug: %s: implications taking too long. (%s %s %s)", ! __func__, sm->state->name, show_comparison(comparison), show_rl(rl)); } if (mixed) *mixed = 1; }
*** 591,601 **** int sec; gettimeofday(&time_before, NULL); DIMPLIED("checking implications: (%s (%s) %s %s)\n", ! sm->name, sm->state->name, show_special(comparison), show_rl(rl)); if (!is_merged(sm)) { DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line); return; } --- 638,648 ---- int sec; gettimeofday(&time_before, NULL); DIMPLIED("checking implications: (%s (%s) %s %s)\n", ! sm->name, sm->state->name, show_comparison(comparison), show_rl(rl)); if (!is_merged(sm)) { DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line); return; }
*** 750,760 **** name = expr_to_var_sym(expr, &sym); if (!name || !sym) goto free; sm = get_sm_state(SMATCH_EXTRA, name, sym); ! if (!sm) goto free; separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed); delete_gate_sm_equiv(implied_true, sm->name, sm->sym); delete_gate_sm_equiv(implied_false, sm->name, sm->sym); --- 797,807 ---- name = expr_to_var_sym(expr, &sym); if (!name || !sym) goto free; sm = get_sm_state(SMATCH_EXTRA, name, sym); ! if (!sm || !sm->merged) goto free; separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed); delete_gate_sm_equiv(implied_true, sm->name, sm->sym); delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
*** 771,784 **** static int handled_by_comparison_hook(struct expression *expr, struct stree **implied_true, struct stree **implied_false) { struct state_list *true_stack = NULL; struct state_list *false_stack = NULL; struct stree *pre_stree; - struct sm_state *sm; sm = comparison_implication_hook(expr, &true_stack, &false_stack); if (!sm) return 0; --- 818,831 ---- static int handled_by_comparison_hook(struct expression *expr, struct stree **implied_true, struct stree **implied_false) { + struct sm_state *sm, *true_sm, *false_sm; struct state_list *true_stack = NULL; struct state_list *false_stack = NULL; struct stree *pre_stree; sm = comparison_implication_hook(expr, &true_stack, &false_stack); if (!sm) return 0;
*** 785,794 **** --- 832,848 ---- pre_stree = clone_stree(__get_cur_stree()); *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack); *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack); + true_sm = get_sm_state_stree(*implied_true, sm->owner, sm->name, sm->sym); + false_sm = get_sm_state_stree(*implied_false, sm->owner, sm->name, sm->sym); + if (true_sm && strcmp(true_sm->state->name, "unknown") == 0) + delete_state_stree(implied_true, sm->owner, sm->name, sm->sym); + if (false_sm && strcmp(false_sm->state->name, "unknown") == 0) + delete_state_stree(implied_false, sm->owner, sm->name, sm->sym); + free_stree(&pre_stree); free_slist(&true_stack); free_slist(&false_stack); return 1;
*** 951,975 **** extra_saved_implied_true = NULL; extra_saved_implied_false = NULL; set_implied_states(NULL); } ! void param_limit_implications(struct expression *expr, int param, char *key, char *value) { ! struct expression *arg; struct symbol *compare_type; char *name; struct symbol *sym; struct sm_state *sm; struct sm_state *tmp; struct stree *implied_true = NULL; struct stree *implied_false = NULL; struct range_list *orig, *limit; if (time_parsing_function() > 40) return; while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); if (expr->type != EXPR_CALL) return; --- 1005,1033 ---- extra_saved_implied_true = NULL; extra_saved_implied_false = NULL; set_implied_states(NULL); } ! void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied) { ! struct expression *orig_expr, *arg; struct symbol *compare_type; char *name; struct symbol *sym; struct sm_state *sm; struct sm_state *tmp; struct stree *implied_true = NULL; struct stree *implied_false = NULL; struct range_list *orig, *limit; + char *left_name = NULL; + struct symbol *left_sym = NULL; + int mixed = 0; if (time_parsing_function() > 40) return; + orig_expr = expr; while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); if (expr->type != EXPR_CALL) return;
*** 997,1009 **** orig = estate_rl(sm->state); orig = cast_rl(compare_type, orig); call_results_to_rl(expr, compare_type, value, &limit); ! separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL); FOR_EACH_SM(implied_true, tmp) { __set_sm_fake_stree(tmp); } END_FOR_EACH_SM(tmp); free_stree(&implied_true); free_stree(&implied_false); --- 1055,1083 ---- orig = estate_rl(sm->state); orig = cast_rl(compare_type, orig); call_results_to_rl(expr, compare_type, value, &limit); ! separate_and_filter(sm, PARAM_LIMIT, limit, __get_cur_stree(), &implied_true, &implied_false, &mixed); + if (orig_expr->type == EXPR_ASSIGNMENT) + left_name = expr_to_var_sym(orig_expr->left, &left_sym); + FOR_EACH_SM(implied_true, tmp) { + /* + * What we're trying to do here is preserve the sm state so that + * smatch extra doesn't create a new sm state when it parses the + * PARAM_LIMIT. + */ + if (!mixed && tmp->sym == sym && + strcmp(tmp->name, name) == 0 && + (!left_name || strcmp(left_name, name) != 0)) { + overwrite_sm_state_stree(implied, tmp); + continue; + } + + // TODO why can't this just be __set_sm()? __set_sm_fake_stree(tmp); } END_FOR_EACH_SM(tmp); free_stree(&implied_true); free_stree(&implied_false);