From 82e85a9e7f2f3830b98f91a34662a229232381f1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 11 May 2023 11:44:37 +0300 Subject: [PATCH] dereference: find more cross function dereferences Quite often there is code like: struct whatever *p = ¶m->foo; p->x = 100; The ¶m->foo is not a dereference. The p->x is a dereference, but it didn't result in anything being recorded in the database. What this code does is that when we see the "p->x", then record the "param" was dereferenced. Signed-off-by: Dan Carpenter --- smatch_dereference.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/smatch_dereference.c b/smatch_dereference.c index 985d37ca..067f7f14 100644 --- a/smatch_dereference.c +++ b/smatch_dereference.c @@ -38,13 +38,40 @@ static void call_deref_hooks(struct expression *expr) static void match_dereference(struct expression *expr) { + struct expression *p, *tmp; + if (expr->type != EXPR_PREOP || expr->op != '*') return; - expr = strip_expr(expr->unop); - if (!is_pointer(expr)) + p = strip_expr(expr->unop); + if (!is_pointer(p)) + return; + call_deref_hooks(p); + + tmp = get_assigned_expr(p); + if (!tmp) + return; + /* + * Imagine we have: + * p = &foo->bar; + * x = p->whatever; + * + * Note that we only care about address assignments because other + * dereferences would have been handled already. + */ + p = strip_expr(tmp->unop); + if (tmp->type != EXPR_PREOP || tmp->op != '&') + return; + p = strip_expr(tmp->unop); + if (p->type != EXPR_DEREF) + return; + p = strip_expr(p->deref); + if (p->type != EXPR_PREOP || p->op != '*') + return; + p = strip_expr(p->unop); + if (!is_pointer(p)) return; - call_deref_hooks(expr); + call_deref_hooks(p); } static void match_pointer_as_array(struct expression *expr) -- 2.11.4.GIT