2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
14 * TODO: The return_null list of functions should be determined automatically
16 const char *return_null
[] = {
25 ALLOCATOR(func_n_param
, "func parameters");
26 DECLARE_PTR_LIST(param_list
, struct func_n_param
);
28 static struct param_list
*funcs
;
29 static struct param_list
*do_not_call
;
30 static struct param_list
*calls
;
35 STATE(assumed_nonnull
);
40 static struct symbol
*func_sym
;
42 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
43 struct smatch_state
*s1
,
44 struct smatch_state
*s2
)
47 * conditions are a special case. In the cond_(true|false)_stack
48 * we expect to be merging null with a new specified state all the
49 * time. Outside of a condition we have things where the code
50 * assumes a global variable is non null. That gets merged with
51 * other code and it becomes undefined. But really it should be
53 * In theory we could test for that latter case by printing a message
54 * when someone checks a variable we already had marked as non-null.
55 * In practise that didn't work really well because a lot of macros
56 * have "unneeded" checks for null.
58 if (!in_condition() && s1
== NULL
)
60 if (s1
== &ignore
|| s2
== &ignore
)
62 if (s1
== NULL
&& s2
== &assumed_nonnull
)
63 return &assumed_nonnull
;
64 if (s1
== &assumed_nonnull
&& s2
== &nonnull
)
65 return &assumed_nonnull
;
66 if (s1
== &argument
&& s2
== &assumed_nonnull
)
67 return &assumed_nonnull
;
68 if (s1
== &argument
&& s2
== &nonnull
)
73 static struct func_n_param
*alloc_func_n_param(struct symbol
*func
, int param
,
76 struct func_n_param
*tmp
= __alloc_func_n_param(0);
84 static int get_arg_num(struct symbol
*sym
)
89 FOR_EACH_PTR(func_sym
->ctype
.base_type
->arguments
, arg
) {
94 } END_FOR_EACH_PTR(arg
);
98 static void add_do_not_call(struct symbol
*sym
, int line
)
100 struct func_n_param
*tmp
;
101 int num
= get_arg_num(sym
);
103 FOR_EACH_PTR(do_not_call
, tmp
) {
104 if (tmp
->func
== func_sym
&& tmp
->param
== num
)
106 } END_FOR_EACH_PTR(tmp
);
107 tmp
= alloc_func_n_param(func_sym
, num
, line
);
108 add_ptr_list(&do_not_call
, tmp
);
111 static void add_param(struct param_list
**list
, struct symbol
*func
, int param
,
114 struct func_n_param
*tmp
;
116 tmp
= alloc_func_n_param(func
, param
, line
);
117 add_ptr_list(list
, tmp
);
120 static void match_function_def(struct symbol
*sym
)
125 add_param(&funcs
, sym
, 0, 0);
126 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, arg
) {
130 set_state(arg
->ident
->name
, my_id
, arg
, &argument
);
131 } END_FOR_EACH_PTR(arg
);
134 static void match_function_call_after(struct expression
*expr
)
136 struct expression
*tmp
;
139 struct symbol
*func
= NULL
;
142 if (expr
->fn
->type
== EXPR_SYMBOL
) {
143 func
= expr
->fn
->symbol
;
147 FOR_EACH_PTR(expr
->args
, tmp
) {
148 tmp
= strip_expr(tmp
);
149 if (tmp
->op
== '&') {
150 name
= get_variable_from_expr(tmp
->unop
, &sym
);
152 set_state(name
, my_id
, sym
, &assumed_nonnull
);
155 name
= get_variable_from_expr(tmp
, &sym
);
156 if (func
&& name
&& sym
) {
157 if (get_state(name
, my_id
, sym
) == &undefined
)
158 add_param(&calls
, func
, i
, get_lineno());
164 } END_FOR_EACH_PTR(tmp
);
167 static char *get_function_call(struct expression
*expr
)
169 if (expr
->type
!= EXPR_CALL
)
171 if (expr
->fn
->type
== EXPR_SYMBOL
&& expr
->fn
->symbol
)
172 return expr
->fn
->symbol
->ident
->name
;
176 static int check_null_returns(const char *name
, struct symbol
*sym
,
177 struct expression
*right
)
182 func_name
= get_function_call(right
);
186 for(i
= 0; i
< sizeof(*return_null
)/sizeof(return_null
[0]); i
++) {
187 if (!strcmp(func_name
,return_null
[i
])) {
188 set_state(name
, my_id
, sym
, &undefined
);
195 static int assign_seen
;
196 static void match_assign(struct expression
*expr
)
198 struct expression
*left
, *right
;
206 left
= strip_expr(expr
->left
);
207 name
= get_variable_from_expr(left
, &sym
);
210 right
= strip_expr(expr
->right
);
211 if (is_zero(right
)) {
212 set_state(name
, my_id
, sym
, &isnull
);
215 if (check_null_returns(name
, sym
, right
))
218 /* by default we assume it's assigned something nonnull */
219 set_state(name
, my_id
, sym
, &assumed_nonnull
);
223 * set_new_true_false_states is used in the following conditions
224 * if (a) { ... if (a) { ... } }
225 * The problem is that after the second blog a is set to undefined
226 * even though the second condition is meaning less. (The second test
227 * could be a macro for example).
230 static void set_new_true_false_states(const char *name
, int my_id
,
231 struct symbol
*sym
, struct smatch_state
*true_state
,
232 struct smatch_state
*false_state
)
234 struct smatch_state
*tmp
;
236 tmp
= get_state(name
, my_id
, sym
);
238 SM_DEBUG("set_new_stuff called at %d value='%s'\n", get_lineno(), show_state(tmp
));
240 if (!tmp
|| tmp
== &undefined
|| tmp
== &isnull
|| tmp
== &argument
)
241 set_true_false_states(name
, my_id
, sym
, true_state
, false_state
);
244 static void match_condition(struct expression
*expr
)
249 expr
= strip_expr(expr
);
254 name
= get_variable_from_expr(expr
, &sym
);
257 set_new_true_false_states(name
, my_id
, sym
, &nonnull
, &isnull
);
259 case EXPR_ASSIGNMENT
:
262 * There is a kernel macro that does
263 * for ( ... ; ... || x = NULL ; ) ...
265 if (is_zero(expr
->right
)) {
266 name
= get_variable_from_expr(expr
->left
, &sym
);
269 set_new_true_false_states(name
, my_id
, sym
, NULL
, &isnull
);
272 /* You have to deal with stuff like if (a = b = c) */
273 match_condition(expr
->right
);
274 match_condition(expr
->left
);
281 static void match_declarations(struct symbol
*sym
)
285 if ((get_base_type(sym
))->type
== SYM_ARRAY
) {
289 name
= sym
->ident
->name
;
291 if (sym
->initializer
) {
292 if (is_zero(sym
->initializer
)) {
293 set_state(name
, my_id
, sym
, &isnull
);
296 if (check_null_returns(name
, sym
, strip_expr(sym
->initializer
)))
298 set_state(name
, my_id
, sym
, &assumed_nonnull
);
300 set_state(name
, my_id
, sym
, &undefined
);
304 static void match_dereferences(struct expression
*expr
)
307 struct symbol
*sym
= NULL
;
308 struct smatch_state
*state
;
310 if (strcmp(show_special(expr
->deref
->op
), "*"))
313 deref
= get_variable_from_expr(expr
->deref
->unop
, &sym
);
317 state
= get_state(deref
, my_id
, sym
);
318 if (state
== &undefined
) {
319 smatch_msg("Dereferencing Undefined: '%s'", deref
);
320 set_state(deref
, my_id
, sym
, &ignore
);
321 } else if (state
== &isnull
) {
323 * It turns out that you only get false positives from
324 * this. Mostly foo = NULL; sizeof(*foo);
325 * And even if it wasn't always a false positive you'd think
326 * it would get caught in testing if it failed every time.
328 set_state(deref
, my_id
, sym
, &ignore
);
329 } else if (state
== &argument
) {
330 add_do_not_call(sym
, get_lineno());
331 set_state(deref
, my_id
, sym
, &assumed_nonnull
);
337 static void end_file_processing()
339 struct func_n_param
*param1
, *param2
;
341 // if a function is not static print it out...
342 FOR_EACH_PTR(do_not_call
, param1
) {
343 if (!(param1
->func
->ctype
.modifiers
& MOD_STATIC
))
344 printf("%s +%d unchecked param %s %d\n",
345 get_filename(), param1
->line
,
346 param1
->func
->ident
->name
, param1
->param
);
347 } END_FOR_EACH_PTR(param1
);
349 // if there is an error print it out...
350 FOR_EACH_PTR(calls
, param1
) {
351 FOR_EACH_PTR(do_not_call
, param2
) {
352 if (param1
->func
== param2
->func
&&
353 param1
->param
== param2
->param
)
354 printf("%s +%d cross_func deref %s %d\n",
355 get_filename(), param1
->line
,
356 param1
->func
->ident
->name
,
358 } END_FOR_EACH_PTR(param2
);
359 } END_FOR_EACH_PTR(param1
);
361 // if someone calls a non-static function print that..
362 FOR_EACH_PTR(calls
, param1
) {
365 FOR_EACH_PTR(funcs
, param2
) {
366 if (param1
->func
== param2
->func
)
368 } END_FOR_EACH_PTR(param2
);
370 printf("%s +%d undefined param %s %d\n", get_filename(),
371 param1
->line
, param1
->func
->ident
->name
,
373 } END_FOR_EACH_PTR(param1
);
376 void register_null_deref(int id
)
379 add_merge_hook(my_id
, &merge_func
);
380 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
381 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
382 add_hook(&match_assign
, ASSIGNMENT_AFTER_HOOK
);
383 add_hook(&match_condition
, CONDITION_HOOK
);
384 add_hook(&match_dereferences
, DEREF_HOOK
);
385 add_hook(&match_declarations
, DECLARATION_HOOK
);
386 add_hook(&end_file_processing
, END_FILE_HOOK
);