2 * sparse/check_string_ret.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
16 int __smatch_lineno
= 0;
21 static char *filename
;
22 static char *cur_func
;
23 static int line_func_start
;
24 static unsigned int path_id
= 0;
25 static unsigned int path_id_next
= 1;
27 char *get_filename() { return filename
; }
28 char *get_function() { return cur_func
; }
29 int get_lineno() { return __smatch_lineno
; }
30 int get_func_pos() { return __smatch_lineno
- line_func_start
; }
32 static void split_statements(struct statement
*stmt
);
33 static void split_symlist(struct symbol_list
*sym_list
);
34 static void split_expr_list(struct expression_list
*expr_list
);
35 static void split_expr(struct expression
*expr
);
37 unsigned int get_path_id()
42 static unsigned int split_path_id()
46 path_id
= path_id_next
++;
50 static void restore_path_id(int old_id
)
56 static int is_logical_and(struct expression
*expr
)
58 /* If you have if (!(a && b)) smatch translates that to
59 * if (!a || !b). Logically those are the same.
62 if ((!__negate
&& expr
->op
== SPECIAL_LOGICAL_AND
) ||
63 (__negate
&& expr
->op
== SPECIAL_LOGICAL_OR
))
68 static int is_logical_or(struct expression
*expr
)
70 if ((!__negate
&& expr
->op
== SPECIAL_LOGICAL_OR
) ||
71 (__negate
&& expr
->op
== SPECIAL_LOGICAL_AND
))
76 static void inc_ands_ors(struct expression
*expr
)
78 if (is_logical_and(expr
))
80 else if (is_logical_or(expr
))
84 static void dec_ands_ors(struct expression
*expr
)
86 if (is_logical_and(expr
))
88 else if (is_logical_or(expr
))
92 void split_conditions(struct expression
*expr
)
95 * If you have if ((a || a = foo()), we know a is
96 * non-null on the true state because 'a' is checked in both and
97 * groups. __ors_reached helps with that. Unfortunately
98 * smatch doesn't handle stuff like if (a && a = foo())
99 * because it never occured to me that people would do that...
102 static int __ors_reached
;
104 if (expr
->type
== EXPR_LOGICAL
) {
105 unsigned int path_orig
;
108 path_orig
= split_path_id();
109 __split_false_states_mini();
111 split_conditions(expr
->left
);
113 if (is_logical_and(expr
)) {
115 __pop_false_states_mini();
116 split_conditions(expr
->right
);
117 } else if (is_logical_or(expr
)) {
118 if (!__ors_reached
) {
125 __use_false_states_mini();
126 split_conditions(expr
->right
);
130 if (__ands
+ __ors
== 0) {
136 restore_path_id(path_orig
);
138 } else if (expr
->type
== EXPR_PREOP
&& expr
->op
== '!') {
139 __negate
= (__negate
+ 1)%2;
140 split_conditions(expr
->unop
);
141 __negate
= (__negate
+ 1)%2;
143 } else if (expr
->type
== EXPR_PREOP
&& expr
->op
== '(') {
144 split_conditions(expr
->unop
);
146 } else if (expr
->type
== EXPR_CALL
) {
147 struct expression
*arg
;
149 if (expr
->fn
->type
!= EXPR_SYMBOL
||
150 strcmp("__builtin_expect", expr
->fn
->symbol_name
->name
)) {
151 __pass_to_client(expr
, CONDITION_HOOK
);
155 arg
= first_ptr_list((struct ptr_list
*) expr
->args
);
156 if (arg
->op
== '!' && arg
->unop
->op
== '!'
157 && arg
->unop
->unop
->op
== '(')
158 split_conditions(arg
->unop
->unop
->unop
);
160 __pass_to_client(expr
, CONDITION_HOOK
);
166 __pass_to_client(expr
, CONDITION_HOOK
);
171 static void split_expr(struct expression
*expr
)
176 __smatch_lineno
= expr
->pos
.line
;
177 __pass_to_client(expr
, EXPR_HOOK
);
179 //printf("Debug expr_type %d\n", expr->type);
181 switch (expr
->type
) {
185 __pass_to_client(expr
, DEREF_HOOK
);
186 split_expr(expr
->unop
);
189 split_statements(expr
->statement
);
195 case EXPR_ASSIGNMENT
:
196 if (expr
->type
== EXPR_ASSIGNMENT
)
197 __pass_to_client(expr
, ASSIGNMENT_HOOK
);
198 split_expr(expr
->left
);
199 split_expr(expr
->right
);
200 if (expr
->type
== EXPR_ASSIGNMENT
)
201 __pass_to_client(expr
, ASSIGNMENT_AFTER_HOOK
);
204 __pass_to_client(expr
, DEREF_HOOK
);
205 split_expr(expr
->deref
);
208 split_expr(expr
->base
);
212 split_expr(expr
->cast_expression
);
214 case EXPR_CONDITIONAL
:
216 __split_true_false_paths();
217 __pass_to_client(expr
->conditional
, WHOLE_CONDITION_HOOK
);
218 split_conditions(expr
->conditional
);
220 split_expr(expr
->cond_true
);
221 __use_false_states();
222 split_expr(expr
->cond_false
);
223 __merge_true_states();
226 __pass_to_client(expr
, FUNCTION_CALL_HOOK
);
227 split_expr(expr
->fn
);
228 split_expr_list(expr
->args
);
229 __pass_to_client(expr
, FUNCTION_CALL_AFTER_HOOK
);
231 if (expr
->fn
->type
== EXPR_SYMBOL
&&
232 !strcmp(expr
->fn
->symbol_name
->name
, "panic"))
236 case EXPR_INITIALIZER
:
237 split_expr_list(expr
->expr_list
);
239 case EXPR_IDENTIFIER
:
240 split_expr(expr
->ident_expression
);
243 split_expr(expr
->idx_expression
);
246 split_expr(expr
->init_expr
);
253 static int is_forever_loop(struct expression
*expr
)
256 if (expr
->type
== EXPR_VALUE
&& expr
->value
== 1) {
263 * Pre Loops are while and for loops.
266 static void handle_pre_loop(struct statement
*stmt
)
268 unsigned int path_orig
;
270 split_statements(stmt
->iterator_pre_statement
);
272 __split_true_false_paths();
275 __pass_to_client(stmt
->iterator_pre_condition
, WHOLE_CONDITION_HOOK
);
276 split_conditions(stmt
->iterator_pre_condition
);
277 path_orig
= split_path_id();
280 split_statements(stmt
->iterator_statement
);
281 split_statements(stmt
->iterator_post_statement
);
282 if (is_forever_loop(stmt
->iterator_pre_condition
)) {
284 __pop_false_states();
288 __merge_false_states();
292 restore_path_id(path_orig
);
296 * Post loops are do {} while();
298 static void handle_post_loop(struct statement
*stmt
)
302 split_statements(stmt
->iterator_statement
);
304 __split_true_false_paths();
305 __pass_to_client(stmt
->iterator_post_condition
, WHOLE_CONDITION_HOOK
);
306 split_conditions(stmt
->iterator_post_condition
);
307 /* It would prossibly be cleaner to make this all one function */
309 __use_false_states();
312 if (is_forever_loop(stmt
->iterator_post_condition
)) {
321 static void split_statements(struct statement
*stmt
)
323 unsigned int path_orig
;
328 __pass_to_client(stmt
, STMT_HOOK
);
330 switch (stmt
->type
) {
331 case STMT_DECLARATION
:
332 __pass_declarations_to_client(stmt
->declaration
);
333 split_symlist(stmt
->declaration
);
336 __pass_to_client(stmt
, RETURN_HOOK
);
337 split_expr(stmt
->ret_value
);
340 case STMT_EXPRESSION
:
341 split_expr(stmt
->expression
);
343 case STMT_COMPOUND
: {
345 FOR_EACH_PTR(stmt
->stmts
, s
) {
347 } END_FOR_EACH_PTR(s
);
351 __split_true_false_paths();
352 __pass_to_client(stmt
->if_conditional
, WHOLE_CONDITION_HOOK
);
353 split_conditions(stmt
->if_conditional
);
354 path_orig
= split_path_id();
356 split_statements(stmt
->if_true
);
358 __use_false_states();
359 split_statements(stmt
->if_false
);
360 __merge_true_states();
361 restore_path_id(path_orig
);
364 if (stmt
->iterator_pre_condition
)
365 handle_pre_loop(stmt
);
366 else if (stmt
->iterator_post_condition
)
367 handle_post_loop(stmt
);
370 split_expr(stmt
->switch_expression
);
371 __save_switch_states();
375 path_orig
= get_path_id();
376 split_statements(stmt
->switch_statement
);
377 if (!__pop_default())
381 restore_path_id(path_orig
);
386 if (!stmt
->case_expression
)
388 split_expr(stmt
->case_expression
);
389 split_expr(stmt
->case_to
);
390 split_statements(stmt
->case_statement
);
394 stmt
->label
->type
== SYM_LABEL
&&
395 stmt
->label
->ident
) {
396 __merge_gotos(stmt
->label
->ident
->name
);
398 split_statements(stmt
->label_statement
);
401 split_expr(stmt
->goto_expression
);
402 if (stmt
->goto_label
&& stmt
->goto_label
->type
== SYM_NODE
) {
403 if (!strcmp(stmt
->goto_label
->ident
->name
, "break")) {
405 } else if (!strcmp(stmt
->goto_label
->ident
->name
,
407 __process_continues();
409 } else if (stmt
->goto_label
&&
410 stmt
->goto_label
->type
== SYM_LABEL
&&
411 stmt
->goto_label
->ident
) {
412 __save_gotos(stmt
->goto_label
->ident
->name
);
419 split_expr(stmt
->asm_string
);
420 //split_expr(stmt->asm_outputs);
421 //split_expr(stmt->asm_inputs);
422 //split_expr(stmt->asm_clobbers);
427 split_expr(stmt
->range_expression
);
428 split_expr(stmt
->range_low
);
429 split_expr(stmt
->range_high
);
434 static void split_expr_list(struct expression_list
*expr_list
)
436 struct expression
*expr
;
437 FOR_EACH_PTR(expr_list
, expr
) {
439 } END_FOR_EACH_PTR(expr
);
443 static void split_sym(struct symbol
*sym
)
447 if (!(sym
->namespace & NS_SYMBOL
))
450 __pass_to_client(sym
, SYM_HOOK
);
451 split_statements(sym
->stmt
);
452 split_expr(sym
->array_size
);
453 split_symlist(sym
->arguments
);
454 split_symlist(sym
->symbol_list
);
455 split_statements(sym
->inline_stmt
);
456 split_symlist(sym
->inline_symbol_list
);
457 split_expr(sym
->initializer
);
460 static void split_symlist(struct symbol_list
*sym_list
)
464 FOR_EACH_PTR(sym_list
, sym
) {
466 } END_FOR_EACH_PTR(sym
);
469 static void split_functions(struct symbol_list
*sym_list
)
473 FOR_EACH_PTR(sym_list
, sym
) {
474 struct symbol
*base_type
;
475 base_type
= get_base_type(sym
);
476 if (sym
->type
== SYM_NODE
&& base_type
->type
== SYM_FN
) {
478 line_func_start
= base_type
->stmt
->pos
.line
;
480 cur_func
= sym
->ident
->name
;
481 __smatch_lineno
= sym
->pos
.line
;
482 __pass_to_client(sym
, FUNC_DEF_HOOK
);
483 split_statements(base_type
->stmt
);
484 __pass_to_client(sym
, END_FUNC_HOOK
);
490 __pass_to_client(sym
, BASE_HOOK
);
492 } END_FOR_EACH_PTR(sym
);
495 void smatch (int argc
, char **argv
)
498 struct string_list
*filelist
= NULL
;
499 struct symbol_list
*sym_list
;
502 printf("Usage: smatch <filename.c>\n");
505 sparse_initialize(argc
, argv
, &filelist
);
506 FOR_EACH_PTR_NOTAG(filelist
, filename
) {
507 sym_list
= __sparse(filename
);
508 split_functions(sym_list
);
509 } END_FOR_EACH_PTR_NOTAG(filename
);