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);
}