Skip to content

Commit 04235e2

Browse files
committed
checkimpl incomplete
1 parent 847fbbc commit 04235e2

2 files changed

Lines changed: 91 additions & 88 deletions

File tree

lib/checkbufferoverrun.cpp

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "checkbufferoverrun.h"
2424

2525
#include "astutils.h"
26+
#include "checkimpl.h"
2627
#include "errorlogger.h"
2728
#include "library.h"
2829
#include "mathlib.h"
@@ -63,6 +64,46 @@ static const CWE CWE_BUFFER_OVERRUN(788U); // Access of Memory Location After
6364

6465
//---------------------------------------------------------------------------
6566

67+
class CheckBufferOverrunImpl : public CheckImpl
68+
{
69+
public:
70+
/** This constructor is used when running checks. */
71+
CheckBufferOverrunImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
72+
: CheckImpl(tokenizer, settings, errorLogger) {}
73+
74+
void arrayIndex();
75+
void arrayIndexError(const Token* tok,
76+
const std::vector<Dimension>& dimensions,
77+
const std::vector<ValueFlow::Value>& indexes);
78+
void negativeIndexError(const Token* tok,
79+
const std::vector<Dimension>& dimensions,
80+
const std::vector<ValueFlow::Value>& indexes);
81+
82+
void pointerArithmetic();
83+
void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue);
84+
85+
void bufferOverflow();
86+
void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty);
87+
88+
void arrayIndexThenCheck();
89+
void arrayIndexThenCheckError(const Token *tok, const std::string &indexName);
90+
91+
void stringNotZeroTerminated();
92+
void terminateStrncpyError(const Token *tok, const std::string &varname);
93+
94+
void argumentSize();
95+
void argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string &paramExpression, const Variable *paramVar, const Variable *functionArg);
96+
97+
void negativeArraySize();
98+
void negativeArraySizeError(const Token* tok);
99+
void negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value); // provide a negative value to memory allocation function
100+
101+
void objectIndex();
102+
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known);
103+
104+
ValueFlow::Value getBufferSize(const Token *bufTok) const;
105+
};
106+
66107
static const ValueFlow::Value *getBufferSizeValue(const Token *tok)
67108
{
68109
const std::list<ValueFlow::Value> &tokenValues = tok->values();
@@ -278,7 +319,7 @@ static std::vector<ValueFlow::Value> getOverrunIndexValues(const Token* tok,
278319
return {};
279320
}
280321

281-
void CheckBufferOverrun::arrayIndex()
322+
void CheckBufferOverrunImpl::arrayIndex()
282323
{
283324
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
284325
if (tok->str() != "[")
@@ -397,7 +438,7 @@ static std::string arrayIndexMessage(const Token* tok,
397438
return errmsg.str();
398439
}
399440

400-
void CheckBufferOverrun::arrayIndexError(const Token* tok,
441+
void CheckBufferOverrunImpl::arrayIndexError(const Token* tok,
401442
const std::vector<Dimension>& dimensions,
402443
const std::vector<ValueFlow::Value>& indexes)
403444
{
@@ -426,7 +467,7 @@ void CheckBufferOverrun::arrayIndexError(const Token* tok,
426467
index->isInconclusive() ? Certainty::inconclusive : Certainty::normal);
427468
}
428469

429-
void CheckBufferOverrun::negativeIndexError(const Token* tok,
470+
void CheckBufferOverrunImpl::negativeIndexError(const Token* tok,
430471
const std::vector<Dimension>& dimensions,
431472
const std::vector<ValueFlow::Value>& indexes)
432473
{
@@ -456,7 +497,7 @@ void CheckBufferOverrun::negativeIndexError(const Token* tok,
456497

457498
//---------------------------------------------------------------------------
458499

459-
void CheckBufferOverrun::pointerArithmetic()
500+
void CheckBufferOverrunImpl::pointerArithmetic()
460501
{
461502
if (!mSettings->severity.isEnabled(Severity::portability))
462503
return;
@@ -518,7 +559,7 @@ void CheckBufferOverrun::pointerArithmetic()
518559
}
519560
}
520561

521-
void CheckBufferOverrun::pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue)
562+
void CheckBufferOverrunImpl::pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue)
522563
{
523564
if (!tok) {
524565
reportError(tok, Severity::portability, "pointerOutOfBounds", "Pointer arithmetic overflow.", CWE_POINTER_ARITHMETIC_OVERFLOW, Certainty::normal);
@@ -542,7 +583,7 @@ void CheckBufferOverrun::pointerArithmeticError(const Token *tok, const Token *i
542583

543584
//---------------------------------------------------------------------------
544585

545-
ValueFlow::Value CheckBufferOverrun::getBufferSize(const Token *bufTok) const
586+
ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok) const
546587
{
547588
if (!bufTok->valueType())
548589
return ValueFlow::Value(-1);
@@ -624,7 +665,7 @@ static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::Mi
624665
}
625666

626667

627-
void CheckBufferOverrun::bufferOverflow()
668+
void CheckBufferOverrunImpl::bufferOverflow()
628669
{
629670
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
630671
for (const Scope * scope : symbolDatabase->functionScopes) {
@@ -679,14 +720,14 @@ void CheckBufferOverrun::bufferOverflow()
679720
}
680721
}
681722

682-
void CheckBufferOverrun::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty)
723+
void CheckBufferOverrunImpl::bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty)
683724
{
684725
reportError(getErrorPath(tok, value, "Buffer overrun"), Severity::error, "bufferAccessOutOfBounds", "Buffer is accessed out of bounds: " + (tok ? tok->expressionString() : "buf"), CWE_BUFFER_OVERRUN, certainty);
685726
}
686727

687728
//---------------------------------------------------------------------------
688729

689-
void CheckBufferOverrun::arrayIndexThenCheck()
730+
void CheckBufferOverrunImpl::arrayIndexThenCheck()
690731
{
691732
if (!mSettings->severity.isEnabled(Severity::portability))
692733
return;
@@ -728,7 +769,7 @@ void CheckBufferOverrun::arrayIndexThenCheck()
728769
}
729770
}
730771

731-
void CheckBufferOverrun::arrayIndexThenCheckError(const Token *tok, const std::string &indexName)
772+
void CheckBufferOverrunImpl::arrayIndexThenCheckError(const Token *tok, const std::string &indexName)
732773
{
733774
reportError(tok, Severity::style, "arrayIndexThenCheck",
734775
"$symbol:" + indexName + "\n"
@@ -741,7 +782,7 @@ void CheckBufferOverrun::arrayIndexThenCheckError(const Token *tok, const std::s
741782

742783
//---------------------------------------------------------------------------
743784

744-
void CheckBufferOverrun::stringNotZeroTerminated()
785+
void CheckBufferOverrunImpl::stringNotZeroTerminated()
745786
{
746787
// this is currently 'inconclusive'. See TestBufferOverrun::terminateStrncpy3
747788
if (!mSettings->severity.isEnabled(Severity::warning) || !mSettings->certainty.isEnabled(Certainty::inconclusive))
@@ -791,7 +832,7 @@ void CheckBufferOverrun::stringNotZeroTerminated()
791832
}
792833
}
793834

794-
void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::string &varname)
835+
void CheckBufferOverrunImpl::terminateStrncpyError(const Token *tok, const std::string &varname)
795836
{
796837
const std::string shortMessage = "The buffer '$symbol' may not be null-terminated after the call to strncpy().";
797838
reportError(tok, Severity::warning, "terminateStrncpy",
@@ -804,7 +845,7 @@ void CheckBufferOverrun::terminateStrncpyError(const Token *tok, const std::stri
804845
}
805846
//---------------------------------------------------------------------------
806847

807-
void CheckBufferOverrun::argumentSize()
848+
void CheckBufferOverrunImpl::argumentSize()
808849
{
809850
// Check '%type% x[10]' arguments
810851
if (!mSettings->severity.isEnabled(Severity::warning))
@@ -850,7 +891,7 @@ void CheckBufferOverrun::argumentSize()
850891
}
851892
}
852893

853-
void CheckBufferOverrun::argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string &paramExpression, const Variable *paramVar, const Variable *functionArg)
894+
void CheckBufferOverrunImpl::argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string &paramExpression, const Variable *paramVar, const Variable *functionArg)
854895
{
855896
const std::string strParamNum = std::to_string(paramIndex + 1) + getOrdinalText(paramIndex + 1);
856897
ErrorPath errorPath;
@@ -917,7 +958,7 @@ bool CheckBufferOverrun::isCtuUnsafePointerArith(const Check *check, const Token
917958
/** @brief Parse current TU and extract file info */
918959
Check::FileInfo *CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
919960
{
920-
CheckBufferOverrun checkBufferOverrun(tokenizer, settings, nullptr);
961+
CheckBufferOverrunImpl checkBufferOverrun(tokenizer, settings, nullptr);
921962
MyFileInfo *fileInfo = new MyFileInfo;
922963
fileInfo->unsafeArrayIndex = CTU::getUnsafeUsage(tokenizer, settings, &checkBufferOverrun, isCtuUnsafeArrayIndex);
923964
fileInfo->unsafePointerArith = CTU::getUnsafeUsage(tokenizer, settings, &checkBufferOverrun, isCtuUnsafePointerArith);
@@ -1013,7 +1054,7 @@ bool CheckBufferOverrun::analyseWholeProgram1(const std::map<std::string, std::l
10131054
return true;
10141055
}
10151056

1016-
void CheckBufferOverrun::objectIndex()
1057+
void CheckBufferOverrunImpl::objectIndex()
10171058
{
10181059
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
10191060
for (const Scope *functionScope : symbolDatabase->functionScopes) {
@@ -1086,7 +1127,7 @@ void CheckBufferOverrun::objectIndex()
10861127
}
10871128
}
10881129

1089-
void CheckBufferOverrun::objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known)
1130+
void CheckBufferOverrunImpl::objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known)
10901131
{
10911132
ErrorPath errorPath;
10921133
std::string name;
@@ -1120,7 +1161,7 @@ static bool isVLAIndex(const Token* tok)
11201161
return isVLAIndex(tok->astOperand1()) || isVLAIndex(tok->astOperand2());
11211162
}
11221163

1123-
void CheckBufferOverrun::negativeArraySize()
1164+
void CheckBufferOverrunImpl::negativeArraySize()
11241165
{
11251166
const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
11261167
for (const Variable* var : symbolDatabase->variableList()) {
@@ -1149,7 +1190,7 @@ void CheckBufferOverrun::negativeArraySize()
11491190
}
11501191
}
11511192

1152-
void CheckBufferOverrun::negativeArraySizeError(const Token* tok)
1193+
void CheckBufferOverrunImpl::negativeArraySizeError(const Token* tok)
11531194
{
11541195
const std::string arrayName = tok ? tok->expressionString() : std::string();
11551196
const std::string line1 = arrayName.empty() ? std::string() : ("$symbol:" + arrayName + '\n');
@@ -1158,11 +1199,38 @@ void CheckBufferOverrun::negativeArraySizeError(const Token* tok)
11581199
"Declaration of array '" + arrayName + "' with negative size is undefined behaviour", CWE758, Certainty::normal);
11591200
}
11601201

1161-
void CheckBufferOverrun::negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value)
1202+
void CheckBufferOverrunImpl::negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value)
11621203
{
11631204
const std::string msg = "Memory allocation size is negative.";
11641205
const ErrorPath errorPath = getErrorPath(tok, value, msg);
11651206
const bool inconclusive = value != nullptr && !value->isKnown();
11661207
reportError(errorPath, inconclusive ? Severity::warning : Severity::error, "negativeMemoryAllocationSize",
11671208
msg, CWE131, inconclusive ? Certainty::inconclusive : Certainty::normal);
11681209
}
1210+
1211+
void CheckBufferOverrun::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger)
1212+
{
1213+
CheckBufferOverrunImpl checkBufferOverrun(&tokenizer, tokenizer.getSettings(), errorLogger);
1214+
checkBufferOverrun.arrayIndex();
1215+
checkBufferOverrun.pointerArithmetic();
1216+
checkBufferOverrun.bufferOverflow();
1217+
checkBufferOverrun.arrayIndexThenCheck();
1218+
checkBufferOverrun.stringNotZeroTerminated();
1219+
checkBufferOverrun.objectIndex();
1220+
checkBufferOverrun.argumentSize();
1221+
checkBufferOverrun.negativeArraySize();
1222+
}
1223+
1224+
void CheckBufferOverrun::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const
1225+
{
1226+
CheckBufferOverrunImpl c(nullptr, settings, errorLogger);
1227+
c.arrayIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
1228+
c.pointerArithmeticError(nullptr, nullptr, nullptr);
1229+
c.negativeIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
1230+
c.arrayIndexThenCheckError(nullptr, "i");
1231+
c.bufferOverflowError(nullptr, nullptr, Certainty::normal);
1232+
c.objectIndexError(nullptr, nullptr, true);
1233+
c.argumentSizeError(nullptr, "function", 1, "buffer", nullptr, nullptr);
1234+
c.negativeMemoryAllocationSizeError(nullptr, nullptr);
1235+
c.negativeArraySizeError(nullptr);
1236+
}

