Fix 11610: false negative: knownConditionTrueFalse with address of variable (#4883)

This commit is contained in:
Paul Fultz II 2023-03-12 13:57:11 -05:00 committed by GitHub
parent a75392307f
commit 61e8b84578
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 45 deletions

View File

@ -1591,7 +1591,8 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
return false;
}
} else {
if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
if (!tok1->function()->isConst() && !tok1->function()->isAttributeConst() &&
!tok1->function()->isAttributePure())
return false;
}
}

View File

@ -1965,7 +1965,7 @@ void CheckStl::string_c_str()
string_c_strError(tok);
} else if (printPerformance && tok->tokAt(1)->astOperand2() && Token::Match(tok->tokAt(1)->astOperand2()->tokAt(-3), "%var% . c_str|data ( ) ;")) {
const Token* vartok = tok->tokAt(1)->astOperand2()->tokAt(-3);
if (tok->variable() && tok->variable()->isStlStringType() && vartok->variable() && vartok->variable()->isStlStringType())
if (tok->variable()->isStlStringType() && vartok->variable() && vartok->variable()->isStlStringType())
string_c_strAssignment(tok);
}
} else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && tok->str() != scope.className) {

View File

@ -1612,7 +1612,7 @@ void CheckUninitVar::valueFlowUninit()
bool uninitderef = false;
if (tok->variable()) {
bool unknown;
const bool isarray = !tok->variable() || tok->variable()->isArray();
const bool isarray = tok->variable()->isArray();
const bool ispointer = astIsPointer(tok) && !isarray;
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
if (ispointer && v->indirect == 1 && !deref)

View File

@ -269,6 +269,12 @@ static void addToErrorPath(ValueFlow::Value& value, const std::vector<const Valu
[&](const ErrorPathItem& e) {
return locations.insert(e.first).second;
});
std::copy_if(ref->debugPath.cbegin(),
ref->debugPath.cend(),
std::back_inserter(value.debugPath),
[&](const ErrorPathItem& e) {
return locations.insert(e.first).second;
});
}
}

View File

