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 if (strcmp(show_special(expr
->deref
->op
), "*"))
90 deref
= get_variable_from_expr_simple(expr
->deref
->unop
, &sym
);
93 state
= get_state("", my_id
, sym
);
94 if (state
== &argument
) {
95 print_unchecked_param(sym
);
96 /* this doesn't actually work because we'll still see
97 the same variable get derefed on other paths */
98 set_state("", my_id
, sym
, &ignore
);
99 } else if (state
== &isnull
)
100 smatch_msg("Error dereferencing NULL: %s", deref
);
103 static void match_function_call_after(struct expression
*expr
)
105 struct expression
*tmp
;
107 struct smatch_state
*state
;
109 FOR_EACH_PTR(expr
->args
, tmp
) {
110 if (tmp
->op
== '&') {
111 get_variable_from_expr(tmp
, &sym
);
112 state
= get_state("", my_id
, sym
);
114 set_state("", my_id
, sym
, &nonnull
);
117 } END_FOR_EACH_PTR(tmp
);
120 static void match_assign(struct expression
*expr
)
122 struct smatch_state
*state
;
124 /* Since we're only tracking arguments, we only want
126 if (expr
->left
->type
!= EXPR_SYMBOL
)
128 state
= get_state("", my_id
, expr
->left
->symbol
);
131 /* probably it's non null */
132 set_state("", my_id
, expr
->left
->symbol
, &nonnull
);
135 static void match_condition(struct expression
*expr
)
139 struct symbol
*sym
= NULL
;
141 if (expr
->left
->type
== EXPR_SYMBOL
) {
142 sym
= expr
->left
->symbol
;
143 if (expr
->right
->type
!= EXPR_VALUE
144 || expr
->right
->value
!= 0)
147 if (expr
->right
->type
== EXPR_SYMBOL
) {
148 sym
= expr
->right
->symbol
;
149 if (expr
->left
->type
!= EXPR_VALUE
150 || expr
->left
->value
!= 0)
156 if (expr
->op
== SPECIAL_EQUAL
)
157 set_true_false_states("", my_id
, sym
, &isnull
,
159 else if (expr
->op
== SPECIAL_NOTEQUAL
)
160 set_true_false_states("", my_id
, sym
, &nonnull
,
165 if (get_state("", my_id
, expr
->symbol
) == &argument
) {
166 set_true_false_states("", my_id
, expr
->symbol
,
175 static void end_of_func_cleanup(struct symbol
*sym
)
180 __free_param(params
[i
]);
185 void register_derefed_params(int id
)
188 add_merge_hook(my_id
, &merge_func
);
189 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
190 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
191 add_hook(&match_deref
, DEREF_HOOK
);
192 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
193 add_hook(&match_condition
, CONDITION_HOOK
);
194 add_hook(&end_of_func_cleanup
, END_FUNC_HOOK
);