2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
19 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
20 struct smatch_state
*s1
,
21 struct smatch_state
*s2
)
23 if (s1
== &ignore
|| s2
== &ignore
)
25 if (s1
== NULL
&& s2
== &nonnull
)
30 static void match_function_call_after(struct expression
*expr
)
32 struct expression
*tmp
;
38 if (expr
->fn
->type
== EXPR_SYMBOL
) {
39 func
= expr
->fn
->symbol_name
->name
;
42 FOR_EACH_PTR(expr
->args
, tmp
) {
43 tmp
= strip_expr(tmp
);
45 name
= get_variable_from_expr_simple(tmp
->unop
, &sym
);
47 name
= alloc_string(name
);
48 set_state(name
, my_id
, sym
, &nonnull
);
51 name
= get_variable_from_expr_simple(tmp
, &sym
);
53 struct smatch_state
*state
= get_state(name
, my_id
, sym
);
54 if ( state
== &isnull
)
55 smatch_msg("Null param %s %d",
57 else if (state
== &undefined
)
58 smatch_msg("Undefined param %s %d",
63 } END_FOR_EACH_PTR(tmp
);
66 static void match_assign(struct expression
*expr
)
68 struct expression
*left
;
72 left
= strip_expr(expr
->left
);
73 name
= get_variable_from_expr_simple(left
, &sym
);
76 name
= alloc_string(name
);
77 if (is_zero(expr
->right
))
78 set_state(name
, my_id
, sym
, &isnull
);
80 set_state(name
, my_id
, sym
, &nonnull
);
84 * set_new_true_false_states is used in the following conditions
85 * if (a) { ... if (a) { ... } }
86 * The problem is that after the second blog a is set to undefined
87 * even though the second condition is meaning less. (The second test
88 * could be a macro for example).
91 static void set_new_true_false_states(const char *name
, int my_id
,
92 struct symbol
*sym
, struct smatch_state
*true_state
,
93 struct smatch_state
*false_state
)
95 struct smatch_state
*tmp
;
97 tmp
= get_state(name
, my_id
, sym
);
99 SM_DEBUG("set_new_stuff called at %d value='%s'\n", get_lineno(), show_state(tmp
));
101 if (!tmp
|| tmp
== &undefined
|| tmp
== &isnull
)
102 set_true_false_states(name
, my_id
, sym
, true_state
, false_state
);
105 static void match_condition(struct expression
*expr
)
113 name
= get_variable_from_expr_simple(expr
, &sym
);
116 name
= alloc_string(name
);
117 set_new_true_false_states(name
, my_id
, sym
, &nonnull
, &isnull
);
119 case EXPR_ASSIGNMENT
:
120 match_condition(expr
->left
);
127 static void match_declarations(struct symbol
*sym
)
131 if ((get_base_type(sym
))->type
== SYM_ARRAY
) {
135 name
= sym
->ident
->name
;
137 if (sym
->initializer
) {
138 if (is_zero(sym
->initializer
))
139 set_state(name
, my_id
, sym
, &isnull
);
141 set_state(name
, my_id
, sym
, &nonnull
);
143 set_state(name
, my_id
, sym
, &undefined
);
147 static void match_dereferences(struct expression
*expr
)
150 struct symbol
*sym
= NULL
;
151 struct smatch_state
*state
;
153 if (strcmp(show_special(expr
->deref
->op
), "*"))
156 deref
= get_variable_from_expr_simple(expr
->deref
->unop
, &sym
);
159 deref
= alloc_string(deref
);
161 state
= get_state(deref
, my_id
, sym
);
162 if (state
== &undefined
) {
163 smatch_msg("Dereferencing Undefined: '%s'", deref
);
164 set_state(deref
, my_id
, sym
, &ignore
);
165 } else if (state
== &isnull
) {
166 /* It turns out that you only get false positives from
167 this. Mostly foo = NULL; sizeof(*foo); */
168 /* smatch_msg("Error dereferencing NULL: %s", deref); */
169 set_state(deref
, my_id
, sym
, &ignore
);
175 void register_null_deref(int id
)
178 add_merge_hook(my_id
, &merge_func
);
179 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
180 add_hook(&match_assign
, ASSIGNMENT_AFTER_HOOK
);
181 add_hook(&match_condition
, CONDITION_HOOK
);
182 add_hook(&match_dereferences
, DEREF_HOOK
);
183 add_hook(&match_declarations
, DECLARATION_HOOK
);