STL: Better out of bounds checking for empty containers when index is unknown
This commit is contained in:
parent
51b0ab0e77
commit
54bea2847a
|
@ -76,13 +76,16 @@ void CheckStl::outOfBounds()
|
||||||
if (Token::Match(tok, "%name% . %name% (") && container->getYield(tok->strAt(2)) == Library::Container::Yield::START_ITERATOR) {
|
if (Token::Match(tok, "%name% . %name% (") && container->getYield(tok->strAt(2)) == Library::Container::Yield::START_ITERATOR) {
|
||||||
const Token *parent = tok->tokAt(3)->astParent();
|
const Token *parent = tok->tokAt(3)->astParent();
|
||||||
const Token *other = nullptr;
|
const Token *other = nullptr;
|
||||||
if (Token::simpleMatch(parent, "+") && parent->astOperand1() && parent->astOperand1()->hasKnownIntValue())
|
if (Token::simpleMatch(parent, "+") && parent->astOperand1() == tok->tokAt(3))
|
||||||
other = parent->astOperand1();
|
|
||||||
else if (Token::simpleMatch(parent, "+") && parent->astOperand2() && parent->astOperand2()->hasKnownIntValue())
|
|
||||||
other = parent->astOperand2();
|
other = parent->astOperand2();
|
||||||
if (other && other->getKnownIntValue() > value.intvalue) {
|
else if (Token::simpleMatch(parent, "+") && parent->astOperand2() == tok->tokAt(3))
|
||||||
|
other = parent->astOperand1();
|
||||||
|
if (other && other->hasKnownIntValue() && other->getKnownIntValue() > value.intvalue) {
|
||||||
outOfBoundsError(parent, tok->str(), &value, other->expressionString(), &other->values().back());
|
outOfBoundsError(parent, tok->str(), &value, other->expressionString(), &other->values().back());
|
||||||
continue;
|
continue;
|
||||||
|
} else if (other && !other->hasKnownIntValue() && value.isKnown() && value.intvalue==0) {
|
||||||
|
outOfBoundsError(parent, tok->str(), &value, other->expressionString(), nullptr);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!container->arrayLike_indexOp && !container->stdStringLike)
|
if (!container->arrayLike_indexOp && !container->stdStringLike)
|
||||||
|
@ -124,6 +127,8 @@ void CheckStl::outOfBoundsError(const Token *tok, const std::string &containerNa
|
||||||
else if (containerSize->intvalue == 0) {
|
else if (containerSize->intvalue == 0) {
|
||||||
if (containerSize->condition)
|
if (containerSize->condition)
|
||||||
errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or expression '" + expression + "' cause access out of bounds.";
|
errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or expression '" + expression + "' cause access out of bounds.";
|
||||||
|
else if (indexValue == nullptr && !index.empty())
|
||||||
|
errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty and '" + index + "' may be non-zero.";
|
||||||
else
|
else
|
||||||
errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty.";
|
errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty.";
|
||||||
} else if (indexValue) {
|
} else if (indexValue) {
|
||||||
|
|
|
@ -280,6 +280,12 @@ private:
|
||||||
" x = s.begin() + 1;\n"
|
" x = s.begin() + 1;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+1' because 's' is empty.\n", errout.str());
|
ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+1' because 's' is empty.\n", errout.str());
|
||||||
|
|
||||||
|
checkNormal("void f(int x) {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" x = s.begin() + x;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void outOfBoundsIndexExpression() {
|
void outOfBoundsIndexExpression() {
|
||||||
|
|
Loading…
Reference in New Issue