From 2a095175d1d629f6e3e9290065e50c8026278313 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 23 Apr 2010 18:15:00 +0200 Subject: [PATCH] extra: handle i++ and i += 2 better outside loops This patch adds the function inside_loop() which returns 1 if we are inside a loop or if we have reached a goto label. Inside loops we assume that i++ can go up to max (Unless they are in a canonical loop format, that's handled as a special case). Outside of a loop i++ is just a matter of adding 1 to the min and max values of i. At this point "i = i + 1;" is always treated as being outside a loop because smatch isn't clever enough to see that it's adding itself to itself. Signed-off-by: Dan Carpenter --- smatch.h | 1 + smatch_extra.c | 10 ++++++++-- smatch_flow.c | 8 ++++++++ validation/sm_math1.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 validation/sm_math1.c diff --git a/smatch.h b/smatch.h index ae07d67a..843106de 100644 --- a/smatch.h +++ b/smatch.h @@ -226,6 +226,7 @@ int in_condition(void); /* smatch_flow.c */ void smatch (int argc, char **argv); +int inside_loop(void); void __split_expr(struct expression *expr); void __split_statements(struct statement *stmt); extern int option_assume_loops; diff --git a/smatch_extra.c b/smatch_extra.c index 8c2b0133..55fc2e3d 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -591,7 +591,8 @@ static void match_assign(struct expression *expr) else min = tmp; } - + if (!inside_loop() && known && get_implied_max(left, &tmp)) + max = tmp + value; } if (expr->op == SPECIAL_SUB_ASSIGN) { if (get_implied_max(left, &tmp)) { @@ -600,7 +601,8 @@ static void match_assign(struct expression *expr) else max = tmp; } - + if (!inside_loop() && known && get_implied_min(left, &tmp)) + min = tmp - value; } set_extra_mod(name, sym, alloc_extra_state_range(min, max)); free: @@ -628,10 +630,14 @@ static void unop_expr(struct expression *expr) if (expr->op == SPECIAL_INCREMENT) { if (get_implied_min(expr->unop, &val)) min = val + 1; + if (!inside_loop() && get_implied_max(expr->unop, &val)) + max = val + 1; } if (expr->op == SPECIAL_DECREMENT) { if (get_implied_max(expr->unop, &val)) max = val - 1; + if (!inside_loop() && get_implied_min(expr->unop, &val)) + min = val - 1; } set_extra_mod(name, sym, alloc_extra_state_range(min, max)); free: diff --git a/smatch_flow.c b/smatch_flow.c index 6685915b..87c00a93 100644 --- a/smatch_flow.c +++ b/smatch_flow.c @@ -25,6 +25,7 @@ static char *pathname; static char *full_filename; static char *cur_func; static int line_func_start; +static int loop_count; static struct expression_list *switch_expr_stack = NULL; struct expression_list *big_expression_stack; struct statement_list *big_statement_stack; @@ -33,6 +34,7 @@ int __bail_on_rest_of_function = 0; char *get_function(void) { return cur_func; } int get_lineno(void) { return __smatch_lineno; } int get_func_pos(void) { return __smatch_lineno - line_func_start; } +int inside_loop(void) { return !!loop_count; } static void split_symlist(struct symbol_list *sym_list); static void split_declaration(struct symbol_list *sym_list); @@ -225,6 +227,7 @@ static void handle_pre_loop(struct statement *stmt) once_through = implied_condition_true(stmt->iterator_pre_condition); + loop_count++; __push_continues(); __push_breaks(); @@ -272,6 +275,7 @@ static void handle_pre_loop(struct statement *stmt) stmt->iterator_pre_condition); __merge_breaks(); } + loop_count--; } /* @@ -283,6 +287,7 @@ static void handle_post_loop(struct statement *stmt) loop_name = get_loop_name(loop_num); loop_num++; + loop_count++; __push_continues(); __push_breaks(); @@ -299,6 +304,7 @@ static void handle_post_loop(struct statement *stmt) __use_false_states(); __merge_breaks(); } + loop_count--; } static int empty_statement(struct statement *stmt) @@ -481,6 +487,7 @@ void __split_statements(struct statement *stmt) if (stmt->label && stmt->label->type == SYM_LABEL && stmt->label->ident) { + loop_count = 1000000; __merge_gotos(stmt->label->ident->name); } __split_statements(stmt->label_statement); @@ -602,6 +609,7 @@ static void split_functions(struct symbol_list *sym_list) cur_func = sym->ident->name; __smatch_lineno = sym->pos.line; last_stmt = NULL; + loop_count = 0; sm_debug("new function: %s\n", cur_func); if (option_two_passes) { __unnullify_path(); diff --git a/validation/sm_math1.c b/validation/sm_math1.c new file mode 100644 index 00000000..e6d9cc3f --- /dev/null +++ b/validation/sm_math1.c @@ -0,0 +1,37 @@ +#include "check_debug.h" + +int something(); + +void func(void) +{ + int x = 3; + int y = 42; + int z = 7; + + x--; + y -= 100; + __smatch_value("y"); + while (something()) { + y++; + __smatch_value("y"); + } + z += something(); + __smatch_value("z"); + __smatch_value("x"); +label_I1: + x--; + __smatch_value("x"); + goto label_I1; +} +/* + * check-name: smatch math test #1 + * check-command: smatch -I.. sm_math1.c + * + * check-output-start +sm_math1.c +13 func(8) y = (-58) +sm_math1.c +16 func(11) y = (-57)-max +sm_math1.c +19 func(14) z = 7-max +sm_math1.c +20 func(15) x = 2 +sm_math1.c +23 func(18) x = min-1 + * check-output-end + */ -- 2.11.4.GIT