Print this page
12166 resync smatch to 0.6.1-rc1-il-3

*** 25,36 **** --- 25,40 ---- struct sqlite3 *smatch_db; struct sqlite3 *mem_db; struct sqlite3 *cache_db; + int debug_db; + static int return_id; + static void call_return_state_hooks(struct expression *expr); + #define SQLITE_CACHE_PAGES 1000 struct def_callback { int hook_type; void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
*** 103,113 **** { int i; for (i = 0; i < argc; i++) { if (i != 0) ! printf(", "); sm_printf("%s", argv[i]); } sm_printf("\n"); return 0; } --- 107,117 ---- { int i; for (i = 0; i < argc; i++) { if (i != 0) ! sm_printf(", "); sm_printf("%s", argv[i]); } sm_printf("\n"); return 0; }
*** 118,128 **** int rc; if (!db) return; ! if (option_debug) { sm_msg("%s", sql); if (strncasecmp(sql, "select", strlen("select")) == 0) sqlite3_exec(db, sql, print_sql_output, NULL, NULL); } --- 122,132 ---- int rc; if (!db) return; ! if (option_debug || debug_db) { sm_msg("%s", sql); if (strncasecmp(sql, "select", strlen("select")) == 0) sqlite3_exec(db, sql, print_sql_output, NULL, NULL); }
*** 799,808 **** --- 803,867 ---- return 1; p = next; } } + char *sm_to_arg_name(struct expression *expr, struct sm_state *sm) + { + struct symbol *sym; + const char *sm_name; + char *name; + bool is_address = false; + bool add_star = false; + char buf[256]; + char *ret = NULL; + int len; + + expr = strip_expr(expr); + if (!expr) + return NULL; + + if (expr->type == EXPR_PREOP && expr->op == '&') { + expr = strip_expr(expr->unop); + is_address = true; + } + + name = expr_to_var_sym(expr, &sym); + if (!name || !sym) + goto free; + if (sym != sm->sym) + goto free; + + sm_name = sm->name; + add_star = false; + if (sm_name[0] == '*') { + add_star = true; + sm_name++; + } + + len = strlen(name); + if (strncmp(name, sm_name, len) != 0) + goto free; + if (sm_name[len] == '\0') { + snprintf(buf, sizeof(buf), "%s%s$", + add_star ? "*" : "", is_address ? "*" : ""); + } else { + if (sm_name[len] != '.' && sm_name[len] != '-') + goto free; + if (sm_name[len] == '-') + len++; + // FIXME does is_address really imply that sm_name[len] == '-' + snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "", + sm_name + len); + } + + ret = alloc_sname(buf); + free: + free_string(name); + return ret; + } + static void print_struct_members(struct expression *call, struct expression *expr, int param, int offset, struct stree *stree, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) { struct sm_state *sm; const char *sm_name;
*** 1415,1459 **** static void match_return_info(int return_id, char *return_ranges, struct expression *expr) { sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature()); } ! static void call_return_state_hooks_conditional(struct expression *expr) { - struct returned_state_callback *cb; - struct range_list *rl; - const char *return_ranges; int final_pass_orig = final_pass; __push_fake_cur_stree(); final_pass = 0; __split_whole_condition(expr->conditional); final_pass = final_pass_orig; ! return_ranges = get_return_ranges_str(expr->cond_true ?: expr->conditional, &rl); - set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl)); - - return_id++; - FOR_EACH_PTR(returned_state_callbacks, cb) { - cb->callback(return_id, (char *)return_ranges, expr->cond_true); - } END_FOR_EACH_PTR(cb); - __push_true_states(); __use_false_states(); ! return_ranges = get_return_ranges_str(expr->cond_false, &rl); ! set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(rl)); - return_id++; - FOR_EACH_PTR(returned_state_callbacks, cb) { - cb->callback(return_id, (char *)return_ranges, expr->cond_false); - } END_FOR_EACH_PTR(cb); - __merge_true_states(); __free_fake_cur_stree(); } static void call_return_state_hooks_compare(struct expression *expr) { struct returned_state_callback *cb; --- 1474,1514 ---- static void match_return_info(int return_id, char *return_ranges, struct expression *expr) { sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature()); } ! static bool call_return_state_hooks_conditional(struct expression *expr) { int final_pass_orig = final_pass; + static int recurse; + if (recurse >= 2) + return false; + if (!expr || + (expr->type != EXPR_CONDITIONAL && expr->type != EXPR_SELECT)) + return false; + + recurse++; + __push_fake_cur_stree(); final_pass = 0; __split_whole_condition(expr->conditional); final_pass = final_pass_orig; ! call_return_state_hooks(expr->cond_true ?: expr->conditional); __push_true_states(); __use_false_states(); ! call_return_state_hooks(expr->cond_false); __merge_true_states(); __free_fake_cur_stree(); + + recurse--; + return true; } static void call_return_state_hooks_compare(struct expression *expr) { struct returned_state_callback *cb;
*** 1534,1545 **** --- 1589,1604 ---- /* bail if it gets too complicated */ nr_possible = 0; FOR_EACH_PTR(sm->possible, tmp) { if (tmp->merged) continue; + if (ptr_in_list(tmp, already_handled)) + continue; + add_ptr_list(&already_handled, tmp); nr_possible++; } END_FOR_EACH_PTR(tmp); + free_slist(&already_handled); nr_states = get_db_state_count(); if (nr_states * nr_possible >= 2000) return 0; FOR_EACH_PTR(sm->possible, tmp) {
*** 1591,1600 **** --- 1650,1662 ---- static bool has_possible_negative(struct sm_state *sm) { struct sm_state *tmp; + if (!type_signed(estate_type(sm->state))) + return false; + FOR_EACH_PTR(sm->possible, tmp) { if (!estate_rl(tmp->state)) continue; if (sval_is_negative(estate_min(tmp->state)) && sval_is_negative(estate_max(tmp->state)))
*** 1602,1612 **** } END_FOR_EACH_PTR(tmp); return false; } ! static bool has_possible_zero_null(struct sm_state *sm) { struct sm_state *tmp; sval_t sval; FOR_EACH_PTR(sm->possible, tmp) { --- 1664,1674 ---- } END_FOR_EACH_PTR(tmp); return false; } ! static bool has_separate_zero_null(struct sm_state *sm) { struct sm_state *tmp; sval_t sval; FOR_EACH_PTR(sm->possible, tmp) {
*** 1624,1644 **** struct sm_state *sm; struct returned_state_callback *cb; struct range_list *rl; const char *return_ranges; struct range_list *ret_rl; int undo; - bool has_zero; /* We're going to print the states 3 times */ if (get_db_state_count() > 10000 / 3) return 0; if (!get_implied_rl(expr, &rl) || !rl) return 0; - if (is_whole_rl(rl) || is_whole_rl_non_zero(rl)) - return 0; /* Forget about INT_MAX and larger */ if (rl_max(rl).value <= 0) return 0; if (!sval_is_negative(rl_min(rl))) return 0; --- 1686,1704 ---- struct sm_state *sm; struct returned_state_callback *cb; struct range_list *rl; const char *return_ranges; struct range_list *ret_rl; + bool separate_zero; int undo; /* We're going to print the states 3 times */ if (get_db_state_count() > 10000 / 3) return 0; if (!get_implied_rl(expr, &rl) || !rl) return 0; /* Forget about INT_MAX and larger */ if (rl_max(rl).value <= 0) return 0; if (!sval_is_negative(rl_min(rl))) return 0;
*** 1646,1658 **** sm = get_sm_state_expr(SMATCH_EXTRA, expr); if (!sm) return 0; if (!has_possible_negative(sm)) return 0; ! has_zero = has_possible_zero_null(sm); ! if (!assume(compare_expression(expr, has_zero ? '>' : SPECIAL_GTE, zero_expr()))) return 0; return_id++; return_ranges = get_return_ranges_str(expr, &ret_rl); set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl)); --- 1706,1718 ---- sm = get_sm_state_expr(SMATCH_EXTRA, expr); if (!sm) return 0; if (!has_possible_negative(sm)) return 0; ! separate_zero = has_separate_zero_null(sm); ! if (!assume(compare_expression(expr, separate_zero ? '>' : SPECIAL_GTE, zero_expr()))) return 0; return_id++; return_ranges = get_return_ranges_str(expr, &ret_rl); set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
*** 1660,1670 **** cb->callback(return_id, (char *)return_ranges, expr); } END_FOR_EACH_PTR(cb); end_assume(); ! if (has_zero) { undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr())); return_id++; return_ranges = get_return_ranges_str(expr, &ret_rl); set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl)); --- 1720,1730 ---- cb->callback(return_id, (char *)return_ranges, expr); } END_FOR_EACH_PTR(cb); end_assume(); ! if (separate_zero) { undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr())); return_id++; return_ranges = get_return_ranges_str(expr, &ret_rl); set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
*** 1717,1727 **** state = sm->state; if (!estate_rl(state)) return 0; if (estate_min(state).value == 0 && estate_max(state).value == 0) return 0; ! if (!has_possible_zero_null(sm)) return 0; nr_states = get_db_state_count(); if (option_info && nr_states >= 1500) return 0; --- 1777,1787 ---- state = sm->state; if (!estate_rl(state)) return 0; if (estate_min(state).value == 0 && estate_max(state).value == 0) return 0; ! if (!has_separate_zero_null(sm)) return 0; nr_states = get_db_state_count(); if (option_info && nr_states >= 1500) return 0;
*** 1759,1768 **** --- 1819,1859 ---- __free_fake_cur_stree(); return 1; } + static bool is_kernel_success_fail(struct sm_state *sm) + { + struct sm_state *tmp; + struct range_list *rl; + bool has_zero = false; + bool has_neg = false; + + if (!type_signed(estate_type(sm->state))) + return false; + + FOR_EACH_PTR(sm->possible, tmp) { + rl = estate_rl(tmp->state); + if (!rl) + return false; + if (rl_min(rl).value == 0 && rl_max(rl).value == 0) { + has_zero = true; + continue; + } + has_neg = true; + if (rl_min(rl).value >= -4095 && rl_max(rl).value < 0) + continue; + if (strcmp(tmp->state->name, "s32min-(-1)") == 0) + continue; + if (strcmp(tmp->state->name, "s32min-(-1),1-s32max") == 0) + continue; + return false; + } END_FOR_EACH_PTR(tmp); + + return has_zero && has_neg; + } + static int call_return_state_hooks_split_success_fail(struct expression *expr) { struct sm_state *sm; struct range_list *rl; struct range_list *nonzero_rl;
*** 1775,1804 **** if (option_project != PROJ_KERNEL) return 0; nr_states = get_db_state_count(); ! if (nr_states > 1500) return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); if (!sm) return 0; if (ptr_list_size((struct ptr_list *)sm->possible) == 1) return 0; rl = estate_rl(sm->state); if (!rl) return 0; - if (rl_min(rl).value < -4095 || rl_min(rl).value >= 0) - return 0; - if (rl_max(rl).value != 0) - return 0; - if (!has_possible_zero_null(sm)) - return 0; - __push_fake_cur_stree(); final_pass = 0; __split_whole_condition(expr); final_pass = final_pass_orig; --- 1866,1890 ---- if (option_project != PROJ_KERNEL) return 0; nr_states = get_db_state_count(); ! if (nr_states > 2000) return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); if (!sm) return 0; if (ptr_list_size((struct ptr_list *)sm->possible) == 1) return 0; + if (!is_kernel_success_fail(sm)) + return 0; rl = estate_rl(sm->state); if (!rl) return 0; __push_fake_cur_stree(); final_pass = 0; __split_whole_condition(expr); final_pass = final_pass_orig;
*** 1840,1858 **** if (rl_min(rl).value == 0 && rl_max(rl).value == 1) return 1; return 0; } - static int is_conditional(struct expression *expr) - { - if (!expr) - return 0; - if (expr->type == EXPR_CONDITIONAL || expr->type == EXPR_SELECT) - return 1; - return 0; - } - static int splitable_function_call(struct expression *expr) { struct sm_state *sm; char buf[64]; --- 1926,1935 ----
*** 1906,1930 **** struct returned_state_callback *cb; struct range_list *ret_rl; const char *return_ranges; struct sm_state *tmp; int ret = 0; - int nr_possible, nr_states; struct state_list *already_handled = NULL; if (!sm || !sm->merged) return 0; if (too_many_possible(sm)) return 0; - /* bail if it gets too complicated */ - nr_possible = ptr_list_size((struct ptr_list *)sm->possible); - nr_states = get_db_state_count(); - if (nr_states * nr_possible >= 2000) - return 0; - FOR_EACH_PTR(sm->possible, tmp) { if (tmp->merged) continue; if (ptr_in_list(tmp, already_handled)) continue; --- 1983,2000 ----
*** 1959,1978 **** if (!start_sm) return 0; sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym); if (!sm || estate_get_single_value(sm->state, &sval)) return 0; return split_on_bool_sm(sm, expr); } static int split_by_null_nonnull_param(struct expression *expr) { struct symbol *arg; struct sm_state *sm; ! sval_t zero = { ! .type = &ulong_ctype, ! }; /* function must only take one pointer */ if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1) return 0; arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments); --- 2029,2050 ---- if (!start_sm) return 0; sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym); if (!sm || estate_get_single_value(sm->state, &sval)) return 0; + + if (get_db_state_count() * 2 >= 2000) + return 0; + return split_on_bool_sm(sm, expr); } static int split_by_null_nonnull_param(struct expression *expr) { struct symbol *arg; struct sm_state *sm; ! int nr_possible; /* function must only take one pointer */ if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1) return 0; arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments);
*** 1985,1997 **** return 0; sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg); if (!sm) return 0; ! if (!rl_has_sval(estate_rl(sm->state), zero)) return 0; return split_on_bool_sm(sm, expr); } struct expression *strip_expr_statement(struct expression *expr) { --- 2057,2073 ---- return 0; sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg); if (!sm) return 0; ! if (!has_separate_zero_null(sm)) return 0; + nr_possible = ptr_list_size((struct ptr_list *)sm->possible); + if (get_db_state_count() * nr_possible >= 2000) + return 0; + return split_on_bool_sm(sm, expr); } struct expression *strip_expr_statement(struct expression *expr) {
*** 2036,2047 **** if (expr && (expr->type == EXPR_COMPARE || !get_implied_value(expr, &sval)) && (is_condition(expr) || is_boolean(expr))) { call_return_state_hooks_compare(expr); return; ! } else if (is_conditional(expr)) { ! call_return_state_hooks_conditional(expr); return; } else if (call_return_state_hooks_split_possible(expr)) { return; } else if (split_positive_from_negative(expr)) { return; --- 2112,2122 ---- if (expr && (expr->type == EXPR_COMPARE || !get_implied_value(expr, &sval)) && (is_condition(expr) || is_boolean(expr))) { call_return_state_hooks_compare(expr); return; ! } else if (call_return_state_hooks_conditional(expr)) { return; } else if (call_return_state_hooks_split_possible(expr)) { return; } else if (split_positive_from_negative(expr)) { return;
*** 2490,2500 **** char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym) { char buf[256]; char *tmp; ! bool add_star = false; if (!arg) return NULL; arg = strip_expr(arg); --- 2565,2575 ---- char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym) { char buf[256]; char *tmp; ! int star_cnt = 0; if (!arg) return NULL; arg = strip_expr(arg);
*** 2514,2542 **** free_string(tmp); return alloc_string(buf); } } ! if (key[0] == '*') { ! add_star = true; key++; } if (arg->type == EXPR_PREOP && arg->op == '&') { arg = strip_expr(arg->unop); tmp = expr_to_var_sym(arg, sym); if (!tmp) return NULL; ! snprintf(buf, sizeof(buf), "%s%s.%s", ! add_star ? "*" : "", tmp, key + 3); return alloc_string(buf); } tmp = expr_to_var_sym(arg, sym); if (!tmp) return NULL; ! snprintf(buf, sizeof(buf), "%s%s%s", add_star ? "*" : "", tmp, key + 1); free_string(tmp); return alloc_string(buf); } char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl) --- 2589,2622 ---- free_string(tmp); return alloc_string(buf); } } ! while (key[0] == '*') { ! star_cnt++; key++; } + if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt) { + arg = strip_expr(arg->unop); + star_cnt--; + } + if (arg->type == EXPR_PREOP && arg->op == '&') { arg = strip_expr(arg->unop); tmp = expr_to_var_sym(arg, sym); if (!tmp) return NULL; ! snprintf(buf, sizeof(buf), "%.*s%s.%s", ! star_cnt, "**********", tmp, key + 3); return alloc_string(buf); } tmp = expr_to_var_sym(arg, sym); if (!tmp) return NULL; ! snprintf(buf, sizeof(buf), "%.*s%s%s", star_cnt, "**********", tmp, key + 1); free_string(tmp); return alloc_string(buf); } char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl)
*** 2548,2577 **** return get_variable_from_key(arg, key, sym); } const char *state_name_to_param_name(const char *state_name, const char *param_name) { int name_len; ! static char buf[256]; ! bool add_star = false; name_len = strlen(param_name); ! if (state_name[0] == '*') { ! add_star = true; state_name++; } if (strcmp(state_name, param_name) == 0) { ! snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : ""); return alloc_sname(buf); } if (state_name[name_len] == '-' && /* check for '-' from "->" */ strncmp(state_name, param_name, name_len) == 0) { ! snprintf(buf, sizeof(buf), "%s$%s", ! add_star ? "*" : "", state_name + name_len); return alloc_sname(buf); } return NULL; } --- 2628,2660 ---- return get_variable_from_key(arg, key, sym); } const char *state_name_to_param_name(const char *state_name, const char *param_name) { + int star_cnt = 0; int name_len; ! char buf[256]; name_len = strlen(param_name); ! while (state_name[0] == '*') { ! star_cnt++; state_name++; } + /* ten out of ten stars! */ + if (star_cnt > 10) + return NULL; + if (strcmp(state_name, param_name) == 0) { ! snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********"); return alloc_sname(buf); } if (state_name[name_len] == '-' && /* check for '-' from "->" */ strncmp(state_name, param_name, name_len) == 0) { ! snprintf(buf, sizeof(buf), "%.*s$%s", star_cnt, "**********", state_name + name_len); return alloc_sname(buf); } return NULL; }