Fix #11774 (False positive: passing struct pointer to function that initialize it) (#5162)

This commit is contained in:
Daniel Marjamäki 2023-06-16 18:43:32 +02:00 committed by GitHub
parent b689ca8d89
commit aca6c47024
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 9 deletions

View File

@ -2346,7 +2346,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
const Token * const tok1 = tok; const Token * const tok1 = tok;
// address of variable // address of variable
if (tok->astParent() && tok->astParent()->isUnaryOp("&")) const bool addressOf = tok->astParent() && tok->astParent()->isUnaryOp("&");
if (addressOf)
indirect++; indirect++;
int argnr; int argnr;
@ -2408,6 +2409,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
if (indirect > 0) { if (indirect > 0) {
if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect))) if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect)))
return true; 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))) if (arg->isArray() || (!arg->isPointer() && (!arg->valueType() || arg->valueType()->type == ValueType::UNKNOWN_TYPE)))
return true; 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(); 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 // Check addressof
if (tok2->astParent() && tok2->astParent()->isUnaryOp("&") && if (tok2->astParent() && tok2->astParent()->isUnaryOp("&")) {
isVariableChanged(tok2->astParent(), indirect + 1, settings, depth - 1)) { if (isVariableChanged(tok2->astParent(), indirect + 1, settings, depth - 1))
return true; 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())) if (cpp && Token::Match(tok2->astParent(), ">>|&") && astIsRHS(tok2) && isLikelyStreamRead(cpp, tok2->astParent()))

View File

@ -5543,6 +5543,17 @@ private:
"}"; "}";
values = tokenValues(code, "n )", ValueFlow::Value::ValueType::UNINIT); values = tokenValues(code, "n )", ValueFlow::Value::ValueType::UNINIT);
ASSERT_EQUALS(0, values.size()); 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() { void valueFlowConditionExpressions() {