From aca6c47024a0094ff469393dc1f2d22c49bb76cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 16 Jun 2023 18:43:32 +0200 Subject: [PATCH] Fix #11774 (False positive: passing struct pointer to function that initialize it) (#5162) --- lib/astutils.cpp | 20 +++++++++++--------- test/testvalueflow.cpp | 11 +++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 876c8665b..c4ac0b967 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2346,7 +2346,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti const Token * const tok1 = tok; // address of variable - if (tok->astParent() && tok->astParent()->isUnaryOp("&")) + const bool addressOf = tok->astParent() && tok->astParent()->isUnaryOp("&"); + if (addressOf) indirect++; int argnr; @@ -2408,6 +2409,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti if (indirect > 0) { if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect))) return true; + if (indirect > 1 && addressOf && arg->isPointer() && (!arg->valueType() || !arg->valueType()->isConst(indirect-1))) + return true; if (arg->isArray() || (!arg->isPointer() && (!arg->valueType() || arg->valueType()->type == ValueType::UNKNOWN_TYPE))) return true; } @@ -2482,16 +2485,15 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, } const ValueType* vt = tok->variable() ? tok->variable()->valueType() : tok->valueType(); - // If its already const then it cant be modified - if (vt) { - if (vt->isConst(indirect)) - return false; - } // Check addressof - if (tok2->astParent() && tok2->astParent()->isUnaryOp("&") && - isVariableChanged(tok2->astParent(), indirect + 1, settings, depth - 1)) { - return true; + if (tok2->astParent() && tok2->astParent()->isUnaryOp("&")) { + if (isVariableChanged(tok2->astParent(), indirect + 1, settings, depth - 1)) + return true; + } else { + // If its already const then it cant be modified + if (vt && vt->isConst(indirect)) + return false; } if (cpp && Token::Match(tok2->astParent(), ">>|&") && astIsRHS(tok2) && isLikelyStreamRead(cpp, tok2->astParent())) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index d079be41e..6e36c1896 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5543,6 +5543,17 @@ private: "}"; values = tokenValues(code, "n )", ValueFlow::Value::ValueType::UNINIT); ASSERT_EQUALS(0, values.size()); + + // #11774 - function call to init data + code = "struct id_struct { int id; };\n" + "int init(const id_struct **id);\n" + "void fp() {\n" + " const id_struct *id_st;\n" + " init(&id_st);\n" + " if (id_st->id > 0) {}\n" + "}\n"; + values = tokenValues(code, ". id", ValueFlow::Value::ValueType::UNINIT); + ASSERT_EQUALS(0, values.size()); } void valueFlowConditionExpressions() {