@ -6138,7 +6138,7 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
if (!parent->astOperand1())
return;
const ValueType *vt1 = parent->astOperand1() ? parent->astOperand1()->valueType() : nullptr;
const ValueType *vt1 = parent->astOperand1()->valueType();
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
if (vt1 && Token::Match(parent, "<<|>>")) {

View File

@ -508,6 +508,24 @@ static bool isComputableValue(const Token* parent, const ValueFlow::Value& value
return true;
}
static Library::Container::Yield getContainerYield(Token* tok, const Settings* settings, Token** parent = nullptr)
{
if (Token::Match(tok, ". %name% (") && tok->astParent() == tok->tokAt(2) && tok->astOperand1() &&
tok->astOperand1()->valueType()) {
const Library::Container* c = getLibraryContainer(tok->astOperand1());
if (parent)
*parent = tok->astParent();
return c ? c->getYield(tok->strAt(1)) : Library::Container::Yield::NO_YIELD;
} else if (Token::Match(tok->previous(), "%name% (")) {
if (parent)
*parent = tok;
if (const Library::Function* f = settings->library.getFunction(tok->previous())) {
return f->containerYield;
}
}
return Library::Container::Yield::NO_YIELD;
}
/** Set token value for cast */
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings);
@ -663,36 +681,25 @@ static void setTokenValue(Token* tok,
}
}
}
else if (Token::Match(parent, ". %name% (") && parent->astParent() == parent->tokAt(2) &&
parent->astOperand1() && parent->astOperand1()->valueType()) {
const Library::Container* c = getLibraryContainer(parent->astOperand1());
const Library::Container::Yield yields = c ? c->getYield(parent->strAt(1)) : Library::Container::Yield::NO_YIELD;
if (yields == Library::Container::Yield::SIZE) {
ValueFlow::Value v(value);
v.valueType = ValueFlow::Value::ValueType::INT;
setTokenValue(parent->astParent(), std::move(v), settings);
} else if (yields == Library::Container::Yield::EMPTY) {
ValueFlow::Value v(value);
v.valueType = ValueFlow::Value::ValueType::INT;
if (value.isImpossible() && value.intvalue == 0)
Token* next = nullptr;
const Library::Container::Yield yields = getContainerYield(parent, settings, &next);
if (yields == Library::Container::Yield::SIZE) {
ValueFlow::Value v(value);
v.valueType = ValueFlow::Value::ValueType::INT;
setTokenValue(next, std::move(v), settings);
} else if (yields == Library::Container::Yield::EMPTY) {
ValueFlow::Value v(value);
v.valueType = ValueFlow::Value::ValueType::INT;
v.bound = ValueFlow::Value::Bound::Point;
if (value.isImpossible()) {
if (value.intvalue == 0)
v.setKnown();
else
v.intvalue = !v.intvalue;
setTokenValue(parent->astParent(), std::move(v), settings);
}
} else if (Token::Match(parent->previous(), "%name% (")) {
if (const Library::Function* f = settings->library.getFunction(parent->previous())) {
if (f->containerYield == Library::Container::Yield::SIZE) {
ValueFlow::Value v(value);
v.valueType = ValueFlow::Value::ValueType::INT;
setTokenValue(parent, std::move(v), settings);
} else if (f->containerYield == Library::Container::Yield::EMPTY) {
ValueFlow::Value v(value);
v.intvalue = !v.intvalue;
v.valueType = ValueFlow::Value::ValueType::INT;
setTokenValue(parent, std::move(v), settings);
}
v.setPossible();
} else {
v.intvalue = !v.intvalue;
}
setTokenValue(next, std::move(v), settings);
}
return;
}
@ -917,7 +924,10 @@ static void setTokenValue(Token* tok,
if (val.isImpossible() && val.intvalue != 0)
continue;
ValueFlow::Value v(val);
v.intvalue = !v.intvalue;
if (val.isImpossible())
v.setKnown();
else
v.intvalue = !v.intvalue;
setTokenValue(parent, std::move(v), settings);
}
}
@ -1859,7 +1869,7 @@ static void valueFlowImpossibleValues(TokenList* tokenList, const Settings* sett
ValueFlow::Value value{0};
value.setImpossible();
setTokenValue(tok->linkAt(1)->next(), std::move(value), settings);
} else if (tokenList->isCPP() && Token::simpleMatch(tok, "this")) {
} else if ((tokenList->isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) {
ValueFlow::Value value{0};
value.setImpossible();
setTokenValue(tok, std::move(value), settings);
@ -6666,16 +6676,7 @@ static void valueFlowInferCondition(TokenList* tokenlist,
continue;
if (tok->hasKnownIntValue())
continue;
if (tok->variable() && (Token::Match(tok->astParent(), "?|&&|!|%oror%") ||
Token::Match(tok->astParent()->previous(), "if|while ("))) {
std::vector<ValueFlow::Value> result = infer(IntegralInferModel{}, "!=", tok->values(), 0);
if (result.size() != 1)
continue;
ValueFlow::Value value = result.front();
value.intvalue = 1;
value.bound = ValueFlow::Value::Bound::Point;
setTokenValue(tok, std::move(value), settings);
} else if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) {
if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) {
if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) {
static const std::array<ValuePtr<InferModel>, 2> iteratorModels = {EndIteratorInferModel{},
StartIteratorInferModel{}};
@ -6694,6 +6695,15 @@ static void valueFlowInferCondition(TokenList* tokenlist,
setTokenValue(tok, std::move(value), settings);
}
}
} else if (Token::Match(tok->astParent(), "?|&&|!|%oror%") ||
Token::Match(tok->astParent()->previous(), "if|while (")) {
std::vector<ValueFlow::Value> result = infer(IntegralInferModel{}, "!=", tok->values(), 0);
if (result.size() != 1)
continue;
ValueFlow::Value value = result.front();
value.intvalue = 1;
value.bound = ValueFlow::Value::Bound::Point;
setTokenValue(tok, std::move(value), settings);
}
}
}

View File

@ -353,11 +353,14 @@ private:
ASSERT_EQUALS("", errout.str());
// no crash on unary operator& (#5643)
// #11610
check("SdrObject* ApplyGraphicToObject() {\n"
" if (&rHitObject) {}\n"
" else if (rHitObject.IsClosedObj() && !&rHitObject) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (style) Condition '&rHitObject' is always true\n"
"[test.cpp:3]: (style) Condition '!&rHitObject' is always false\n",
errout.str());
// #5695: increment
check("void f(int a0, int n) {\n"
@ -3800,6 +3803,7 @@ private:
"}\n");
ASSERT_EQUALS("", errout.str());
// TODO: if (!v) is a known condition as well
check("struct a {\n"
" int *b();\n"
"};\n"
@ -3813,7 +3817,7 @@ private:
" if (v == nullptr && e) {}\n"
" return d;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:11]: (style) Condition 'e' is always true\n", errout.str());
// #10037
check("struct a {\n"

View File

@ -1072,6 +1072,13 @@ private:
"}";
ASSERT_EQUALS(false, testValueOfX(code, 3U, 0));
code = "void f(int i) {\n"
" int * p = &i;\n"
" bool x = !p || i;\n"
" bool a = x;\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 4U, 1));
code = "bool f(const uint16_t * const p) {\n"
" const uint8_t x = (uint8_t)(*p & 0x01E0U) >> 5U;\n"
" return x != 0;\n"