Fix or_slist_stack(). Before it just saved one stack which was bogus.
[smatch.git] / check_null_deref.c
blob3255252013c42089cb32ecb81d92aa225c3b8250
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;
126 name = sym->ident->name;
127 if (sym->initializer && is_zero(sym->initializer))
128 set_state(name, my_id, sym, ISNULL);
132 static int is_array(struct expression *expr)
134 struct symbol *tmp = NULL;
135 char *name;
137 name = get_variable_from_expr_simple(expr, NULL);
138 if (expr->ctype)
139 tmp = get_base_type(expr->ctype);
140 if (!tmp || !name)
141 return 0;
142 if (tmp->type == SYM_PTR)
143 tmp = get_base_type(tmp);
144 if (!tmp)
145 return 0;
146 printf("debug: %s %d\n", name, tmp->type);
147 if (tmp->ident)
148 printf("name %s\n", tmp->ident->name);
150 return 0;
151 if (expr->type != EXPR_BINOP || expr->op != '+')
152 return 0;
153 //if (expr->left->ctype && expr->left->ctype.base_type == &ptr_ctype)
154 // return 1;
155 return 0;
158 static void match_dereferences(struct expression *expr)
160 char *deref = NULL;
161 struct symbol *sym = NULL;
163 if (expr->op == '*') {
164 expr = expr->unop;
165 } else if (expr->type == EXPR_DEREF && expr->deref->op == '*')
166 expr = expr->deref->unop;
169 * Say you have foo->bar.baz.n
170 * In that case we really only care about part to the
171 * left of the ->.
173 while (expr->type == EXPR_DEREF && expr->deref->op != '*')
174 expr = expr->deref;
176 deref = get_variable_from_expr_simple(expr, &sym);
177 if (!deref)
178 return;
179 deref = alloc_string(deref);
181 switch(get_state(deref, my_id, sym)) {
182 case UNDEFINED:
183 smatch_msg("Dereferencing Undefined: %s", deref);
184 set_state(deref, my_id, sym, IGNORE);
185 break;
186 case ISNULL:
187 /* It turns out that you only get false positives from
188 this. Mostly foo = NULL; sizeof(*foo); */
189 /* smatch_msg("Error dereferencing NULL: %s", deref); */
190 set_state(deref, my_id, sym, IGNORE);
191 break;
192 default:
193 free_string(deref);
194 break;
198 void register_null_deref(int id)
200 my_id = id;
201 add_merge_hook(my_id, &merge_func);
202 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
203 add_hook(&match_assign, ASSIGNMENT_AFTER_HOOK);
204 add_hook(&match_condition, CONDITION_HOOK);
205 add_hook(&match_dereferences, DEREF_HOOK);
206 add_hook(&match_declarations, DECLARATION_HOOK);