2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_slist.h"
15 * TODO: The return_null list of functions should be determined automatically
17 static const char *return_null
[] = {
26 ALLOCATOR(func_n_param
, "func parameters");
27 DECLARE_PTR_LIST(param_list
, struct func_n_param
);
29 static struct param_list
*funcs
;
30 static struct param_list
*do_not_call
;
31 static struct param_list
*calls
;
38 STATE(assumed_nonnull
);
43 static struct symbol
*func_sym
;
46 * merge_func() is to handle assumed_nonnull.
48 * Assumed_nonnull is a funny state. It's almost the same as
49 * no state. Maybe it would be better to delete it completely...
51 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
52 struct smatch_state
*s1
,
53 struct smatch_state
*s2
)
55 if (s1
== &ignore
|| s2
== &ignore
)
61 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
63 if (sm
->state
== &assumed_nonnull
)
64 return &assumed_nonnull
;
68 static int is_maybe_null_no_arg(const char *name
, struct symbol
*sym
)
70 struct state_list
*slist
;
74 slist
= get_possible_states(name
, my_id
, sym
);
75 FOR_EACH_PTR(slist
, tmp
) {
76 if (tmp
->state
== &ignore
)
78 if (tmp
->state
== &isnull
) {
79 SM_DEBUG("is_maybe_null_no_arg() says %s &isnull\n", name
);
82 if (tmp
->state
== &undefined
) {
83 SM_DEBUG("is_maybe_null_no_arg() says %s &undefined\n", name
);
86 } END_FOR_EACH_PTR(tmp
);
91 static int is_maybe_null(const char *name
, struct symbol
*sym
)
93 struct state_list
*slist
;
97 slist
= get_possible_states(name
, my_id
, sym
);
98 FOR_EACH_PTR(slist
, tmp
) {
99 if (tmp
->state
== &ignore
)
101 if (tmp
->state
== &isnull
) {
102 SM_DEBUG("is_maybe_null() says %s &isnull\n", name
);
105 if (tmp
->state
== &undefined
) {
106 SM_DEBUG("is_maybe_null() says %s &undefined\n", name
);
109 if (tmp
->state
== &arg_null
) {
110 SM_DEBUG("is_maybe_null() says %s &arg_null\n", name
);
113 } END_FOR_EACH_PTR(tmp
);
117 static int is_maybe_null_arg(char *name
, struct symbol
*sym
)
119 struct state_list
*slist
;
120 struct sm_state
*tmp
;
123 slist
= get_possible_states(name
, my_id
, sym
);
124 FOR_EACH_PTR(slist
, tmp
) {
125 if (tmp
->state
!= &argument
&& tmp
->state
!= &arg_null
&&
126 tmp
->state
!= &arg_nonnull
&& tmp
->state
!= &merged
&&
127 tmp
->state
!= &assumed_nonnull
)
129 if (tmp
->state
== &argument
|| tmp
->state
== &arg_null
)
131 } END_FOR_EACH_PTR(tmp
);
133 /* We really only care about arguments if they are null */
137 static struct func_n_param
*alloc_func_n_param(struct symbol
*func
, int param
,
140 struct func_n_param
*tmp
= __alloc_func_n_param(0);
148 static int get_arg_num(struct symbol
*sym
)
153 FOR_EACH_PTR(func_sym
->ctype
.base_type
->arguments
, arg
) {
158 } END_FOR_EACH_PTR(arg
);
162 static void add_do_not_call(struct symbol
*sym
, int line
)
164 struct func_n_param
*tmp
;
165 int num
= get_arg_num(sym
);
167 FOR_EACH_PTR(do_not_call
, tmp
) {
168 if (tmp
->func
== func_sym
&& tmp
->param
== num
)
170 } END_FOR_EACH_PTR(tmp
);
171 tmp
= alloc_func_n_param(func_sym
, num
, line
);
172 add_ptr_list(&do_not_call
, tmp
);
175 static void add_param(struct param_list
**list
, struct symbol
*func
, int param
,
178 struct func_n_param
*tmp
;
180 tmp
= alloc_func_n_param(func
, param
, line
);
181 add_ptr_list(list
, tmp
);
184 static void match_function_def(struct symbol
*sym
)
189 add_param(&funcs
, sym
, 0, 0);
190 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, arg
) {
194 set_state(arg
->ident
->name
, my_id
, arg
, &argument
);
195 } END_FOR_EACH_PTR(arg
);
198 static void match_function_call_after(struct expression
*expr
)
200 struct expression
*tmp
;
203 struct symbol
*func
= NULL
;
206 if (expr
->fn
->type
== EXPR_SYMBOL
)
207 func
= expr
->fn
->symbol
;
210 FOR_EACH_PTR(expr
->args
, tmp
) {
211 tmp
= strip_expr(tmp
);
212 if (tmp
->op
== '&') {
213 name
= get_variable_from_expr(tmp
->unop
, &sym
);
215 set_state(name
, my_id
, sym
, &assumed_nonnull
);
219 name
= get_variable_from_expr(tmp
, &sym
);
220 if (name
&& is_maybe_null_no_arg(name
, sym
))
221 add_param(&calls
, func
, i
, get_lineno());
225 } END_FOR_EACH_PTR(tmp
);
228 static void match_assign_returns_null(const char *fn
, struct expression
*expr
,
231 struct expression
*left
;
235 left
= strip_expr(expr
->left
);
236 name
= get_variable_from_expr(left
, &sym
);
239 set_state(name
, my_id
, sym
, &undefined
);
243 static void match_assign(struct expression
*expr
)
245 struct expression
*left
, *right
;
249 left
= strip_expr(expr
->left
);
250 name
= get_variable_from_expr(left
, &sym
);
253 right
= strip_expr(expr
->right
);
254 if (is_zero(right
)) {
255 set_state(name
, my_id
, sym
, &isnull
);
259 /* hack alert. we set the state to here but it might get
260 set later to &undefined in match_function_assign().
261 By default we assume it's assigned something nonnull here. */
262 set_state(name
, my_id
, sym
, &assumed_nonnull
);
267 * set_new_true_false_paths() is used in the following conditions
268 * if (a) { ... if (a) { ... } }
269 * The problem is that after the second blog a is set to undefined
270 * even though the second condition is meaning less. (The second test
271 * could be a macro for example).
273 * Also, stuff passed to the condition hook is processed behind the scenes
274 * a bit. Instead of a condition like (foo == 0) which is true when foo is
275 * null, we get just (foo) and the true and false states are adjusted later.
276 * Basically the important thing to remember, is that for us, true is always
277 * non null and false is always null.
279 static void set_new_true_false_paths(const char *name
, struct symbol
*sym
,
280 int recently_assigned
)
282 struct smatch_state
*tmp
;
284 tmp
= get_state(name
, my_id
, sym
);
286 SM_DEBUG("set_new_stuff called at for %s on line %d value='%s'\n",
287 name
, get_lineno(), show_state(tmp
));
289 if (tmp
== &argument
) {
290 set_true_false_states(name
, my_id
, sym
, &arg_nonnull
, &arg_null
);
294 if (tmp
== &ignore
) {
295 set_true_false_states(name
, my_id
, sym
, &ignore
, &ignore
);
299 if (!tmp
|| recently_assigned
|| is_maybe_null(name
, sym
)) {
300 set_true_false_states(name
, my_id
, sym
, &nonnull
, &isnull
);
305 static void match_var_null_nonnull(struct expression
*expr
,
306 int recently_assigned
)
311 name
= get_variable_from_expr(expr
, &sym
);
314 set_new_true_false_paths(name
, sym
, recently_assigned
);
318 static void match_condition(struct expression
*expr
)
322 expr
= strip_expr(expr
);
327 match_var_null_nonnull(expr
, 0);
329 case EXPR_ASSIGNMENT
:
331 * There is a kernel macro that does
332 * for ( ... ; ... || x = NULL ; ) ...
334 if (is_zero(expr
->right
)) {
335 name
= get_variable_from_expr(expr
->left
, &sym
);
338 set_true_false_states(name
, my_id
, sym
, NULL
, &isnull
);
342 match_var_null_nonnull(expr
->left
, 1);
347 static void match_declarations(struct symbol
*sym
)
351 if ((get_base_type(sym
))->type
== SYM_ARRAY
) {
355 name
= sym
->ident
->name
;
357 if (sym
->initializer
) {
358 if (is_zero(sym
->initializer
)) {
359 set_state(name
, my_id
, sym
, &isnull
);
362 set_state(name
, my_id
, sym
, &assumed_nonnull
);
364 set_state(name
, my_id
, sym
, &undefined
);
368 static void match_dereferences(struct expression
*expr
)
371 struct symbol
*sym
= NULL
;
373 if (strcmp(show_special(expr
->deref
->op
), "*"))
376 deref
= get_variable_from_expr(expr
->deref
->unop
, &sym
);
380 if (is_maybe_null_arg(deref
, sym
)) {
381 add_do_not_call(sym
, get_lineno());
382 set_state(deref
, my_id
, sym
, &assumed_nonnull
);
383 } else if (is_maybe_null(deref
, sym
)) {
384 smatch_msg("error: dereferencing undefined: '%s'", deref
);
385 set_state(deref
, my_id
, sym
, &ignore
);
390 static void end_file_processing(void)
392 struct func_n_param
*param1
, *param2
;
394 // if a function is not static print it out...
395 FOR_EACH_PTR(do_not_call
, param1
) {
396 if (!(param1
->func
->ctype
.modifiers
& MOD_STATIC
))
397 printf("%s +%d info: unchecked param %s %d\n",
398 get_filename(), param1
->line
,
399 param1
->func
->ident
->name
, param1
->param
);
400 } END_FOR_EACH_PTR(param1
);
402 // if there is an error print it out...
403 FOR_EACH_PTR(calls
, param1
) {
404 FOR_EACH_PTR(do_not_call
, param2
) {
405 if (param1
->func
== param2
->func
&&
406 param1
->param
== param2
->param
)
407 printf("%s +%d error: cross_func deref %s %d\n",
408 get_filename(), param1
->line
,
409 param1
->func
->ident
->name
,
411 } END_FOR_EACH_PTR(param2
);
412 } END_FOR_EACH_PTR(param1
);
414 // if someone calls a non-static function print that..
415 FOR_EACH_PTR(calls
, param1
) {
418 FOR_EACH_PTR(funcs
, param2
) {
419 if (param1
->func
== param2
->func
)
421 } END_FOR_EACH_PTR(param2
);
423 printf("%s +%d info: undefined param %s %d\n",
424 get_filename(), param1
->line
,
425 param1
->func
->ident
->name
, param1
->param
);
426 } END_FOR_EACH_PTR(param1
);
429 static void register_allocation_funcs(void)
434 token
= get_tokens_file("kernel.allocation_funcs");
437 if (token_type(token
) != TOKEN_STREAMBEGIN
)
440 while (token_type(token
) != TOKEN_STREAMEND
) {
441 if (token_type(token
) != TOKEN_IDENT
)
443 func
= show_ident(token
->ident
);
444 add_function_assign_hook(func
, &match_assign_returns_null
,
451 void check_null_deref(int id
)
456 add_merge_hook(my_id
, &merge_func
);
457 add_unmatched_state_hook(my_id
, &unmatched_state
);
458 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
459 add_hook(&match_function_call_after
, FUNCTION_CALL_HOOK
);
460 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
461 add_hook(&match_condition
, CONDITION_HOOK
);
462 add_hook(&match_dereferences
, DEREF_HOOK
);
463 add_hook(&match_declarations
, DECLARATION_HOOK
);
464 add_hook(&end_file_processing
, END_FILE_HOOK
);
466 for(i
= 0; i
< sizeof(*return_null
)/sizeof(return_null
[0]); i
++) {
467 add_function_assign_hook(return_null
[i
],
468 &match_assign_returns_null
, NULL
);
470 register_allocation_funcs();