bug hunting: Add array index check
This commit is contained in:
parent
a810678b83
commit
396c353d3c
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in New Issue