bug hunting: Add array index check

This commit is contained in:
Daniel Marjamäki 2020-12-05 11:46:07 +01:00
parent a810678b83
commit 396c353d3c
2 changed files with 51 additions and 0 deletions

View File

@ -24,6 +24,9 @@
#include "token.h" #include "token.h"
#include <cstring> #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) static float getKnownFloatValue(const Token *tok, float def)
{ {
@ -34,6 +37,42 @@ static float getKnownFloatValue(const Token *tok, float def)
return 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) 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) void addBughuntingChecks(std::vector<ExprEngine::Callback> *callbacks)
{ {
callbacks->push_back(arrayIndex);
callbacks->push_back(bufferOverflow); callbacks->push_back(bufferOverflow);
callbacks->push_back(divByZero); callbacks->push_back(divByZero);
callbacks->push_back(checkFunctionCall); callbacks->push_back(checkFunctionCall);

View File

@ -36,6 +36,7 @@ private:
settings.inconclusive = true; settings.inconclusive = true;
LOAD_LIB_2(settings.library, "std.cfg"); LOAD_LIB_2(settings.library, "std.cfg");
TEST_CASE(checkAssignment); TEST_CASE(checkAssignment);
TEST_CASE(arrayIndexOutOfBounds1);
TEST_CASE(uninit); TEST_CASE(uninit);
TEST_CASE(uninit_array); TEST_CASE(uninit_array);
TEST_CASE(uninit_function_par); 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()); 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() { void uninit() {
check("void foo() { int x; x = x + 1; }"); check("void foo() { int x; x = x + 1; }");
ASSERT_EQUALS("[test.cpp:1]: (error) Cannot determine that 'x' is initialized\n", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (error) Cannot determine that 'x' is initialized\n", errout.str());