Update the line number at the very start of the function. Otherwise it was
[smatch.git] / check_null_deref.c
blobc73630ba31176ba05da94c614b4fe8cf68a4f003
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 enum states {
16 ARGUMENT,
17 ISNULL,
18 NONNULL,
19 IGNORE,
22 static void match_function_call_after(struct expression *expr)
24 struct expression *tmp;
25 struct symbol *sym;
26 char *name;
27 char *func = NULL;
28 int i = 0;
30 if (expr->fn->type == EXPR_SYMBOL) {
31 func = expr->fn->symbol_name->name;
34 FOR_EACH_PTR(expr->args, tmp) {
35 if (tmp->op == '&') {
36 name = get_variable_from_expr_simple(tmp->unop, &sym);
37 if (name) {
38 name = alloc_string(name);
39 set_state(name, my_id, sym, NONNULL);
41 } else {
42 name = get_variable_from_expr_simple(tmp, &sym);
43 if (name && sym) {
44 int state = get_state(name, my_id, sym);
45 if ( state == ISNULL)
46 smatch_msg("Null param %s %d",
47 func, i);
48 else if (state == UNDEFINED)
49 smatch_msg("Undefined param %s %d",
50 func, i);
53 i++;
54 } END_FOR_EACH_PTR(tmp);
57 static int is_null(struct expression *expr)
59 if (expr->type == EXPR_VALUE && expr->value == 0)
60 return 1;
61 if (expr->op == '(')
62 return is_null(expr->unop);
63 if (expr->type == EXPR_CAST)
64 return is_null(expr->cast_expression);
65 return 0;
68 static void match_assign(struct expression *expr)
70 struct symbol *sym;
71 char *name;
73 name = get_variable_from_expr_simple(expr->left, &sym);
74 if (!name)
75 return;
76 name = alloc_string(name);
77 if (is_null(expr->right))
78 set_state(name, my_id, sym, ISNULL);
79 else
80 set_state(name, my_id, sym, NONNULL);
83 static void match_condition(struct expression *expr)
85 struct symbol *sym_left;
86 struct symbol *sym_right;
87 char *left;
88 char *right;
90 switch(expr->type) {
91 case EXPR_COMPARE:
92 left = get_variable_from_expr_simple(expr->left, &sym_left);
93 if (!left)
94 return;
95 left = alloc_string(left);
96 right = get_variable_from_expr_simple(expr->right, &sym_right);
97 if (!right)
98 return;
99 right = alloc_string(right);
101 if (is_null(expr->right)) {
102 if (expr->op == SPECIAL_EQUAL)
103 set_true_false_states(left, my_id, sym_left,
104 ISNULL, NONNULL);
105 else if (expr->op == SPECIAL_NOTEQUAL)
106 set_true_false_states(left, my_id, sym_left,
107 NONNULL, ISNULL);
108 free_string(right);
109 return;
112 if (is_null(expr->left)) {
113 if (expr->op == SPECIAL_EQUAL)
114 set_true_false_states(right, my_id, sym_right,
115 ISNULL, NONNULL);
116 else if (expr->op == SPECIAL_NOTEQUAL)
117 set_true_false_states(right, my_id, sym_right,
118 NONNULL, ISNULL);
119 free_string(left);
120 return;
123 free_string(left);
124 free_string(right);
125 return;
126 case EXPR_SYMBOL:
127 case EXPR_DEREF:
128 left = get_variable_from_expr_simple(expr, &sym_left);
129 if (!left)
130 return;
131 left = alloc_string(left);
132 set_true_false_states(left, my_id, sym_left, NONNULL, ISNULL);
133 return;
134 case EXPR_ASSIGNMENT:
135 match_condition(expr->left);
136 return;
137 default:
138 return;
142 static void match_declarations(struct symbol *sym)
144 if (sym->ident) {
145 const char * name;
146 name = sym->ident->name;
147 if (sym->initializer && is_null(sym->initializer))
148 set_state(name, my_id, sym, ISNULL);
152 static int is_array(struct expression *expr)
154 struct symbol *tmp = NULL;
155 char *name;
157 name = get_variable_from_expr_simple(expr, NULL);
158 if (expr->ctype)
159 tmp = get_base_type(expr->ctype);
160 if (!tmp || !name)
161 return 0;
162 if (tmp->type == SYM_PTR)
163 tmp = get_base_type(tmp);
164 if (!tmp)
165 return 0;
166 printf("debug: %s %d\n", name, tmp->type);
167 if (tmp->ident)
168 printf("name %s\n", tmp->ident->name);
170 return 0;
171 if (expr->type != EXPR_BINOP || expr->op != '+')
172 return 0;
173 //if (expr->left->ctype && expr->left->ctype.base_type == &ptr_ctype)
174 // return 1;
175 return 0;
178 static void match_dereferences(struct expression *expr)
180 char *deref = NULL;
181 struct symbol *sym = NULL;
183 if (expr->op == '*') {
184 expr = expr->unop;
185 } else if (expr->type == EXPR_DEREF && expr->deref->op == '*')
186 expr = expr->deref->unop;
189 * Say you have foo->bar.baz.n
190 * In that case we really only care about part to the
191 * left of the ->.
193 while (expr->type == EXPR_DEREF && expr->deref->op != '*')
194 expr = expr->deref;
196 deref = get_variable_from_expr_simple(expr, &sym);
197 if (!deref)
198 return;
199 deref = alloc_string(deref);
201 switch(get_state(deref, my_id, sym)) {
202 case UNDEFINED:
203 smatch_msg("Dereferencing Undefined: %s", deref);
204 set_state(deref, my_id, sym, IGNORE);
205 break;
206 case ISNULL:
207 /* It turns out that you only get false positives from
208 this. Mostly foo = NULL; sizeof(*foo); */
209 /* smatch_msg("Error dereferencing NULL: %s", deref); */
210 set_state(deref, my_id, sym, IGNORE);
211 break;
212 default:
213 free_string(deref);
214 break;
218 void register_null_deref(int id)
220 my_id = id;
221 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
222 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
223 add_hook(&match_condition, CONDITION_HOOK);
224 add_hook(&match_dereferences, DEREF_HOOK);
225 add_hook(&match_declarations, DECLARATION_HOOK);