From 43f32e21c213c3bdc01f87130b6d52f6fe70d91e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 23 Nov 2012 14:50:49 +0300 Subject: [PATCH] extra: handle loops where without a hard max that don't have a break If the loop doesn't have a hard max, then the value after the loop is unknown-ish the same as it was before. If we have a break statement this works already, but if we don't then this was setting it to the max. Signed-off-by: Dan Carpenter --- smatch.h | 1 + smatch_extra.c | 9 ++++++++- smatch_states.c | 11 +++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/smatch.h b/smatch.h index be682653..3f7cc486 100644 --- a/smatch.h +++ b/smatch.h @@ -409,6 +409,7 @@ void __merge_continues(void); void __push_breaks(void); void __process_breaks(void); +int __has_breaks(void); void __merge_breaks(void); void __use_breaks(void); diff --git a/smatch_extra.c b/smatch_extra.c index ae3f8bbe..5a6eb85a 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -370,7 +370,14 @@ void __extra_pre_loop_hook_after(struct sm_state *sm, limit = sval_binop(estate_min(sm->state), '-', sval_type_val(estate_type(sm->state), 1)); } - state = alloc_estate(limit); + if (!estate_has_hard_max(sm->state) && !__has_breaks()) { + if (iter_expr->op == SPECIAL_INCREMENT) + state = alloc_estate_range(estate_min(sm->state), limit); + else + state = alloc_estate_range(limit, estate_max(sm->state)); + } else { + state = alloc_estate(limit); + } if (!estate_has_hard_max(sm->state)) estate_clear_hard_max(state); set_extra_mod(sm->name, sm->sym, state); diff --git a/smatch_states.c b/smatch_states.c index 3811c28f..0cf8bd24 100644 --- a/smatch_states.c +++ b/smatch_states.c @@ -682,6 +682,17 @@ void __process_breaks(void) push_slist(&break_stack, slist); } +int __has_breaks(void) +{ + struct state_list *slist; + int ret; + + slist = pop_slist(&break_stack); + ret = !!slist; + push_slist(&break_stack, slist); + return ret; +} + void __merge_breaks(void) { struct state_list *slist; -- 2.11.4.GIT