lib/checkbufferoverrun.h

Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -60,36 +60,9 @@ class CPPCHECKLIB CheckBufferOverrun : public Check {
6060
public:
6161

6262
/** This constructor is used when registering the CheckClass */
63-
CheckBufferOverrun() : Check(myName()) {}
64-
65-
/** This constructor is used when running checks. */
66-
CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
67-
: Check(myName(), tokenizer, settings, errorLogger) {}
68-
69-
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
70-
CheckBufferOverrun checkBufferOverrun(&tokenizer, tokenizer.getSettings(), errorLogger);
71-
checkBufferOverrun.arrayIndex();
72-
checkBufferOverrun.pointerArithmetic();
73-
checkBufferOverrun.bufferOverflow();
74-
checkBufferOverrun.arrayIndexThenCheck();
75-
checkBufferOverrun.stringNotZeroTerminated();
76-
checkBufferOverrun.objectIndex();
77-
checkBufferOverrun.argumentSize();
78-
checkBufferOverrun.negativeArraySize();
79-
}
63+
CheckBufferOverrun() : Check("Bounds checking") {}
8064

81-
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
82-
CheckBufferOverrun c(nullptr, settings, errorLogger);
83-
c.arrayIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
84-
c.pointerArithmeticError(nullptr, nullptr, nullptr);
85-
c.negativeIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
86-
c.arrayIndexThenCheckError(nullptr, "i");
87-
c.bufferOverflowError(nullptr, nullptr, Certainty::normal);
88-
c.objectIndexError(nullptr, nullptr, true);
89-
c.argumentSizeError(nullptr, "function", 1, "buffer", nullptr, nullptr);
90-
c.negativeMemoryAllocationSizeError(nullptr, nullptr);
91-
c.negativeArraySizeError(nullptr);
92-
}
65+
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override;
9366

