Print this page
new smatch

*** 97,112 **** void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { call_extra_hooks(extra_nomod_hooks, name, sym, expr, state); } static bool in_param_set; void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { remove_from_equiv(name, sym); call_extra_mod_hooks(name, sym, expr, state); ! if ((__in_fake_assign || in_param_set) && estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym)) return; set_state(SMATCH_EXTRA, name, sym, state); } --- 97,186 ---- void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { call_extra_hooks(extra_nomod_hooks, name, sym, expr, state); } + static void set_union_info(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) + { + struct symbol *type, *tmp, *inner_type, *inner, *new_type; + struct expression *deref, *member_expr; + struct smatch_state *new; + int offset, inner_offset; + static bool in_recurse; + char *member_name; + + if (__in_fake_assign) + return; + + if (in_recurse) + return; + in_recurse = true; + + if (!expr || expr->type != EXPR_DEREF || !expr->member) + goto done; + offset = get_member_offset_from_deref(expr); + if (offset < 0) + goto done; + + deref = strip_expr(expr->deref); + type = get_type(deref); + if (type_is_ptr(type)) + type = get_real_base_type(type); + if (!type || type->type != SYM_STRUCT) + goto done; + + FOR_EACH_PTR(type->symbol_list, tmp) { + inner_type = get_real_base_type(tmp); + if (!inner_type || inner_type->type != SYM_UNION) + continue; + + inner = first_ptr_list((struct ptr_list *)inner_type->symbol_list); + if (!inner || !inner->ident) + continue; + + inner_offset = get_member_offset(type, inner->ident->name); + if (inner_offset < offset) + continue; + if (inner_offset > offset) + goto done; + + FOR_EACH_PTR(inner_type->symbol_list, inner) { + struct symbol *tmp_type; + + if (!inner->ident || inner->ident == expr->member) + continue; + tmp_type = get_real_base_type(inner); + if (tmp_type && tmp_type->type == SYM_STRUCT) + continue; + member_expr = deref; + if (tmp->ident) + member_expr = member_expression(member_expr, '.', tmp->ident); + member_expr = member_expression(member_expr, expr->op, inner->ident); + member_name = expr_to_var(member_expr); + if (!member_name) + continue; + new_type = get_real_base_type(inner); + new = alloc_estate_rl(cast_rl(new_type, estate_rl(state))); + set_extra_mod_helper(member_name, sym, member_expr, new); + free_string(member_name); + } END_FOR_EACH_PTR(inner); + } END_FOR_EACH_PTR(tmp); + + done: + in_recurse = false; + } + static bool in_param_set; void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { + if (!expr) + expr = gen_expression_from_name_sym(name, sym); remove_from_equiv(name, sym); + set_union_info(name, sym, expr, state); call_extra_mod_hooks(name, sym, expr, state); ! update_mtag_data(expr, state); ! if (in_param_set && estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym)) return; set_state(SMATCH_EXTRA, name, sym, state); }
*** 170,180 **** free: free_string(orig_name); return NULL; } ! static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym) { struct expression *tmp; struct sm_state *sm; char buf[256]; --- 244,254 ---- free: free_string(orig_name); return NULL; } ! static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack) { struct expression *tmp; struct sm_state *sm; char buf[256];
*** 194,203 **** --- 268,279 ---- } END_FOR_EACH_SM(sm); return NULL; found: + if (!use_stack && name[tmp->symbol->ident->len] != '-') + return NULL; snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len); *new_sym = sm->sym; return alloc_string(buf); }
*** 222,232 **** len = snprintf(buf, sizeof(buf), "%s", name); if (len >= sizeof(buf) - 2) return NULL; ! while (len >= 1) { if (buf[len] == '>' && buf[len - 1] == '-') { len--; buf[len] = '\0'; ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym); if (ret) --- 298,308 ---- len = snprintf(buf, sizeof(buf), "%s", name); if (len >= sizeof(buf) - 2) return NULL; ! while (use_stack && len >= 1) { if (buf[len] == '>' && buf[len - 1] == '-') { len--; buf[len] = '\0'; ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym); if (ret)
*** 233,243 **** return ret; } len--; } ! ret = get_long_name_sym(name, sym, new_sym); if (ret) return ret; return NULL; } --- 309,319 ---- return ret; } len--; } ! ret = get_long_name_sym(name, sym, new_sym, use_stack); if (ret) return ret; return NULL; }
*** 256,268 **** { char *new_name; struct symbol *new_sym; set_extra_mod_helper(name, sym, expr, state); ! new_name = get_other_name_sym(name, sym, &new_sym); if (new_name && new_sym) ! set_extra_mod_helper(new_name, new_sym, expr, state); free_string(new_name); } static struct expression *chunk_get_array_base(struct expression *expr) { --- 332,344 ---- { char *new_name; struct symbol *new_sym; set_extra_mod_helper(name, sym, expr, state); ! new_name = get_other_name_sym_nostack(name, sym, &new_sym); if (new_name && new_sym) ! set_extra_mod_helper(new_name, new_sym, NULL, state); free_string(new_name); } static struct expression *chunk_get_array_base(struct expression *expr) {
*** 1229,1252 **** static void asm_expr(struct statement *stmt) { struct expression *expr; struct symbol *type; - int state = 0; FOR_EACH_PTR(stmt->asm_outputs, expr) { ! switch (state) { ! case 0: /* identifier */ ! case 1: /* constraint */ ! state++; continue; - case 2: /* expression */ - state = 0; - type = get_type(strip_expr(expr)); - set_extra_expr_mod(expr, alloc_estate_whole(type)); - continue; } } END_FOR_EACH_PTR(expr); } static void check_dereference(struct expression *expr) { --- 1305,1322 ---- static void asm_expr(struct statement *stmt) { struct expression *expr; struct symbol *type; FOR_EACH_PTR(stmt->asm_outputs, expr) { ! if (expr->type != EXPR_ASM_OPERAND) { ! sm_perror("unexpected asm param type %d", expr->type); continue; } + type = get_type(strip_expr(expr->expr)); + set_extra_expr_mod(expr->expr, alloc_estate_whole(type)); } END_FOR_EACH_PTR(expr); } static void check_dereference(struct expression *expr) {
*** 1278,1287 **** --- 1348,1359 ---- static void match_dereferences(struct expression *expr) { if (expr->type != EXPR_PREOP) return; + if (getting_address(expr)) + return; /* it's saying that foo[1] = bar dereferences foo[1] */ if (is_array(expr)) return; check_dereference(expr->unop); }
*** 2201,2211 **** buf[sizeof(buf) - 1] = '\0'; start = &buf[0]; while (*start == '*') { start++; ! state = get_state(SMATCH_EXTRA, start, sym); if (!state) continue; if (!estate_rl(state)) return 1; if (estate_min(state).value == 0 && --- 2273,2283 ---- buf[sizeof(buf) - 1] = '\0'; start = &buf[0]; while (*start == '*') { start++; ! state = __get_state(SMATCH_EXTRA, start, sym); if (!state) continue; if (!estate_rl(state)) return 1; if (estate_min(state).value == 0 &&
*** 2371,2386 **** static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm) { struct range_list *rl; sval_t dummy; ! if (estate_is_whole(sm->state)) return; if (filter_unused_param_value_info(call, param, printed_name, sm)) return; rl = estate_rl(sm->state); rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl); sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl)); if (!estate_get_single_value(sm->state, &dummy)) { if (estate_has_hard_max(sm->state)) sql_insert_caller_info(call, HARD_MAX, param, printed_name, sval_to_str(estate_max(sm->state))); --- 2443,2460 ---- static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm) { struct range_list *rl; sval_t dummy; ! if (estate_is_whole(sm->state) || !estate_rl(sm->state)) return; if (filter_unused_param_value_info(call, param, printed_name, sm)) return; rl = estate_rl(sm->state); rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl); + if (!rl) + return; sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl)); if (!estate_get_single_value(sm->state, &dummy)) { if (estate_has_hard_max(sm->state)) sql_insert_caller_info(call, HARD_MAX, param, printed_name, sval_to_str(estate_max(sm->state)));
*** 2567,2577 **** db_param_limit_filter(expr, param, key, value, PARAM_FILTER); } static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op) { ! struct expression *arg; char *name; char *other_name = NULL; struct symbol *sym, *other_sym; struct symbol *param_type, *arg_type; struct smatch_state *state; --- 2641,2651 ---- db_param_limit_filter(expr, param, key, value, PARAM_FILTER); } static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op) { ! struct expression *arg, *gen_expr; char *name; char *other_name = NULL; struct symbol *sym, *other_sym; struct symbol *param_type, *arg_type; struct smatch_state *state;
*** 2587,2599 **** --- 2661,2676 ---- if (!arg) return; arg_type = get_arg_type_from_key(expr->fn, param, arg, key); param_type = get_member_type_from_key(arg, key); + if (param_type && param_type->type == SYM_STRUCT) + return; name = get_variable_from_key(arg, key, &sym); if (!name || !sym) goto free; + gen_expr = gen_expression_from_key(arg, key); state = get_state(SMATCH_EXTRA, name, sym); if (state) new = estate_rl(state);
*** 2603,2615 **** new = added; else new = rl_union(new, added); other_name = get_other_name_sym_nostack(name, sym, &other_sym); ! set_extra_mod(name, sym, NULL, alloc_estate_rl(new)); if (other_name && other_sym) ! set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new)); free: free_string(other_name); free_string(name); } --- 2680,2692 ---- new = added; else new = rl_union(new, added); other_name = get_other_name_sym_nostack(name, sym, &other_sym); ! set_extra_mod(name, sym, gen_expr, alloc_estate_rl(new)); if (other_name && other_sym) ! set_extra_mod(other_name, other_sym, gen_expr, alloc_estate_rl(new)); free: free_string(other_name); free_string(name); }