From 65662296ea627f612e4c204d120b8dbd6d0da13b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 30 Jul 2015 12:54:36 +0300 Subject: [PATCH] extra: handle arrays better using the chunk code This lets use parse code like "if (foo[3] > 10)". Very exciting. :) The offset doesn't have to be a literal, but if you try to mix literals with variables then it tends to reset to unknown. Signed-off-by: Dan Carpenter --- smatch_extra.c | 53 +++++++++++++++++++++++++++++++++++++++++--------- smatch_var_sym.c | 3 +++ validation/sm_chunk2.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 validation/sm_chunk2.c diff --git a/smatch_extra.c b/smatch_extra.c index 1cf43c57..795c29a5 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -34,6 +34,8 @@ static int my_id; static int link_id; +static void match_link_modify(struct sm_state *sm, struct expression *mod_expr); + struct string_list *__ignored_macros = NULL; static int in_warn_on_macro(void) { @@ -640,6 +642,42 @@ free: free_string(name); } +static void do_array_assign(struct expression *left, int op, struct expression *right) +{ + struct expression *array; + struct expression *offset; + struct var_sym_list *vsl; + struct var_sym *vs; + char *name; + struct symbol *sym; + struct range_list *rl; + sval_t sval; + + array = get_array_base(left); + offset = get_array_offset(left); + get_absolute_rl(right, &rl); + rl = cast_rl(get_type(left), rl); + + name = expr_to_chunk_sym_vsl(left, &sym, &vsl); + + if (!name || !vsl || op != '=' || !get_value(offset, &sval) || is_whole_rl(rl)) { + struct sm_state *sm; + + sm = get_sm_state_expr(link_id, array); + if (sm) + match_link_modify(sm, NULL); + goto free; + } + + FOR_EACH_PTR(vsl, vs) { + store_link(link_id, vs->var, vs->sym, name, sym); + } END_FOR_EACH_PTR(vs); + + set_state(SMATCH_EXTRA, name, sym, alloc_estate_rl(rl)); +free: + free_string(name); +} + static void match_vanilla_assign(struct expression *left, struct expression *right) { struct range_list *rl = NULL; @@ -658,8 +696,11 @@ static void match_vanilla_assign(struct expression *left, struct expression *rig save_chunk_info(left, right); name = expr_to_var_sym(left, &sym); - if (!name) + if (!name) { + if (is_array(left)) + do_array_assign(left, '=', right); return; + } left_type = get_type(left); right_type = get_type(right); @@ -1406,8 +1447,6 @@ static void handle_AND_condition(struct expression *expr) /* this is actually hooked from smatch_implied.c... it's hacky, yes */ void __extra_match_condition(struct expression *expr) { - struct symbol *sym; - char *name; struct smatch_state *pre_state; struct smatch_state *true_state; struct smatch_state *false_state; @@ -1425,17 +1464,13 @@ void __extra_match_condition(struct expression *expr) zero = sval_blank(expr); zero.value = 0; - name = expr_to_var_sym(expr, &sym); - if (!name) - return; - pre_state = get_state(my_id, name, sym); + pre_state = get_extra_state(expr); true_state = estate_filter_sval(pre_state, zero); if (possibly_true(expr, SPECIAL_EQUAL, zero_expr())) false_state = alloc_estate_sval(zero); else false_state = alloc_estate_empty(); - set_extra_true_false(name, sym, true_state, false_state); - free_string(name); + set_extra_expr_true_false(expr, true_state, false_state); return; } case EXPR_COMPARE: diff --git a/smatch_var_sym.c b/smatch_var_sym.c index bce7169b..3e5f3a20 100644 --- a/smatch_var_sym.c +++ b/smatch_var_sym.c @@ -39,6 +39,9 @@ struct var_sym_list *expr_to_vsl(struct expression *expr) if (!expr) return NULL; + if (expr->type == EXPR_PREOP && expr->op == '*') + return expr_to_vsl(expr->unop); + if (expr->type == EXPR_BINOP || expr->type == EXPR_LOGICAL || expr->type == EXPR_COMPARE) { diff --git a/validation/sm_chunk2.c b/validation/sm_chunk2.c new file mode 100644 index 00000000..e22c41e3 --- /dev/null +++ b/validation/sm_chunk2.c @@ -0,0 +1,40 @@ +#include "check_debug.h" + +void initialize(void *p); + +int main(int x) +{ + unsigned int aaa[10]; + int y; + + initialize(&aaa); + initialize(&y); + + if (aaa[5] > 3) + return 0; + aaa[0] = 42; + __smatch_implied(aaa[0]); + __smatch_implied(aaa[5]); + aaa[y] = 10; + __smatch_implied(aaa[5]); + if (aaa[y] > 4) + return 0; + __smatch_implied(aaa[y]); + y = 3; + __smatch_implied(aaa[y]); + + return 0; +} + +/* + * check-name: smatch chunk #2 + * check-command: smatch -I.. sm_chunk2.c + * + * check-output-start +sm_chunk2.c:16 main() implied: aaa[0] = '42' +sm_chunk2.c:17 main() implied: aaa[5] = '0-3' +sm_chunk2.c:19 main() implied: aaa[5] = '0-u32max' +sm_chunk2.c:22 main() implied: aaa[y] = '0-4' +sm_chunk2.c:24 main() implied: aaa[y] = '0-u32max' + * check-output-end + */ -- 2.11.4.GIT