Fix issue 10120: FP: containerOutOfBounds, regression (#3064)

This commit is contained in:
Paul Fultz II 2021-01-21 12:50:57 -06:00 committed by GitHub
parent 8b26ecbcdd
commit d05acf3c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 6 deletions

View File

@ -42,6 +42,7 @@ struct Analyzer {
Inconclusive = (1 << 3), Inconclusive = (1 << 3),
Match = (1 << 4), Match = (1 << 4),
Idempotent = (1 << 5), Idempotent = (1 << 5),
Incremental = (1 << 6),
}; };
void set(unsigned int f, bool state = true) { void set(unsigned int f, bool state = true) {
@ -80,6 +81,10 @@ struct Analyzer {
return get(Idempotent); return get(Idempotent);
} }
bool isIncremental() const {
return get(Incremental);
}
bool matches() const { bool matches() const {
return get(Match); return get(Match);
} }

View File

@ -320,12 +320,14 @@ struct ForwardTraversal {
Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&Analyzer::Action::isModified)); Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&Analyzer::Action::isModified));
const Token* nextStatement = Token::findmatch(writeTok, ";|}", endBlock); const Token* nextStatement = Token::findmatch(writeTok, ";|}", endBlock);
if (!Token::Match(nextStatement, ";|} break ;")) { if (!Token::Match(nextStatement, ";|} break ;")) {
continueUpdateRangeAfterLoop(ftv, endBlock, endToken); if (!allAnalysis.isIncremental())
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
return Break(Terminate::Bail); return Break(Terminate::Bail);
} }
} else { } else {
if (stepTok && updateRecursive(stepTok) == Progress::Break) { if (stepTok && updateRecursive(stepTok) == Progress::Break) {
continueUpdateRangeAfterLoop(ftv, endBlock, endToken); if (!allAnalysis.isIncremental())
continueUpdateRangeAfterLoop(ftv, endBlock, endToken);
return Break(Terminate::Bail); return Break(Terminate::Bail);
} }
} }

View File

@ -1893,13 +1893,14 @@ struct ValueFlowAnalyzer : Analyzer {
} else { } else {
if (rhsValue && !value->isImpossible() && value->equalValue(*rhsValue)) if (rhsValue && !value->isImpossible() && value->equalValue(*rhsValue))
a = Action::Idempotent; a = Action::Idempotent;
a |= Action::Incremental;
} }
return a; return a;
} }
// increment/decrement // increment/decrement
if (Token::Match(tok->previous(), "++|-- %name%") || Token::Match(tok, "%name% ++|--")) { if (Token::Match(tok->previous(), "++|-- %name%") || Token::Match(tok, "%name% ++|--")) {
return Action::Read | Action::Write; return Action::Read | Action::Write | Action::Incremental;
} }
return Action::None; return Action::None;
} }
@ -5706,17 +5707,17 @@ struct ContainerVariableAnalyzer : VariableAnalyzer {
if (tok->valueType()->container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) { if (tok->valueType()->container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
const Token* rhs = parent->astOperand2(); const Token* rhs = parent->astOperand2();
if (rhs->tokType() == Token::eString) if (rhs->tokType() == Token::eString)
return Action::Read | Action::Write; return Action::Read | Action::Write | Action::Incremental;
if (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) { if (rhs->valueType() && rhs->valueType()->container && rhs->valueType()->container->stdStringLike) {
if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) { if (std::any_of(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value &rhsval) {
return rhsval.isKnown() && rhsval.isContainerSizeValue(); return rhsval.isKnown() && rhsval.isContainerSizeValue();
})) }))
return Action::Read | Action::Write; return Action::Read | Action::Write | Action::Incremental;
} }
} else if (Token::Match(tok, "%name% . %name% (")) { } else if (Token::Match(tok, "%name% . %name% (")) {
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2)); Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP)
return Action::Read | Action::Write; return Action::Read | Action::Write | Action::Incremental;
} }
return Action::None; return Action::None;
} }

View File

@ -380,6 +380,22 @@ private:
" return ArrS[0];\n" " return ArrS[0];\n"
"}\n", true); "}\n", true);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkNormal("extern void Bar(const double, const double);\n"
"void f(std::vector<double> &r, const double ) {\n"
" std::vector<double> result;\n"
" double d = 0.0;\n"
" const double inc = 0.1;\n"
" for(unsigned int i = 0; i < 10; ++i) {\n"
" result.push_back(d);\n"
" d = (i + 1) * inc;\n"
" }\n"
" Bar(1.0, d);\n"
" Bar(10U, result.size());\n"
" Bar(0.0, result[0]);\n"
" Bar(0.34, result[1]);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void outOfBoundsIndexExpression() { void outOfBoundsIndexExpression() {