bug hunting: Add array index check
This commit is contained in:
parent
a810678b83
commit
396c353d3c
|
@ -24,6 +24,9 @@
|
|||
#include "token.h"
|
||||
#include <cstring>
|
||||
|
||||
static const CWE CWE_BUFFER_UNDERRUN(786U); // Access of Memory Location Before Start of Buffer
|
||||
static const CWE CWE_BUFFER_OVERRUN(788U); // Access of Memory Location After End of Buffer
|
||||
|
||||
|
||||
static float getKnownFloatValue(const Token *tok, float def)
|
||||
{
|
||||
|
@ -34,6 +37,42 @@ static float getKnownFloatValue(const Token *tok, float def)
|
|||
return def;
|
||||
}
|
||||
|
||||
static void arrayIndex(const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase)
|
||||
{
|
||||
if (!Token::simpleMatch(tok->astParent(), "["))
|
||||
return;
|
||||
const Token *buf = tok->astParent()->astOperand1();
|
||||
if (!buf || !buf->variable() || !buf->variable()->isArray())
|
||||
// TODO
|
||||
return;
|
||||
const Token *index = tok->astParent()->astOperand2();
|
||||
if (tok != index)
|
||||
// TODO
|
||||
return;
|
||||
if (buf->variable()->dimensions().size() == 1 && buf->variable()->dimensions()[0].known) {
|
||||
const MathLib::bigint bufSize = buf->variable()->dimensions()[0].num;
|
||||
if (value.isGreaterThan(dataBase, bufSize - 1)) {
|
||||
const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue);
|
||||
dataBase->reportError(tok,
|
||||
Severity::SeverityType::error,
|
||||
"bughuntingArrayIndexOutOfBounds",
|
||||
"Array index out of bounds, cannot determine that " + index->expressionString() + " is less than " + std::to_string(bufSize),
|
||||
CWE_BUFFER_OVERRUN,
|
||||
false,
|
||||
bailout);
|
||||
}
|
||||
}
|
||||
if (value.isLessThan(dataBase, 0)) {
|
||||
const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue);
|
||||
dataBase->reportError(tok,
|
||||
Severity::SeverityType::error,
|
||||
"bughuntingArrayIndexNegative",
|
||||
"Array index out of bounds, cannot determine that " + index->expressionString() + " is not negative",
|
||||
CWE_BUFFER_UNDERRUN,
|
||||
false,
|
||||
bailout);
|
||||
}
|
||||
}
|
||||
|
||||
static void bufferOverflow(const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase)
|
||||
{
|
||||
|
@ -565,6 +604,7 @@ static void checkAssignment(const Token *tok, const ExprEngine::Value &value, Ex
|
|||
|
||||
void addBughuntingChecks(std::vector<ExprEngine::Callback> *callbacks)
|
||||
{
|
||||
callbacks->push_back(arrayIndex);
|
||||
callbacks->push_back(bufferOverflow);
|
||||
callbacks->push_back(divByZero);
|
||||
callbacks->push_back(checkFunctionCall);
|
||||
|
|
|
@ -36,6 +36,7 @@ private:
|
|||
settings.inconclusive = true;
|
||||
LOAD_LIB_2(settings.library, "std.cfg");
|
||||
TEST_CASE(checkAssignment);
|
||||
TEST_CASE(arrayIndexOutOfBounds1);
|
||||
TEST_CASE(uninit);
|
||||
TEST_CASE(uninit_array);
|
||||
TEST_CASE(uninit_function_par);
|
||||
|
@ -67,6 +68,16 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:2]: (error) There is assignment, cannot determine that value is greater or equal with 0\n", errout.str());
|
||||
}
|
||||
|
||||
void arrayIndexOutOfBounds1() {
|
||||
check("void foo(int x) {\n"
|
||||
" int p[8];"
|
||||
" p[x] = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (error) Array index out of bounds, cannot determine that x is less than 8\n"
|
||||
"[test.cpp:2]: (error) Array index out of bounds, cannot determine that x is not negative\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
void uninit() {
|
||||
check("void foo() { int x; x = x + 1; }");
|
||||
ASSERT_EQUALS("[test.cpp:1]: (error) Cannot determine that 'x' is initialized\n", errout.str());
|
||||
|
|
Loading…
Reference in New Issue