Fix 10728: Crash in CheckStl::checkDereferenceInvalidIterator2 (#3721)
* Fix 10728: Crash in CheckStl::checkDereferenceInvalidIterator2 * Format
This commit is contained in:
parent
b6c010c17e
commit
7b793af451
|
@ -994,7 +994,7 @@ void CheckBufferOverrun::objectIndex()
|
|||
if (idx->hasKnownIntValue() && idx->getKnownIntValue() == 0)
|
||||
continue;
|
||||
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(obj, false, true);
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(obj, false, -1);
|
||||
for (const ValueFlow::Value& v:values) {
|
||||
if (v.lifetimeKind != ValueFlow::Value::LifetimeKind::Address)
|
||||
continue;
|
||||
|
|
|
@ -728,9 +728,9 @@ static bool isSameIteratorContainerExpression(const Token* tok1,
|
|||
return false;
|
||||
}
|
||||
|
||||
static ValueFlow::Value getLifetimeIteratorValue(const Token* tok)
|
||||
static ValueFlow::Value getLifetimeIteratorValue(const Token* tok, MathLib::bigint path = 0)
|
||||
{
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok);
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok, false, path);
|
||||
auto it = std::find_if(values.begin(), values.end(), [](const ValueFlow::Value& v) {
|
||||
return v.lifetimeKind == ValueFlow::Value::LifetimeKind::Iterator;
|
||||
});
|
||||
|
@ -2294,6 +2294,8 @@ void CheckStl::checkDereferenceInvalidIterator2()
|
|||
isInvalidIterator = true;
|
||||
} else {
|
||||
auto it = std::find_if(contValues.begin(), contValues.end(), [&](const ValueFlow::Value& c) {
|
||||
if (value.path != c.path)
|
||||
return false;
|
||||
if (value.isIteratorStartValue() && value.intvalue >= c.intvalue)
|
||||
return true;
|
||||
if (value.isIteratorEndValue() && -value.intvalue > c.intvalue)
|
||||
|
@ -2329,7 +2331,7 @@ void CheckStl::checkDereferenceInvalidIterator2()
|
|||
inconclusive = true;
|
||||
}
|
||||
if (cValue) {
|
||||
const ValueFlow::Value& lValue = getLifetimeIteratorValue(tok);
|
||||
const ValueFlow::Value& lValue = getLifetimeIteratorValue(tok, cValue->path);
|
||||
if (emptyAdvance)
|
||||
outOfBoundsError(emptyAdvance,
|
||||
lValue.tokvalue->expressionString(),
|
||||
|
|
|
@ -2426,7 +2426,7 @@ const ValueFlow::Value* Token::getMaxValue(bool condition, MathLib::bigint path)
|
|||
continue;
|
||||
if (value.isImpossible())
|
||||
continue;
|
||||
if (value.path != 0 && value.path != path)
|
||||
if (path > -0 && value.path != 0 && value.path != path)
|
||||
continue;
|
||||
if ((!ret || value.intvalue > ret->intvalue) &&
|
||||
((value.condition != nullptr) == condition))
|
||||
|
|
|
@ -2973,16 +2973,18 @@ std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, Error
|
|||
return msg;
|
||||
}
|
||||
|
||||
std::vector<ValueFlow::Value> getLifetimeObjValues(const Token *tok, bool inconclusive, bool subfunction)
|
||||
std::vector<ValueFlow::Value> getLifetimeObjValues(const Token* tok, bool inconclusive, MathLib::bigint path)
|
||||
{
|
||||
std::vector<ValueFlow::Value> result;
|
||||
auto pred = [&](const ValueFlow::Value &v) {
|
||||
if (!v.isLocalLifetimeValue() && !(subfunction && v.isSubFunctionLifetimeValue()))
|
||||
auto pred = [&](const ValueFlow::Value& v) {
|
||||
if (!v.isLocalLifetimeValue() && !(path != 0 && v.isSubFunctionLifetimeValue()))
|
||||
return false;
|
||||
if (!inconclusive && v.isInconclusive())
|
||||
return false;
|
||||
if (!v.tokvalue)
|
||||
return false;
|
||||
if (path >= 0 && v.path != 0 && v.path != path)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
std::copy_if(tok->values().begin(), tok->values().end(), std::back_inserter(result), pred);
|
||||
|
@ -2991,7 +2993,7 @@ std::vector<ValueFlow::Value> getLifetimeObjValues(const Token *tok, bool inconc
|
|||
|
||||
ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive)
|
||||
{
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok, inconclusive, false);
|
||||
std::vector<ValueFlow::Value> values = getLifetimeObjValues(tok, inconclusive);
|
||||
// There should only be one lifetime
|
||||
if (values.size() != 1)
|
||||
return ValueFlow::Value{};
|
||||
|
|
|
@ -513,6 +513,8 @@ std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, Value
|
|||
|
||||
CPPCHECKLIB ValueFlow::Value getLifetimeObjValue(const Token *tok, bool inconclusive = false);
|
||||
|
||||
CPPCHECKLIB std::vector<ValueFlow::Value> getLifetimeObjValues(const Token *tok, bool inconclusive = false, bool subfunction = false);
|
||||
CPPCHECKLIB std::vector<ValueFlow::Value> getLifetimeObjValues(const Token* tok,
|
||||
bool inconclusive = false,
|
||||
MathLib::bigint path = 0);
|
||||
|
||||
#endif // valueflowH
|
||||
|
|
|
@ -692,6 +692,19 @@ private:
|
|||
"test.cpp:2:note:condition 'i<=(int)v.size()'\n"
|
||||
"test.cpp:3:note:Access out of bounds\n",
|
||||
errout.str());
|
||||
|
||||
check("template<class Iterator>\n"
|
||||
"void b(Iterator d) {\n"
|
||||
" std::string c = \"a\";\n"
|
||||
" d + c.length();\n"
|
||||
"}\n"
|
||||
"void f() {\n"
|
||||
" std::string buf;\n"
|
||||
" b(buf.begin());\n"
|
||||
"}\n",
|
||||
true);
|
||||
ASSERT_EQUALS("test.cpp:4:error:Out of bounds access in expression 'd+c.length()' because 'buf' is empty.\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
void outOfBoundsSymbolic()
|
||||
|
|
Loading…
Reference in New Issue