Missed a crashing bug in the int => struct conversion.
[smatch.git] / check_derefed_params.c
blob8b7f71ef4a7f8b19c472831d4a2f6d08ab485098
1 /*
2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "token.h"
11 #include "smatch.h"
13 static int my_id;
15 STATE(argument);
16 STATE(ignore);
17 STATE(isnull);
18 STATE(nonnull);
20 struct param {
21 struct symbol *sym;
22 int used;
24 ALLOCATOR(param, "parameters");
25 #define MAX_PARAMS 16
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)
33 return &ignore;
34 if (s1 == &argument)
35 return s2;
36 return &undefined;
39 static struct param *new_param(struct symbol *arg)
41 struct param *new;
43 new = __alloc_param(0);
44 if (!new) {
45 printf("Internal error: Unable to allocate memory in new_param()\n");
46 exit(1);
48 new->sym = arg;
49 new->used = 0;
50 return new;
53 static void match_function_def(struct symbol *sym)
55 struct symbol *arg;
56 int i = 0;
57 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
58 set_state("", my_id, arg, &argument);
59 params[i] = new_param(arg);
60 i++;
61 if (i >= MAX_PARAMS - 1) {
62 printf("Error function has too many params.\n");
63 break;
65 } END_FOR_EACH_PTR(arg);
66 params[i] = NULL;
69 static void print_unchecked_param(struct symbol *sym) {
70 int i = 0;
72 while (params[i]) {
73 if (params[i]->sym == sym && !params[i]->used) {
74 smatch_msg("unchecked param: %s %d", get_function(),
75 i);
77 i++;
81 static void match_deref(struct expression *expr)
83 char *deref = NULL;
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;
101 struct symbol *sym;
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);
108 if (state) {
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
120 EXPR_SYMBOLs. */
121 if (expr->left->type != EXPR_SYMBOL)
122 return;
123 state = get_state("", my_id, expr->left->symbol);
124 if (!state)
125 return;
126 /* probably it's non null */
127 set_state("", my_id, expr->left->symbol, &nonnull);
130 static void match_condition(struct expression *expr)
132 switch(expr->type) {
133 case EXPR_COMPARE: {
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)
140 return;
142 if (expr->right->type == EXPR_SYMBOL) {
143 sym = expr->right->symbol;
144 if (expr->left->type != EXPR_VALUE
145 || expr->left->value != 0)
146 return;
148 if (!sym)
149 return;
151 if (expr->op == SPECIAL_EQUAL)
152 set_true_false_states("", my_id, sym, &isnull,
153 &nonnull);
154 else if (expr->op == SPECIAL_NOTEQUAL)
155 set_true_false_states("", my_id, sym, &nonnull,
156 &isnull);
157 return;
159 case EXPR_SYMBOL:
160 if (get_state("", my_id, expr->symbol) == &argument) {
161 set_true_false_states("", my_id, expr->symbol,
162 &nonnull, &isnull);
164 return;
165 default:
166 return;
170 static void end_of_func_cleanup(struct symbol *sym)
172 int i = 0;
174 while (params[i]) {
175 __free_param(params[i]);
176 i++;
180 void register_derefed_params(int id)
182 my_id = 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);