2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
24 ALLOCATOR(param
, "parameters");
26 struct param
*params
[MAX_PARAMS
];
28 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
29 struct smatch_state
*s1
,
30 struct smatch_state
*s2
)
32 if (s1
== &ignore
|| s2
== &ignore
)
39 static struct param
*new_param(struct symbol
*arg
)
43 new = __alloc_param(0);
45 printf("Internal error: Unable to allocate memory in new_param()\n");
53 static void match_function_def(struct symbol
*sym
)
57 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, arg
) {
58 set_state("", my_id
, arg
, &argument
);
59 params
[i
] = new_param(arg
);
61 if (i
>= MAX_PARAMS
- 1) {
62 printf("Error function has too many params.\n");
65 } END_FOR_EACH_PTR(arg
);
69 static void print_unchecked_param(struct symbol
*sym
) {
73 if (params
[i
]->sym
== sym
&& !params
[i
]->used
) {
74 smatch_msg("unchecked param: %s %d", get_function(),
81 static void match_deref(struct expression
*expr
)
84 struct symbol
*sym
= NULL
;
85 struct smatch_state
*state
;
87 deref
= get_variable_from_expr(expr
->deref
, &sym
);
88 state
= get_state("", my_id
, sym
);
89 if (state
== &argument
) {
90 print_unchecked_param(sym
);
91 /* this doesn't actually work because we'll still see
92 the same variable get derefed on other paths */
93 set_state("", my_id
, sym
, &ignore
);
94 } else if (state
== &isnull
)
95 smatch_msg("Error dereferencing NULL: %s", deref
);
98 static void match_function_call_after(struct expression
*expr
)
100 struct expression
*tmp
;
102 struct smatch_state
*state
;
104 FOR_EACH_PTR(expr
->args
, tmp
) {
105 if (tmp
->op
== '&') {
106 get_variable_from_expr(tmp
, &sym
);
107 state
= get_state("", my_id
, sym
);
109 set_state("", my_id
, sym
, &nonnull
);
112 } END_FOR_EACH_PTR(tmp
);
115 static void match_assign(struct expression
*expr
)
117 struct smatch_state
*state
;
119 /* Since we're only tracking arguments, we only want
121 if (expr
->left
->type
!= EXPR_SYMBOL
)
123 state
= get_state("", my_id
, expr
->left
->symbol
);
126 /* probably it's non null */
127 set_state("", my_id
, expr
->left
->symbol
, &nonnull
);
130 static void match_condition(struct expression
*expr
)
134 struct symbol
*sym
= NULL
;
136 if (expr
->left
->type
== EXPR_SYMBOL
) {
137 sym
= expr
->left
->symbol
;
138 if (expr
->right
->type
!= EXPR_VALUE
139 || expr
->right
->value
!= 0)
142 if (expr
->right
->type
== EXPR_SYMBOL
) {
143 sym
= expr
->right
->symbol
;
144 if (expr
->left
->type
!= EXPR_VALUE
145 || expr
->left
->value
!= 0)
151 if (expr
->op
== SPECIAL_EQUAL
)
152 set_true_false_states("", my_id
, sym
, &isnull
,
154 else if (expr
->op
== SPECIAL_NOTEQUAL
)
155 set_true_false_states("", my_id
, sym
, &nonnull
,
160 if (get_state("", my_id
, expr
->symbol
) == &argument
) {
161 set_true_false_states("", my_id
, expr
->symbol
,
170 static void end_of_func_cleanup(struct symbol
*sym
)
175 __free_param(params
[i
]);
180 void register_derefed_params(int id
)
183 add_merge_hook(my_id
, &merge_func
);
184 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
185 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
186 add_hook(&match_deref
, DEREF_HOOK
);
187 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
188 add_hook(&match_condition
, CONDITION_HOOK
);
189 add_hook(&end_of_func_cleanup
, END_FUNC_HOOK
);