2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
21 static int merge_func(const char *name
, struct symbol
*sym
, int s1
, int s2
)
28 static void match_function_call_after(struct expression
*expr
)
30 struct expression
*tmp
;
36 if (expr
->fn
->type
== EXPR_SYMBOL
) {
37 func
= expr
->fn
->symbol_name
->name
;
40 FOR_EACH_PTR(expr
->args
, tmp
) {
42 name
= get_variable_from_expr_simple(tmp
->unop
, &sym
);
44 name
= alloc_string(name
);
45 set_state(name
, my_id
, sym
, NONNULL
);
48 name
= get_variable_from_expr_simple(tmp
, &sym
);
50 int state
= get_state(name
, my_id
, sym
);
52 smatch_msg("Null param %s %d",
54 else if (state
== UNDEFINED
)
55 smatch_msg("Undefined param %s %d",
60 } END_FOR_EACH_PTR(tmp
);
63 static int is_null(struct expression
*expr
)
65 if (expr
->type
== EXPR_VALUE
&& expr
->value
== 0)
68 return is_null(expr
->unop
);
69 if (expr
->type
== EXPR_CAST
)
70 return is_null(expr
->cast_expression
);
74 static void match_assign(struct expression
*expr
)
79 name
= get_variable_from_expr_simple(expr
->left
, &sym
);
82 name
= alloc_string(name
);
83 if (is_null(expr
->right
))
84 set_state(name
, my_id
, sym
, ISNULL
);
86 set_state(name
, my_id
, sym
, NONNULL
);
89 static void match_condition(struct expression
*expr
)
91 struct symbol
*sym_left
;
92 struct symbol
*sym_right
;
98 left
= get_variable_from_expr_simple(expr
->left
, &sym_left
);
101 left
= alloc_string(left
);
102 right
= get_variable_from_expr_simple(expr
->right
, &sym_right
);
105 right
= alloc_string(right
);
107 if (is_null(expr
->right
)) {
108 if (expr
->op
== SPECIAL_EQUAL
)
109 set_true_false_states(left
, my_id
, sym_left
,
111 else if (expr
->op
== SPECIAL_NOTEQUAL
)
112 set_true_false_states(left
, my_id
, sym_left
,
118 if (is_null(expr
->left
)) {
119 if (expr
->op
== SPECIAL_EQUAL
)
120 set_true_false_states(right
, my_id
, sym_right
,
122 else if (expr
->op
== SPECIAL_NOTEQUAL
)
123 set_true_false_states(right
, my_id
, sym_right
,
134 left
= get_variable_from_expr_simple(expr
, &sym_left
);
137 left
= alloc_string(left
);
138 set_true_false_states(left
, my_id
, sym_left
, NONNULL
, ISNULL
);
139 SM_DEBUG("set the blasted states\n");
141 case EXPR_ASSIGNMENT
:
142 match_condition(expr
->left
);
149 static void match_declarations(struct symbol
*sym
)
153 name
= sym
->ident
->name
;
154 if (sym
->initializer
&& is_null(sym
->initializer
))
155 set_state(name
, my_id
, sym
, ISNULL
);
159 static int is_array(struct expression
*expr
)
161 struct symbol
*tmp
= NULL
;
164 name
= get_variable_from_expr_simple(expr
, NULL
);
166 tmp
= get_base_type(expr
->ctype
);
169 if (tmp
->type
== SYM_PTR
)
170 tmp
= get_base_type(tmp
);
173 printf("debug: %s %d\n", name
, tmp
->type
);
175 printf("name %s\n", tmp
->ident
->name
);
178 if (expr
->type
!= EXPR_BINOP
|| expr
->op
!= '+')
180 //if (expr->left->ctype && expr->left->ctype.base_type == &ptr_ctype)
185 static void match_dereferences(struct expression
*expr
)
188 struct symbol
*sym
= NULL
;
190 if (expr
->op
== '*') {
192 } else if (expr
->type
== EXPR_DEREF
&& expr
->deref
->op
== '*')
193 expr
= expr
->deref
->unop
;
196 * Say you have foo->bar.baz.n
197 * In that case we really only care about part to the
200 while (expr
->type
== EXPR_DEREF
&& expr
->deref
->op
!= '*')
203 deref
= get_variable_from_expr_simple(expr
, &sym
);
206 deref
= alloc_string(deref
);
208 switch(get_state(deref
, my_id
, sym
)) {
210 smatch_msg("Dereferencing Undefined: %s", deref
);
211 set_state(deref
, my_id
, sym
, IGNORE
);
214 /* It turns out that you only get false positives from
215 this. Mostly foo = NULL; sizeof(*foo); */
216 /* smatch_msg("Error dereferencing NULL: %s", deref); */
217 set_state(deref
, my_id
, sym
, IGNORE
);
225 void register_null_deref(int id
)
228 add_merge_hook(my_id
, &merge_func
);
229 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
230 add_hook(&match_assign
, ASSIGNMENT_AFTER_HOOK
);
231 add_hook(&match_condition
, CONDITION_HOOK
);
232 add_hook(&match_dereferences
, DEREF_HOOK
);
233 add_hook(&match_declarations
, DECLARATION_HOOK
);