From af289c8357c4cd342660abd5766550f48ae397aa Mon Sep 17 00:00:00 2001 From: KenPatrickLehrmann <54900810+KenPatrickLehrmann@users.noreply.github.com> Date: Sun, 2 Jan 2022 08:14:10 +0100 Subject: [PATCH] Handle (&foo)-> in isVariableChanged (#3624) --- lib/astutils.cpp | 5 ++++- test/testuninitvar.cpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 151ebed3b..682ab3940 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2134,11 +2134,14 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, int derefs = 0; while (Token::simpleMatch(tok2->astParent(), "*") || (Token::simpleMatch(tok2->astParent(), ".") && !Token::simpleMatch(tok2->astParent()->astParent(), "(")) || + (tok2->astParent() && tok2->astParent()->isUnaryOp("&") && !tok2->astParent()->astOperand2() && Token::simpleMatch(tok2->astParent()->astParent(), ".") && tok2->astParent()->astParent()->originalName()=="->") || (Token::simpleMatch(tok2->astParent(), "[") && tok2 == tok2->astParent()->astOperand1())) { - if (tok2->astParent()->isUnaryOp("*") || (astIsLHS(tok2) && tok2->astParent()->originalName() == "->")) + if (tok2->astParent() && (tok2->astParent()->isUnaryOp("*") || (astIsLHS(tok2) && tok2->astParent()->originalName() == "->"))) derefs++; if (derefs > indirect) break; + if ((tok2->astParent() && tok2->astParent()->isUnaryOp("&") && Token::simpleMatch(tok2->astParent()->astParent(), ".") && tok2->astParent()->astParent()->originalName()=="->")) + tok2 = tok2->astParent(); tok2 = tok2->astParent(); } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 769b528b4..2848d6aa4 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -93,6 +93,8 @@ private: TEST_CASE(isVariableUsageDeref); // *p + TEST_CASE(uninitvar_memberaccess); // (&(a))->b <=> a.b + // whole program analysis TEST_CASE(ctuTest); } @@ -5989,6 +5991,24 @@ private: ASSERT_EQUALS("", errout.str()); } + void uninitvar_memberaccess() { + valueFlowUninit("struct foo{char *bar;};\n" + "void f(unsigned long long *p) {\n" + " foo a;\n" + " ((&a)->bar) = reinterpret_cast(*p);\n" + " if ((&a)->bar) ;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("struct foo{char *bar;};\n" + "void f(unsigned long long *p) {\n" + " foo a;\n" + " ((&(a))->bar) = reinterpret_cast(*p);\n" + " if ((&a)->bar) ;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void ctu_(const char* file, int line, const char code[]) { // Clear the error buffer.. errout.str("");