9467
/** @brief Parse current TU and extract file info */
9568
Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const override;
@@ -98,40 +71,7 @@ class CPPCHECKLIB CheckBufferOverrun : public Check {
9871
bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override;
9972

10073
private:
101-
102-
void arrayIndex();
103-
void arrayIndexError(const Token* tok,
104-
const std::vector<Dimension>& dimensions,
105-
const std::vector<ValueFlow::Value>& indexes);
106-
void negativeIndexError(const Token* tok,
107-
const std::vector<Dimension>& dimensions,
108-
const std::vector<ValueFlow::Value>& indexes);
109-
110-
void pointerArithmetic();
111-
void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue);
112-
113-
void bufferOverflow();
114-
void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty);
115-
116-
void arrayIndexThenCheck();
117-
void arrayIndexThenCheckError(const Token *tok, const std::string &indexName);
118-
119-
void stringNotZeroTerminated();
120-
void terminateStrncpyError(const Token *tok, const std::string &varname);
121-
122-
void argumentSize();
123-
void argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string &paramExpression, const Variable *paramVar, const Variable *functionArg);
124-
125-
void negativeArraySize();
126-
void negativeArraySizeError(const Token* tok);
127-
void negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value); // provide a negative value to memory allocation function
128-
129-
void objectIndex();
130-
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known);
131-
132-
ValueFlow::Value getBufferSize(const Token *bufTok) const;
133-
134-
// CTU
74+
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override;
13575

13676
/** data for multifile checking */
13777
class MyFileInfo : public Check::FileInfo {
@@ -153,11 +93,6 @@ class CPPCHECKLIB CheckBufferOverrun : public Check {
15393
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override;
15494
static bool analyseWholeProgram1(const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, int type, ErrorLogger &errorLogger);
15595

156-
157-
static std::string myName() {
158-
return "Bounds checking";
159-
}
160-
16196
std::string classInfo() const override {
16297
return "Out of bounds checking:\n"
16398
"- Array index out of bounds\n"

0 commit comments

Comments
 (0)