Update the line number at the very start of the function. Otherwise it was
[smatch.git] / check_derefed_params.c
blobc09a9d95486d009fdc9fee436daae8fe2d077286
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 struct param {
23 struct symbol *sym;
24 int used;
26 ALLOCATOR(param, "parameters");
27 #define MAX_PARAMS 16
28 struct param *params[MAX_PARAMS];
30 static struct param *new_param(struct symbol *arg)
32 struct param *new;
34 new = __alloc_param(0);
35 if (!new) {
36 printf("Internal error: Unable to allocate memory in new_param()\n");
37 exit(1);
39 new->sym = arg;
40 new->used = 0;
41 return new;
44 static void match_function_def(struct symbol *sym)
46 struct symbol *arg;
47 int i = 0;
48 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
49 set_state("", my_id, arg, ARGUMENT);
50 params[i] = new_param(arg);
51 i++;
52 if (i >= MAX_PARAMS - 1) {
53 printf("Error function has too many params.\n");
54 break;
56 } END_FOR_EACH_PTR(arg);
57 params[i] = NULL;
60 static void print_unchecked_param(struct symbol *sym) {
61 int i = 0;
63 while (params[i]) {
64 if (params[i]->sym == sym && !params[i]->used) {
65 smatch_msg("unchecked param: %s %d", get_function(),
66 i);
68 i++;
72 static void match_deref(struct expression *expr)
74 char *deref = NULL;
75 struct symbol *sym = NULL;
77 deref = get_variable_from_expr(expr->deref, &sym);
78 switch(get_state("", my_id, sym)) {
79 case ARGUMENT:
80 print_unchecked_param(sym);
81 /* this doesn't actually work because we'll still see
82 the same variable get derefed on other paths */
83 set_state("", my_id, sym, IGNORE);
84 break;
85 case ISNULL:
86 smatch_msg("Error dereferencing NULL: %s", deref);
87 break;
88 default:
89 break;
93 static void match_function_call_after(struct expression *expr)
95 struct expression *tmp;
96 struct symbol *sym;
97 int state;
99 FOR_EACH_PTR(expr->args, tmp) {
100 if (tmp->op == '&') {
101 get_variable_from_expr(tmp, &sym);
102 state = get_state("", my_id, sym);
103 if (state != NOTFOUND) {
104 set_state("", my_id, sym, NONNULL);
107 } END_FOR_EACH_PTR(tmp);
110 static void match_assign(struct expression *expr)
112 int state;
114 /* Since we're only tracking arguments, we only want
115 EXPR_SYMBOLs. */
116 if (expr->left->type != EXPR_SYMBOL)
117 return;
118 state = get_state("", my_id, expr->left->symbol);
119 if (state == NOTFOUND)
120 return;
121 /* probably it's non null */
122 set_state("", my_id, expr->left->symbol, NONNULL);
125 static void match_condition(struct expression *expr)
127 switch(expr->type) {
128 case EXPR_COMPARE: {
129 struct symbol *sym = NULL;
131 if (expr->left->type == EXPR_SYMBOL) {
132 sym = expr->left->symbol;
133 if (expr->right->type != EXPR_VALUE
134 || expr->right->value != 0)
135 return;
137 if (expr->right->type == EXPR_SYMBOL) {
138 sym = expr->right->symbol;
139 if (expr->left->type != EXPR_VALUE
140 || expr->left->value != 0)
141 return;
143 if (!sym)
144 return;
146 if (expr->op == SPECIAL_EQUAL)
147 set_true_false_states("", my_id, sym, ISNULL,
148 NONNULL);
149 else if (expr->op == SPECIAL_NOTEQUAL)
150 set_true_false_states("", my_id, sym, NONNULL,
151 ISNULL);
152 return;
154 case EXPR_SYMBOL:
155 if (get_state("", my_id, expr->symbol) == ARGUMENT) {
156 set_true_false_states("", my_id, expr->symbol,
157 NONNULL, ISNULL);
159 return;
160 default:
161 return;
165 static void end_of_func_cleanup(struct symbol *sym)
167 int i = 0;
169 while (params[i]) {
170 __free_param(params[i]);
171 i++;
175 void register_derefed_params(int id)
177 my_id = id;
178 add_hook(&match_function_def, FUNC_DEF_HOOK);
179 add_hook(&match_function_call_after, FUNCTION_CALL_AFTER_HOOK);
180 add_hook(&match_deref, DEREF_HOOK);
181 add_hook(&match_assign, ASSIGNMENT_HOOK);
182 add_hook(&match_condition, CONDITION_HOOK);
183 add_hook(&end_of_func_cleanup, END_FUNC_HOOK);