From 720ae018989d8963bc88c7c6fb5bc78e58e3d6b0 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 11 Aug 2023 18:46:51 +0200 Subject: [PATCH] Fix #11353 FP uninitvar for struct member set via pointer (#5314) --- lib/valueflow.cpp | 12 ++++++++++-- test/testuninitvar.cpp | 23 ++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index cb34915cb..b1e7e52a2 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3295,6 +3295,12 @@ struct MemberExpressionAnalyzer : SubExpressionAnalyzer { : SubExpressionAnalyzer(e, std::move(val), t, s), varname(std::move(varname)) {} + bool match(const Token* tok) const override + { + return SubExpressionAnalyzer::match(tok) || + (Token::simpleMatch(tok->astParent(), ".") && SubExpressionAnalyzer::match(tok->astParent())); + } + bool submatch(const Token* tok, bool exact) const override { if (!Token::Match(tok, ". %var%")) @@ -7965,6 +7971,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) Token* start = findStartToken(var, tok->next(), &settings->library); std::map partialReads; + Analyzer::Result result; if (const Scope* scope = var->typeScope()) { if (Token::findsimplematch(scope->bodyStart, "union", scope->bodyEnd)) continue; @@ -7979,7 +7986,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) continue; } MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings); - valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, *settings); + result = valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, *settings); for (auto&& p : *analyzer.partialReads) { Token* tok2 = p.first; @@ -8009,7 +8016,8 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) if (partial) continue; - valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings); + if (result.terminate != Analyzer::Terminate::Modified) + valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings); } } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index fdaad7eb1..f7432725d 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6181,7 +6181,7 @@ private: " memcpy(wcsin, x, sizeof(wcsstruct));\n" // <- warning " x->wcsprm = NULL;\n" // <- no warning "}"); - ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: x\n", errout.str()); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: x.wcsprm\n", errout.str()); valueFlowUninit("struct wcsstruct {\n" " int *wcsprm;\n" @@ -6264,7 +6264,7 @@ private: " int * x = &s1.x;\n" " struct S s2 = {*x, 0};\n" "}"); - ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:9]: (error) Uninitialized variable: *x\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: *x\n", errout.str()); valueFlowUninit("struct S {\n" " int x;\n" @@ -6277,7 +6277,7 @@ private: " int * x = &s1.x;\n" " s2.x = *x;\n" "}"); - ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:10]: (error) Uninitialized variable: *x\n", errout.str()); + ASSERT_EQUALS("[test.cpp:10]: (error) Uninitialized variable: *x\n", errout.str()); valueFlowUninit("void f(bool * x) {\n" " *x = false;\n" @@ -6897,7 +6897,7 @@ private: " int a = ab.a;\n" " int b = ab.b;\n" "}"); - TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: ab.b\n", errout.str()); // STL class member valueFlowUninit("struct A {\n" @@ -7009,7 +7009,7 @@ private: " memcpy(in, s, sizeof(S));\n" " s->p = NULL;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s.p\n", errout.str()); valueFlowUninit("struct S {\n" // #11321 @@ -7270,7 +7270,7 @@ private: " A::B b;\n" " x.push_back(b);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: b\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: b.i\n", errout.str()); valueFlowUninit("struct A {\n" " struct B {\n" @@ -7294,7 +7294,7 @@ private: " A a;\n" " x.push_back(a);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: a\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: a.j\n", errout.str()); valueFlowUninit("struct S { struct T { int* p; } t[2]; };\n" // #11018 "void f() {\n" @@ -7314,6 +7314,15 @@ private: " int y = x < (1, s.i);\n" "}\n"); ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: s.i\n", errout.str()); + + valueFlowUninit("struct S { int x; };\n" // #11353 + "struct S f() {\n" + " struct S s;\n" + " int* p = &s.x;\n" + " *p = 0;\n" + " return s;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void ctu_(const char* file, int line, const char code[]) {