Print this page
new smatch

*** 34,49 **** { if (sm->state != &ok) set_state(my_id, sm->name, sm->sym, &ok); } ! static void pre_merge_hook(struct sm_state *sm) { if (is_impossible_path()) ! set_state(my_id, sm->name, sm->sym, &ok); } static int is_freed(struct expression *expr) { struct sm_state *sm; sm = get_sm_state_expr(my_id, expr); --- 34,66 ---- { if (sm->state != &ok) set_state(my_id, sm->name, sm->sym, &ok); } ! static void pre_merge_hook(struct sm_state *cur, struct sm_state *other) { if (is_impossible_path()) ! set_state(my_id, cur->name, cur->sym, &ok); } + static struct smatch_state *unmatched_state(struct sm_state *sm) + { + struct smatch_state *state; + sval_t sval; + + if (sm->state != &freed) + return &undefined; + + state = get_state(SMATCH_EXTRA, sm->name, sm->sym); + if (!state) + return &undefined; + if (!estate_get_single_value(state, &sval) || sval.value != 0) + return &undefined; + /* It makes it easier to consider NULL pointers as freed. */ + return &freed; + } + static int is_freed(struct expression *expr) { struct sm_state *sm; sm = get_sm_state_expr(my_id, expr);
*** 339,347 **** --- 356,365 ---- add_hook(&match_call, FUNCTION_CALL_HOOK); add_hook(&match_return, RETURN_HOOK); add_modification_hook_late(my_id, &ok_to_use); add_pre_merge_hook(my_id, &pre_merge_hook); + add_unmatched_state_hook(my_id, &unmatched_state); select_return_states_hook(PARAM_FREED, &set_param_freed); add_untracked_param_hook(&match_untracked); }