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

*** 48,57 **** --- 48,58 ---- void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm); }; ALLOCATOR(member_info_callback, "caller_info callbacks"); DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback); static struct member_info_cb_list *member_callbacks; + static struct member_info_cb_list *member_callbacks_new; struct returned_state_callback { void (*callback)(int return_id, char *return_ranges, struct expression *return_expr); }; ALLOCATOR(returned_state_callback, "returned state callbacks");
*** 176,194 **** void db_ignore_states(int id) { use_states[id] = 0; } void sql_insert_return_states(int return_id, const char *return_ranges, int type, int param, const char *key, const char *value) { if (key && strlen(key) >= 80) return; return_ranges = replace_return_ranges(return_ranges); ! sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'", ! get_base_file(), get_function(), (unsigned long)__inline_fn, ! return_id, return_ranges, fn_static(), type, param, key, value); } static struct string_list *common_funcs; static int is_common_function(const char *fn) { --- 177,216 ---- void db_ignore_states(int id) { use_states[id] = 0; } + unsigned long long __fn_mtag; + static void set_fn_mtag(struct symbol *sym) + { + char buf[128]; + + if (cur_func_sym->ctype.modifiers & MOD_STATIC) + snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function()); + else + snprintf(buf, sizeof(buf), "extern %s", get_function()); + + __fn_mtag = str_to_mtag(buf); + } + void sql_insert_return_states(int return_id, const char *return_ranges, int type, int param, const char *key, const char *value) { + unsigned long long id; + + if (key && strlen(key) >= 80) return; + if (__inline_fn) + id = (unsigned long)__inline_fn; + else + id = __fn_mtag; + return_ranges = replace_return_ranges(return_ranges); ! sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'", ! get_base_file(), get_function(), id, return_id, ! return_ranges, fn_static(), type, param, key, value); } static struct string_list *common_funcs; static int is_common_function(const char *fn) {
*** 370,388 **** type, param, key, value); } void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name) { ! sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'", ! tag, get_filename(), get_function(), get_lineno(), left_name, right_name); } ! void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container) { ! sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container); } void sql_insert_mtag_alias(mtag_t orig, mtag_t alias) { sql_insert(mtag_alias, "%lld, %lld", orig, alias); } --- 392,416 ---- type, param, key, value); } void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name) { ! sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'", ! tag, get_filename(), get_function(), get_lineno(), ! left_name, right_name); } ! void sql_insert_mtag_info(mtag_t tag, int type, const char *value) { ! sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value); } + void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset) + { + sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset); + } + void sql_insert_mtag_alias(mtag_t orig, mtag_t alias) { sql_insert(mtag_alias, "%lld, %lld", orig, alias); }
*** 399,415 **** *saved_tag = -1ULL; return 0; } ! int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container) { mtag_t tmp = 0; run_sql(save_mtag, &tmp, ! "select container from mtag_map where tag = %lld and offset = %d;", ! tag, offset); if (tmp == 0 || tmp == -1ULL) return 0; *container = tmp; return 1; --- 427,443 ---- *saved_tag = -1ULL; return 0; } ! int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container) { mtag_t tmp = 0; run_sql(save_mtag, &tmp, ! "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;", ! tag, container_offset); if (tmp == 0 || tmp == -1ULL) return 0; *container = tmp; return 1;
*** 418,428 **** int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag) { mtag_t tmp = 0; run_sql(save_mtag, &tmp, ! "select tag from mtag_map where container = %lld and offset = %d;", container, offset); if (tmp == 0 || tmp == -1ULL) return 0; *tag = tmp; --- 446,456 ---- int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag) { mtag_t tmp = 0; run_sql(save_mtag, &tmp, ! "select tag from mtag_map where container = %lld and container_offset = %d;", container, offset); if (tmp == 0 || tmp == -1ULL) return 0; *tag = tmp;
*** 620,629 **** --- 648,666 ---- member_callback->owner = owner; member_callback->callback = callback; add_ptr_list(&member_callbacks, member_callback); } + void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) + { + struct member_info_callback *member_callback = __alloc_member_info_callback(0); + + member_callback->owner = owner; + member_callback->callback = callback; + add_ptr_list(&member_callbacks_new, member_callback); + } + void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr)) { struct returned_state_callback *callback = __alloc_returned_state_callback(0); callback->callback = fn;
*** 849,859 **** free_string(name); return ret; } static void print_struct_members(struct expression *call, struct expression *expr, int param, 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; char *name; struct symbol *sym; --- 886,897 ---- free_string(name); return ret; } static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree, ! void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm), ! bool new) { struct sm_state *sm; const char *sm_name; char *name; struct symbol *sym;
*** 889,916 **** add_star = true; sm_name++; } // FIXME: simplify? if (!add_star && strcmp(name, sm_name) == 0) { ! if (is_address) snprintf(printed_name, sizeof(printed_name), "*$"); ! else /* these are already handled. fixme: handle them here */ continue; } else if (add_star && strcmp(name, sm_name) == 0) { snprintf(printed_name, sizeof(printed_name), "%s*$", is_address ? "*" : ""); } else if (strncmp(name, sm_name, len) == 0) { if (sm_name[len] != '.' && sm_name[len] != '-') continue; ! if (is_address) snprintf(printed_name, sizeof(printed_name), "%s$->%s", add_star ? "*" : "", sm_name + len + 1); ! else snprintf(printed_name, sizeof(printed_name), "%s$%s", add_star ? "*" : "", sm_name + len); } else { continue; } if (is_recursive_member(printed_name)) continue; --- 927,963 ---- add_star = true; sm_name++; } // FIXME: simplify? if (!add_star && strcmp(name, sm_name) == 0) { ! if (is_address) { snprintf(printed_name, sizeof(printed_name), "*$"); ! } else { ! if (new) ! snprintf(printed_name, sizeof(printed_name), "$"); ! else continue; + } } else if (add_star && strcmp(name, sm_name) == 0) { snprintf(printed_name, sizeof(printed_name), "%s*$", is_address ? "*" : ""); } else if (strncmp(name, sm_name, len) == 0) { if (sm_name[len] != '.' && sm_name[len] != '-') continue; ! if (is_address && sm_name[len] == '.') { snprintf(printed_name, sizeof(printed_name), "%s$->%s", add_star ? "*" : "", sm_name + len + 1); ! } else if (is_address && sm_name[len] == '-') { snprintf(printed_name, sizeof(printed_name), + "%s(*$)%s", add_star ? "*" : "", + sm_name + len); + } else { + snprintf(printed_name, sizeof(printed_name), "%s$%s", add_star ? "*" : "", sm_name + len); + } } else { continue; } if (is_recursive_member(printed_name)) continue;
*** 934,952 **** FOR_EACH_PTR(member_callbacks, cb) { stree = get_all_states_stree(cb->owner); i = 0; FOR_EACH_PTR(call->args, arg) { ! print_struct_members(call, arg, i, stree, cb->callback); i++; } END_FOR_EACH_PTR(arg); free_stree(&stree); } END_FOR_EACH_PTR(cb); free_string(name); } static int get_param(int param, char **name, struct symbol **sym) { struct symbol *arg; int i; --- 981,1024 ---- FOR_EACH_PTR(member_callbacks, cb) { stree = get_all_states_stree(cb->owner); i = 0; FOR_EACH_PTR(call->args, arg) { ! print_struct_members(call, arg, i, stree, cb->callback, 0); i++; } END_FOR_EACH_PTR(arg); free_stree(&stree); } END_FOR_EACH_PTR(cb); free_string(name); } + static void match_call_info_new(struct expression *call) + { + struct member_info_callback *cb; + struct expression *arg; + struct stree *stree; + char *name; + int i; + + name = get_fnptr_name(call->fn); + if (!name) + return; + + FOR_EACH_PTR(member_callbacks_new, cb) { + stree = get_all_states_stree(cb->owner); + i = 0; + FOR_EACH_PTR(call->args, arg) { + print_struct_members(call, arg, i, stree, cb->callback, 1); + i++; + } END_FOR_EACH_PTR(arg); + free_stree(&stree); + } END_FOR_EACH_PTR(cb); + + free_string(name); + } + static int get_param(int param, char **name, struct symbol **sym) { struct symbol *arg; int i;
*** 1104,1113 **** --- 1176,1186 ---- struct timeval end_time; if (!sym || !sym->ident) return; + set_fn_mtag(sym); gettimeofday(&data.start_time, NULL); __push_fake_cur_stree(); __unnullify_path();
*** 1567,1577 **** static int call_return_state_hooks_split_possible(struct expression *expr) { struct sm_state *sm; ! if (!expr || expr_equal_to_param(expr, -1)) return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); return split_possible_helper(sm, expr); } --- 1640,1650 ---- static int call_return_state_hooks_split_possible(struct expression *expr) { struct sm_state *sm; ! if (!expr) return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); return split_possible_helper(sm, expr); }
*** 1705,1714 **** --- 1778,1789 ---- 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_negative(sm)) + return 0; if (!has_separate_zero_null(sm)) return 0; nr_states = get_db_state_count(); if (option_info && nr_states >= 1500)
*** 2018,2027 **** --- 2093,2120 ---- if (!last_stmt || last_stmt->type != STMT_EXPRESSION) return orig; return strip_expr(last_stmt->expression); } + static bool is_kernel_error_path(struct expression *expr) + { + struct range_list *rl; + + /* + * Splitting up returns requires resources. It also requires resources + * for the caller. It doesn't seem worth it to split anything up. + */ + if (!get_implied_rl(expr, &rl)) + return false; + if (rl_type(rl) != &int_ctype) + return false; + if (rl_min(rl).value >= -4095 && + rl_max(rl).value < 0) + return true; + return false; + } + static void call_return_state_hooks(struct expression *expr) { struct returned_state_callback *cb; struct range_list *ret_rl; const char *return_ranges;
*** 2042,2051 **** --- 2135,2146 ---- (is_condition(expr) || is_boolean(expr))) { call_return_state_hooks_compare(expr); return; } else if (call_return_state_hooks_conditional(expr)) { return; + } else if (is_kernel_error_path(expr)) { + goto vanilla; } else if (call_return_state_hooks_split_possible(expr)) { return; } else if (split_positive_from_negative(expr)) { return; } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
*** 2163,2172 **** --- 2258,2268 ---- "db/constraints.schema", "db/constraints_required.schema", "db/fn_ptr_data_link.schema", "db/fn_data_link.schema", "db/mtag_about.schema", + "db/mtag_info.schema", "db/mtag_map.schema", "db/mtag_data.schema", "db/mtag_alias.schema", }; static char buf[4096];
*** 2210,2220 **** --- 2306,2318 ---- int rc; const char *schema_files[] = { "db/call_implies.schema", "db/return_implies.schema", "db/type_info.schema", + "db/mtag_about.schema", "db/mtag_data.schema", + "db/mtag_info.schema", "db/sink_info.schema", }; static char buf[4096]; int fd; int ret;
*** 2275,2291 **** return 0; } static void dump_cache(struct symbol_list *sym_list) { if (!option_info) return; ! cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;"); ! cache_sql(&save_cache_data, (char *)"return_implies", "select * from return_implies;"); ! cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;"); ! cache_sql(&save_cache_data, (char *)"mtag_data", "select * from mtag_data;"); ! cache_sql(&save_cache_data, (char *)"sink_info", "select * from sink_info;"); } void open_smatch_db(char *db_file) { int rc; --- 2373,2396 ---- return 0; } static void dump_cache(struct symbol_list *sym_list) { + const char *cache_tables[] = { + "type_info", "return_implies", "call_implies", "mtag_data", + "mtag_info", "mtag_about", "sink_info", + }; + char buf[64]; + int i; + if (!option_info) return; ! ! for (i = 0; i < ARRAY_SIZE(cache_tables); i++) { ! snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]); ! cache_sql(&save_cache_data, (char *)cache_tables[i], buf); ! } } void open_smatch_db(char *db_file) { int rc;
*** 2427,2436 **** --- 2532,2542 ---- } void register_definition_db_callbacks(int id) { add_hook(&match_call_info, FUNCTION_CALL_HOOK); + add_hook(&match_call_info_new, FUNCTION_CALL_HOOK); add_split_return_callback(match_return_info); add_split_return_callback(print_returned_struct_members); add_hook(&call_return_state_hooks, RETURN_HOOK); add_hook(&match_end_func_info, END_FUNC_HOOK); add_hook(&match_after_func, AFTER_FUNC_HOOK);
*** 2491,2503 **** --- 2597,2611 ---- return get_variable_from_key(arg, key, sym); } char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym) { + struct symbol *type; char buf[256]; char *tmp; int star_cnt = 0; + bool add_dot = false; if (!arg) return NULL; arg = strip_expr(arg);
*** 2517,2532 **** 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 == '&') { --- 2625,2665 ---- free_string(tmp); return alloc_string(buf); } } + if (strncmp(key, "(*$)", 4) == 0) { + char buf[64]; + + if (arg->type == EXPR_PREOP && arg->op == '&') { + arg = strip_expr(arg->unop); + snprintf(buf, sizeof(buf), "$%s", key + 4); + return get_variable_from_key(arg, buf, sym); + } else { + tmp = expr_to_var_sym(arg, sym); + if (!tmp) + return NULL; + snprintf(buf, sizeof(buf), "(*%s)%s", tmp, key + 4); + free_string(tmp); + return alloc_string(buf); + } + } + while (key[0] == '*') { star_cnt++; key++; } ! /* ! * FIXME: This is a hack. ! * We should be able to parse expressions like (*$)->foo and *$->foo. ! */ ! type = get_type(arg); ! if (is_struct_ptr(type)) ! add_dot = true; ! ! if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt && !add_dot) { arg = strip_expr(arg->unop); star_cnt--; } if (arg->type == EXPR_PREOP && arg->op == '&') {
*** 2571,2580 **** --- 2704,2721 ---- /* ten out of ten stars! */ if (star_cnt > 10) return NULL; + if (strncmp(state_name, "(*", 2) == 0 && + strncmp(state_name + 2, param_name, name_len) == 0 && + state_name[name_len + 2] == ')') { + snprintf(buf, sizeof(buf), "%.*s(*$)%s", star_cnt, "**********", + state_name + name_len + 3); + return alloc_sname(buf); + } + if (strcmp(state_name, param_name) == 0) { snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********"); return alloc_sname(buf); }