Fixed #1693 (false negative: std::vector, negative index)
This commit is contained in:
parent
0cae823c5d
commit
2679b576c2
|
@ -44,6 +44,7 @@ static const struct CWE CWE628(628U); // Function Call with Incorrectly Specif
|
||||||
static const struct CWE CWE664(664U); // Improper Control of a Resource Through its Lifetime
|
static const struct CWE CWE664(664U); // Improper Control of a Resource Through its Lifetime
|
||||||
static const struct CWE CWE704(704U); // Incorrect Type Conversion or Cast
|
static const struct CWE CWE704(704U); // Incorrect Type Conversion or Cast
|
||||||
static const struct CWE CWE762(762U); // Mismatched Memory Management Routines
|
static const struct CWE CWE762(762U); // Mismatched Memory Management Routines
|
||||||
|
static const struct CWE CWE786(786U); // Access of Memory Location Before Start of Buffer
|
||||||
static const struct CWE CWE788(788U); // Access of Memory Location After End of Buffer
|
static const struct CWE CWE788(788U); // Access of Memory Location After End of Buffer
|
||||||
static const struct CWE CWE825(825U); // Expired Pointer Dereference
|
static const struct CWE CWE825(825U); // Expired Pointer Dereference
|
||||||
static const struct CWE CWE834(834U); // Excessive Iteration
|
static const struct CWE CWE834(834U); // Excessive Iteration
|
||||||
|
@ -437,6 +438,42 @@ void CheckStl::stlOutOfBoundsError(const Token *tok, const std::string &num, con
|
||||||
reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + "[" + num + "] is out of bounds.", CWE788, false);
|
reportError(tok, Severity::error, "stlOutOfBounds", "When " + num + "==" + var + ".size(), " + var + "[" + num + "] is out of bounds.", CWE788, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckStl::negativeIndex()
|
||||||
|
{
|
||||||
|
// Negative index is out of bounds..
|
||||||
|
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t ii = 0; ii < functions; ++ii) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[ii];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (!Token::Match(tok, "%var% ["))
|
||||||
|
continue;
|
||||||
|
const Variable * const var = tok->variable();
|
||||||
|
if (!var || tok == var->nameToken())
|
||||||
|
continue;
|
||||||
|
const Library::Container * const container = _settings->library.detectContainer(var->typeStartToken());
|
||||||
|
if (!container || !container->arrayLike_indexOp)
|
||||||
|
continue;
|
||||||
|
const ValueFlow::Value *index = tok->next()->astOperand2()->getValueLE(-1, _settings);
|
||||||
|
if (!index)
|
||||||
|
continue;
|
||||||
|
negativeIndexError(tok, *index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckStl::negativeIndexError(const Token *tok, const ValueFlow::Value &index)
|
||||||
|
{
|
||||||
|
const ErrorPath errorPath = getErrorPath(tok, &index, "Negative array index");
|
||||||
|
std::ostringstream errmsg;
|
||||||
|
if (index.condition)
|
||||||
|
errmsg << ValueFlow::eitherTheConditionIsRedundant(index.condition)
|
||||||
|
<< ", otherwise there is negative array index " << index.intvalue << ".";
|
||||||
|
else
|
||||||
|
errmsg << "Array index " << index.intvalue << " is out of bounds.";
|
||||||
|
reportError(errorPath, index.errorSeverity() ? Severity::error : Severity::warning, "negativeContainerIndex", errmsg.str(), CWE786, index.inconclusive);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStl::erase()
|
void CheckStl::erase()
|
||||||
{
|
{
|
||||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
CheckStl checkStl(tokenizer, settings, errorLogger);
|
CheckStl checkStl(tokenizer, settings, errorLogger);
|
||||||
|
|
||||||
checkStl.stlOutOfBounds();
|
checkStl.stlOutOfBounds();
|
||||||
|
checkStl.negativeIndex();
|
||||||
checkStl.iterators();
|
checkStl.iterators();
|
||||||
checkStl.mismatchingContainers();
|
checkStl.mismatchingContainers();
|
||||||
checkStl.erase();
|
checkStl.erase();
|
||||||
|
@ -86,6 +87,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void stlOutOfBounds();
|
void stlOutOfBounds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* negative index for array like containers
|
||||||
|
*/
|
||||||
|
void negativeIndex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds errors like this:
|
* Finds errors like this:
|
||||||
* for (it = foo.begin(); it != bar.end(); ++it)
|
* for (it = foo.begin(); it != bar.end(); ++it)
|
||||||
|
@ -171,6 +177,7 @@ private:
|
||||||
void string_c_strParam(const Token *tok, unsigned int number);
|
void string_c_strParam(const Token *tok, unsigned int number);
|
||||||
|
|
||||||
void stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at);
|
void stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var, bool at);
|
||||||
|
void negativeIndexError(const Token *tok, const ValueFlow::Value &index);
|
||||||
void invalidIteratorError(const Token *tok, const std::string &iteratorName);
|
void invalidIteratorError(const Token *tok, const std::string &iteratorName);
|
||||||
void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2);
|
void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2);
|
||||||
void mismatchingContainersError(const Token *tok);
|
void mismatchingContainersError(const Token *tok);
|
||||||
|
@ -203,6 +210,7 @@ private:
|
||||||
c.mismatchingContainersError(nullptr);
|
c.mismatchingContainersError(nullptr);
|
||||||
c.dereferenceErasedError(nullptr, nullptr, "iter");
|
c.dereferenceErasedError(nullptr, nullptr, "iter");
|
||||||
c.stlOutOfBoundsError(nullptr, "i", "foo", false);
|
c.stlOutOfBoundsError(nullptr, "i", "foo", false);
|
||||||
|
c.negativeIndexError(nullptr, ValueFlow::Value(-1));
|
||||||
c.invalidIteratorError(nullptr, "push_back|push_front|insert", "iterator");
|
c.invalidIteratorError(nullptr, "push_back|push_front|insert", "iterator");
|
||||||
c.invalidPointerError(nullptr, "push_back", "pointer");
|
c.invalidPointerError(nullptr, "push_back", "pointer");
|
||||||
c.stlBoundariesError(nullptr);
|
c.stlBoundariesError(nullptr);
|
||||||
|
|
|
@ -60,6 +60,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(STLSize);
|
TEST_CASE(STLSize);
|
||||||
TEST_CASE(STLSizeNoErr);
|
TEST_CASE(STLSizeNoErr);
|
||||||
|
TEST_CASE(negativeIndex);
|
||||||
TEST_CASE(erase1);
|
TEST_CASE(erase1);
|
||||||
TEST_CASE(erase2);
|
TEST_CASE(erase2);
|
||||||
TEST_CASE(erase3);
|
TEST_CASE(erase3);
|
||||||
|
@ -720,7 +721,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void negativeIndex() {
|
||||||
|
check("void f(const std::vector<int> &v) {\n"
|
||||||
|
" v[-11] = 123;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Array index -11 is out of bounds.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue