78 }
79
80 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
81 {
82 if (!sym || !sym->ident)
83 return;
84 if (strcmp(name, sym->ident->name) != 0)
85 return;
86 set_state(my_id, name, sym, &initialized);
87 }
88
89 static void match_assign(struct expression *expr)
90 {
91 struct expression *right;
92
93 right = strip_expr(expr->right);
94 if (right->type == EXPR_PREOP && right->op == '&')
95 set_state_expr(my_id, right->unop, &initialized);
96 }
97
98 static int is_initialized(struct expression *expr)
99 {
100 struct sm_state *sm;
101
102 expr = strip_expr(expr);
103 if (expr->type != EXPR_SYMBOL)
104 return 1;
105 sm = get_sm_state_expr(my_id, expr);
106 if (!sm)
107 return 1;
108 if (!slist_has_state(sm->possible, &uninitialized))
109 return 1;
110 return 0;
111 }
112
113 static void match_dereferences(struct expression *expr)
114 {
115 char *name;
116
117 if (parse_error)
118 return;
119
120 if (expr->type != EXPR_PREOP)
121 return;
122 if (is_impossible_path())
123 return;
124 if (is_initialized(expr->unop))
125 return;
126
127 name = expr_to_str(expr->unop);
128 sm_error("potentially dereferencing uninitialized '%s'.", name);
129 free_string(name);
130
131 set_state_expr(my_id, expr->unop, &initialized);
132 }
133
134 static void match_condition(struct expression *expr)
135 {
136 char *name;
137
138 if (parse_error)
139 return;
140
141 if (is_impossible_path())
142 return;
143
144 if (is_initialized(expr))
145 return;
146
147 name = expr_to_str(expr);
148 sm_error("potentially using uninitialized '%s'.", name);
149 free_string(name);
150
151 set_state_expr(my_id, expr, &initialized);
152 }
153
154 static void match_call(struct expression *expr)
155 {
156 struct expression *arg;
157 char *name;
158
248 parent = expr_get_parent_expr(parent);
249 if (!parent)
250 return 0;
251 }
252 if (parent->type == EXPR_PREOP && parent->op == '&')
253 return 1;
254 if (parent->type == EXPR_ASSIGNMENT && expr_equiv(parent->left, expr))
255 return 1;
256
257 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
258 if (stmt && stmt->type == STMT_ASM)
259 return 1;
260
261 return 0;
262 }
263
264 static void match_symbol(struct expression *expr)
265 {
266 char *name;
267
268 if (parse_error)
269 return;
270
271 if (is_impossible_path())
272 return;
273
274 if (is_initialized(expr))
275 return;
276
277 if (is_being_modified(expr))
278 return;
279
280 name = expr_to_str(expr);
281 sm_error("uninitialized symbol '%s'.", name);
282 free_string(name);
283
284 set_state_expr(my_id, expr, &initialized);
285 }
286
287 static void match_untracked(struct expression *call, int param)
288 {
335
336 token = token->next;
337 if (token_type(token) != TOKEN_NUMBER)
338 return;
339 param = atoi(token->number);
340
341 add_function_hook(func, &match_ignore_param, INT_PTR(param));
342
343 token = token->next;
344 }
345 clear_token_alloc();
346 }
347
348 void check_uninitialized(int id)
349 {
350 my_id = id;
351
352 add_hook(&match_declarations, DECLARATION_HOOK);
353 add_extra_mod_hook(&extra_mod_hook);
354 add_hook(&match_assign, ASSIGNMENT_HOOK);
355 add_untracked_param_hook(&match_untracked);
356 add_pre_merge_hook(my_id, &pre_merge_hook);
357
358 add_hook(&match_dereferences, DEREF_HOOK);
359 add_hook(&match_condition, CONDITION_HOOK);
360 add_hook(&match_call, FUNCTION_CALL_HOOK);
361 add_hook(&match_call_struct_members, FUNCTION_CALL_HOOK);
362 add_hook(&match_symbol, SYM_HOOK);
363
364 register_ignored_params_from_file();
365 }
|
78 }
79
80 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
81 {
82 if (!sym || !sym->ident)
83 return;
84 if (strcmp(name, sym->ident->name) != 0)
85 return;
86 set_state(my_id, name, sym, &initialized);
87 }
88
89 static void match_assign(struct expression *expr)
90 {
91 struct expression *right;
92
93 right = strip_expr(expr->right);
94 if (right->type == EXPR_PREOP && right->op == '&')
95 set_state_expr(my_id, right->unop, &initialized);
96 }
97
98 static void match_negative_comparison(struct expression *expr)
99 {
100 struct expression *success;
101 struct sm_state *sm;
102 sval_t max;
103
104 /*
105 * In the kernel, people don't use "if (ret) {" and "if (ret < 0) {"
106 * consistently. Ideally Smatch would know the return but often it
107 * doesn't.
108 *
109 */
110
111 if (option_project != PROJ_KERNEL)
112 return;
113
114 if (expr->type != EXPR_COMPARE || expr->op != '<')
115 return;
116 if (!is_zero(expr->right))
117 return;
118 if (get_implied_max(expr->left, &max) && max.value == 0)
119 return;
120
121 success = compare_expression(expr->left, SPECIAL_EQUAL, expr->right);
122 if (!assume(success))
123 return;
124
125 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
126 if (sm->state == &initialized)
127 set_true_false_states(my_id, sm->name, sm->sym, NULL, &initialized);
128 } END_FOR_EACH_SM(sm);
129
130 end_assume();
131 }
132
133 static int is_initialized(struct expression *expr)
134 {
135 struct sm_state *sm;
136
137 expr = strip_expr(expr);
138 if (expr->type != EXPR_SYMBOL)
139 return 1;
140 sm = get_sm_state_expr(my_id, expr);
141 if (!sm)
142 return 1;
143 if (!slist_has_state(sm->possible, &uninitialized))
144 return 1;
145 return 0;
146 }
147
148 static void match_dereferences(struct expression *expr)
149 {
150 char *name;
151
152 if (implications_off || parse_error)
153 return;
154
155 if (expr->type != EXPR_PREOP)
156 return;
157 if (is_impossible_path())
158 return;
159 if (is_initialized(expr->unop))
160 return;
161
162 name = expr_to_str(expr->unop);
163 sm_error("potentially dereferencing uninitialized '%s'.", name);
164 free_string(name);
165
166 set_state_expr(my_id, expr->unop, &initialized);
167 }
168
169 static void match_condition(struct expression *expr)
170 {
171 char *name;
172
173 if (implications_off || parse_error)
174 return;
175
176 if (is_impossible_path())
177 return;
178
179 if (is_initialized(expr))
180 return;
181
182 name = expr_to_str(expr);
183 sm_error("potentially using uninitialized '%s'.", name);
184 free_string(name);
185
186 set_state_expr(my_id, expr, &initialized);
187 }
188
189 static void match_call(struct expression *expr)
190 {
191 struct expression *arg;
192 char *name;
193
283 parent = expr_get_parent_expr(parent);
284 if (!parent)
285 return 0;
286 }
287 if (parent->type == EXPR_PREOP && parent->op == '&')
288 return 1;
289 if (parent->type == EXPR_ASSIGNMENT && expr_equiv(parent->left, expr))
290 return 1;
291
292 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
293 if (stmt && stmt->type == STMT_ASM)
294 return 1;
295
296 return 0;
297 }
298
299 static void match_symbol(struct expression *expr)
300 {
301 char *name;
302
303 if (implications_off || parse_error)
304 return;
305
306 if (is_impossible_path())
307 return;
308
309 if (is_initialized(expr))
310 return;
311
312 if (is_being_modified(expr))
313 return;
314
315 name = expr_to_str(expr);
316 sm_error("uninitialized symbol '%s'.", name);
317 free_string(name);
318
319 set_state_expr(my_id, expr, &initialized);
320 }
321
322 static void match_untracked(struct expression *call, int param)
323 {
370
371 token = token->next;
372 if (token_type(token) != TOKEN_NUMBER)
373 return;
374 param = atoi(token->number);
375
376 add_function_hook(func, &match_ignore_param, INT_PTR(param));
377
378 token = token->next;
379 }
380 clear_token_alloc();
381 }
382
383 void check_uninitialized(int id)
384 {
385 my_id = id;
386
387 add_hook(&match_declarations, DECLARATION_HOOK);
388 add_extra_mod_hook(&extra_mod_hook);
389 add_hook(&match_assign, ASSIGNMENT_HOOK);
390 add_hook(&match_negative_comparison, CONDITION_HOOK);
391 add_untracked_param_hook(&match_untracked);
392 add_pre_merge_hook(my_id, &pre_merge_hook);
393
394 add_hook(&match_dereferences, DEREF_HOOK);
395 add_hook(&match_condition, CONDITION_HOOK);
396 add_hook(&match_call, FUNCTION_CALL_HOOK);
397 add_hook(&match_call_struct_members, FUNCTION_CALL_HOOK);
398 add_hook(&match_symbol, SYM_HOOK);
399
400 register_ignored_params_from_file();
401 }
|