From f8d6258b41e2599efee5bb3eab05f8ac927571a4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 10 Jan 2017 17:51:35 +0300 Subject: [PATCH] function_hooks, db: handle PARAM_LIMIT for struct members Say you have a function call: frob(foo, bar); The original code could say things like if foo is NULL we will return -EINVAL, but it didn't say things like if foo->member is NULL we return whatever. With this change that's possible now. Signed-off-by: Dan Carpenter --- smatch_function_hooks.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/smatch_function_hooks.c b/smatch_function_hooks.c index 78ebd3c5..7b8b0f47 100644 --- a/smatch_function_hooks.c +++ b/smatch_function_hooks.c @@ -392,13 +392,11 @@ static void handle_ret_equals_param(char *ret_string, struct range_list *rl, str static int impossible_limit(struct expression *expr, int param, char *key, char *value) { struct expression *arg; + struct smatch_state *state; struct range_list *passed; struct range_list *limit; struct symbol *compare_type; - if (strcmp(key, "$") != 0) - return 0; - while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); if (expr->type != EXPR_CALL) @@ -407,12 +405,34 @@ static int impossible_limit(struct expression *expr, int param, char *key, char arg = get_argument_from_call_expr(expr->args, param); if (!arg) return 0; - if (!get_implied_rl(arg, &passed)) - return 0; - if (!passed || is_whole_rl(passed)) - return 0; - compare_type = get_arg_type(expr->fn, param); + if (strcmp(key, "$") == 0) { + if (!get_implied_rl(arg, &passed)) + return 0; + + compare_type = get_arg_type(expr->fn, param); + } else { + char *name; + struct symbol *sym; + + name = get_variable_from_key(arg, key, &sym); + if (!name || !sym) + return 0; + + state = get_state(SMATCH_EXTRA, name, sym); + if (!state) { + free_string(name); + return 0; + } + passed = estate_rl(state); + if (!passed || is_whole_rl(passed)) { + free_string(name); + return 0; + } + + compare_type = get_member_type_from_key(arg, key); + } + passed = cast_rl(compare_type, passed); call_results_to_rl(expr, compare_type, value, &limit); if (!limit || is_whole_rl(limit)) -- 2.11.4.GIT