If the pointer is initialized to non-null then set the state appropriately.
[smatch.git] / check_null_deref.c
blob7822c8da23247c31099f6614a47b802d1ea57521
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 ISNULL,
17 NONNULL,
18 IGNORE,
21 static int merge_func(const char *name, struct symbol *sym, int s1, int s2)
23 if (s2 == IGNORE)
24 return IGNORE;
25 return UNDEFINED;
28 static void match_function_call_after(struct expression *expr)
30 struct expression *tmp;
31 struct symbol *sym;
32 char *name;
33 char *func = NULL;
34 int i = 0;
36 if (expr->fn->type == EXPR_SYMBOL) {
37 func = expr->fn->symbol_name->name;
40 FOR_EACH_PTR(expr->args, tmp) {
41 if (tmp->op == '&') {
42 name = get_variable_from_expr_simple(tmp->unop, &sym);
43 if (name) {
44 name = alloc_string(name);
45 set_state(name, my_id, sym, NONNULL);
47 } else {
48 name = get_variable_from_expr_simple(tmp, &sym);
49 if (name && sym) {
50 int state = get_state(name, my_id, sym);
51 if ( state == ISNULL)
52 smatch_msg("Null param %s %d",
53 func, i);
54 else if (state == UNDEFINED)
55 smatch_msg("Undefined param %s %d",
56 func, i);
59 i++;
60 } END_FOR_EACH_PTR(tmp);
63 static void match_assign(struct expression *expr)
65 struct symbol *sym;
66 char *name;
68 name = get_variable_from_expr_simple(expr->left, &sym);
69 if (!name)
70 return;
71 name = alloc_string(name);
72 if (is_zero(expr->right))
73 set_state(name, my_id, sym, ISNULL);
74 else
75 set_state(name, my_id, sym, NONNULL);
79 * set_new_true_false_states is used in the following conditions
80 * if (a) { ... if (a) { ... } }
81 * The problem is that after the second blog a is set to undefined
82 * even though the second condition is meaning less. (The second test
83 * could be a macro for example).
86 static void set_new_true_false_states(const char *name, int my_id,
87 struct symbol *sym, int true_state,
88 int false_state)
90 int tmp;
92 tmp = get_state(name, my_id, sym);
94 SM_DEBUG("set_new_stuff called at %d value=%d\n", get_lineno(), tmp);
96 if (tmp == NOTFOUND || tmp == UNDEFINED || tmp == ISNULL)
97 set_true_false_states(name, my_id, sym, true_state, false_state);
100 static void match_condition(struct expression *expr)
102 struct symbol *sym;
103 char *name;
105 switch(expr->type) {
106 case EXPR_SYMBOL:
107 case EXPR_DEREF:
108 name = get_variable_from_expr_simple(expr, &sym);
109 if (!name)
110 return;
111 name = alloc_string(name);
112 set_new_true_false_states(name, my_id, sym, NONNULL, ISNULL);
113 return;
114 case EXPR_ASSIGNMENT:
115 match_condition(expr->left);
116 return;
117 default:
118 return;
122 static void match_declarations(struct symbol *sym)
124 if (sym->ident) {
125 const char * name;
127 name = sym->ident->name;
128 if (sym->initializer) {
129 if (is_zero(sym->initializer))
130 set_state(name, my_id, sym, ISNULL);
131 else
132 set_state(name, my_id, sym, NONNULL);
137 static int is_array(struct expression *expr)
139 struct symbol *tmp = NULL;
140 char *name;
142 name = get_variable_from_expr_simple(expr, NULL);
143 if (expr->ctype)
144 tmp = get_base_type(expr->ctype);
145 if (!tmp || !name)
146 return 0;
147 if (tmp->type == SYM_PTR)
148 tmp = get_base_type(tmp);
149 if (!tmp)
150 return 0;
151 printf("debug: %s %d\n", name, tmp->type);
152 if (tmp->ident)
153 printf("name %s\n", tmp->ident->name);
155 return 0;
156 if (expr->type != EXPR_BINOP || expr->op != '+')
157 return 0;
158 //if (expr->left->ctype && expr->left->ctype.base_type == &ptr_ctype)
159 // return 1;
160 return 0;
163 static void match_dereferences(struct expression *expr)
165 char *deref = NULL;
166 struct symbol *sym = NULL;
168 if (expr->op == '*') {
169 expr = expr->unop;
170 } else if (expr->type == EXPR_DEREF && expr->deref->op == '*')
171 expr = expr->deref->unop;
174 * Say you have foo->bar.baz.n
175 * In that case we really only care about part to the
176 * left of the ->.
178 while (expr->type == EXPR_DEREF && expr->deref->op != '*')
179 expr = expr->deref;
181 deref = get_variable_from_expr_simple(expr, &sym);
182 if (!deref)
183 return;
184 deref = alloc_string(deref);
186 switch(get_state(deref, my_id, sym)) {
187 case UNDEFINED:
188 smatch_msg("Dereferencing Undefined: %s", deref);
189 set_state(deref, my_id, sym, IGNORE);
190 break;
191 case ISNULL:
192 /* It turns out that you only get false positives from
193 this. Mostly foo = NULL; sizeof(*foo); */
194 /* smatch_msg("Error dereferencing NULL: %s", deref); */
195 set_state(deref, my_id, sym, IGNORE);
196 break;
197 default:
198 free_string(deref);
199 break;
203 void register_null_deref(int id)
205 my_id = id;
206 add_merge_hook(my_id, &merge_func);
207 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
208 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
209 add_hook(&match_condition, CONDITION_HOOK);
210 add_hook(&match_dereferences, DEREF_HOOK);
211 add_hook(&match_declarations, DECLARATION_HOOK);