Skip to content

Commit 9eb16e1

Browse files
authored
Replaced check for pipe() buffer size by ordinary CheckBufferOverrun, provide required Library configuration option (#4183)
Merged from LCppC.
1 parent 6873f52 commit 9eb16e1

13 files changed

Lines changed: 91 additions & 169 deletions

cfg/cppcheck-cfg.rng

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@
306306
<attribute name="value">
307307
<ref name="MINSIZE-VALUE"/>
308308
</attribute>
309+
<optional>
310+
<attribute name="baseType"><text/></attribute>
311+
</optional>
309312
</element>
310313
</choice>
311314
</zeroOrMore>

cfg/gnu.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@
414414
<arg nr="1" direction="out">
415415
<not-null/>
416416
<not-bool/>
417-
<minsize type="value" value="2"/>
417+
<minsize type="value" value="2" baseType="int"/>
418418
</arg>
419419
<arg nr="2" direction="in">
420420
<not-uninit/>

cfg/posix.cfg

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,7 +1742,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
17421742
<arg nr="2" direction="in">
17431743
<not-uninit/>
17441744
<not-bool/>
1745-
<minsize type="value" value="2"/>
1745+
<minsize type="value" value="2" baseType="timespec"/>
17461746
</arg>
17471747
</function>
17481748
<!-- int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags);-->
@@ -1762,7 +1762,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
17621762
<arg nr="3" direction="in">
17631763
<not-uninit/>
17641764
<not-bool/>
1765-
<minsize type="value" value="2"/>
1765+
<minsize type="value" value="2" baseType="timespec"/>
17661766
</arg>
17671767
<arg nr="4" direction="in">
17681768
<not-uninit/>
@@ -1782,7 +1782,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
17821782
<arg nr="2" direction="in">
17831783
<not-uninit/>
17841784
<not-bool/>
1785-
<minsize type="value" value="2"/>
1785+
<minsize type="value" value="2" baseType="timeval"/>
17861786
</arg>
17871787
<warn severity="style" reason="Obsolescent" alternatives="utimensat"/>
17881788
</function>
@@ -2749,7 +2749,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
27492749
<arg nr="4" direction="out">
27502750
<not-null/>
27512751
<not-bool/>
2752-
<minsize type="value" value="2"/>
2752+
<minsize type="value" value="2" baseType="int"/>
27532753
</arg>
27542754
</function>
27552755
<!-- http://man7.org/linux/man-pages/man2/socketpair.2.html -->
@@ -2761,7 +2761,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
27612761
<arg nr="1" direction="out">
27622762
<not-null/>
27632763
<not-bool/>
2764-
<minsize type="value" value="2"/>
2764+
<minsize type="value" value="2" baseType="int"/>
27652765
</arg>
27662766
</function>
27672767
<!-- int pselect(int nfds, fd_set *restrict readfds,

lib/checkbufferoverrun.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ ValueFlow::Value CheckBufferOverrun::getBufferSize(const Token *bufTok) const
563563
}
564564
//---------------------------------------------------------------------------
565565

566-
static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::MinSize &minsize, const std::vector<const Token *> &args, const MathLib::bigint bufferSize, const Settings *settings)
566+
static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::MinSize &minsize, const std::vector<const Token *> &args, const MathLib::bigint bufferSize, const Settings *settings, const Tokenizer* tokenizer)
567567
{
568568
const Token * const arg = (minsize.arg > 0 && minsize.arg - 1 < args.size()) ? args[minsize.arg - 1] : nullptr;
569569
const Token * const arg2 = (minsize.arg2 > 0 && minsize.arg2 - 1 < args.size()) ? args[minsize.arg2 - 1] : nullptr;
@@ -589,8 +589,13 @@ static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::Mi
589589
if (arg && arg2 && arg->hasKnownIntValue() && arg2->hasKnownIntValue())
590590
return (arg->getKnownIntValue() * arg2->getKnownIntValue()) <= bufferSize;
591591
break;
592-
case Library::ArgumentChecks::MinSize::Type::VALUE:
593-
return minsize.value <= bufferSize;
592+
case Library::ArgumentChecks::MinSize::Type::VALUE: {
593+
MathLib::bigint myMinsize = minsize.value;
594+
unsigned int baseSize = tokenizer->sizeOfType(minsize.baseType);
595+
if (baseSize != 0)
596+
myMinsize *= baseSize;
597+
return myMinsize <= bufferSize;
598+
}
594599
case Library::ArgumentChecks::MinSize::Type::NONE:
595600
break;
596601
}
@@ -644,7 +649,7 @@ void CheckBufferOverrun::bufferOverflow()
644649
}
645650
}
646651
const bool error = std::none_of(minsizes->begin(), minsizes->end(), [=](const Library::ArgumentChecks::MinSize &minsize) {
647-
return checkBufferSize(tok, minsize, args, bufferSize.intvalue, mSettings);
652+
return checkBufferSize(tok, minsize, args, bufferSize.intvalue, mSettings, mTokenizer);
648653
});
649654
if (error)
650655
bufferOverflowError(args[argnr], &bufferSize, (bufferSize.intvalue == 1) ? Certainty::inconclusive : Certainty::normal);

lib/checkother.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -384,47 +384,6 @@ void CheckOther::invalidPointerCastError(const Token* tok, const std::string& fr
384384
reportError(tok, Severity::portability, "invalidPointerCast", "Casting between " + from + " and " + to + " which have an incompatible binary data representation.", CWE704, Certainty::normal);
385385
}
386386

387-
//---------------------------------------------------------------------------
388-
// This check detects errors on POSIX systems, when a pipe command called
389-
// with a wrong dimensioned file descriptor array. The pipe command requires
390-
// exactly an integer array of dimension two as parameter.
391-
//
392-
// References:
393-
// - http://linux.die.net/man/2/pipe
394-
// - ticket #3521
395-
//---------------------------------------------------------------------------
396-
void CheckOther::checkPipeParameterSize()
397-
{
398-
if (!mSettings->posix())
399-
return;
400-
401-
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
402-
for (const Scope * scope : symbolDatabase->functionScopes) {
403-
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
404-
if (Token::Match(tok, "pipe ( %var% )") ||
405-
Token::Match(tok, "pipe2 ( %var% ,")) {
406-
const Token * const varTok = tok->tokAt(2);
407-
408-
const Variable *var = varTok->variable();
409-
MathLib::bigint dim;
410-
if (var && var->isArray() && !var->isArgument() && ((dim=var->dimension(0U)) < 2)) {
411-
const std::string strDim = MathLib::toString(dim);
412-
checkPipeParameterSizeError(varTok,varTok->str(), strDim);
413-
}
414-
}
415-
}
416-
}
417-
}
418-
419-
void CheckOther::checkPipeParameterSizeError(const Token *tok, const std::string &strVarName, const std::string &strDim)
420-
{
421-
reportError(tok, Severity::error,
422-
"wrongPipeParameterSize",
423-
"$symbol:" + strVarName + "\n"
424-
"Buffer '$symbol' must have size of 2 integers if used as parameter of pipe().\n"
425-
"The pipe()/pipe2() system command takes an argument, which is an array of exactly two integers.\n"
426-
"The variable '$symbol' is an array of size " + strDim + ", which does not match.", CWE686, Certainty::safe);
427-
}
428387

429388
//---------------------------------------------------------------------------
430389
// Detect redundant assignments: x = 0; x = 4;

lib/checkother.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ class CPPCHECKLIB CheckOther : public Check {
8787
checkOther.checkKnownArgument();
8888
checkOther.checkComparePointers();
8989
checkOther.checkIncompleteStatement();
90-
checkOther.checkPipeParameterSize();
9190
checkOther.checkRedundantCopy();
9291
checkOther.clarifyCalculation();
9392
checkOther.checkPassByReference();
@@ -190,9 +189,6 @@ class CPPCHECKLIB CheckOther : public Check {
190189
/** @brief %Check that variadic function calls don't use NULL. If NULL is \#defined as 0 and the function expects a pointer, the behaviour is undefined. */
191190
void checkVarFuncNullUB();
192191

193-
/** @brief %Check that calling the POSIX pipe() system call is called with an integer array of size two. */
194-
void checkPipeParameterSize();
195-
196192
/** @brief %Check to avoid casting a return value to unsigned char and then back to integer type. */
197193
void checkCastIntToCharAndBack();
198194

@@ -234,7 +230,6 @@ class CPPCHECKLIB CheckOther : public Check {
234230
// Error messages..
235231
void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result);
236232
void checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName);
237-
void checkPipeParameterSizeError(const Token *tok, const std::string &strVarName, const std::string &strDim);
238233
void clarifyCalculationError(const Token *tok, const std::string &op);
239234
void clarifyStatementError(const Token* tok);
240235
void cstyleCastError(const Token *tok);
@@ -299,7 +294,6 @@ class CPPCHECKLIB CheckOther : public Check {
299294
c.invalidPointerCastError(nullptr, "float *", "double *", false, false);
300295
c.negativeBitwiseShiftError(nullptr, 1);
301296
c.negativeBitwiseShiftError(nullptr, 2);
302-
c.checkPipeParameterSizeError(nullptr, "varname", "dimension");
303297
c.raceAfterInterlockedDecrementError(nullptr);
304298
c.invalidFreeError(nullptr, "malloc", false);
305299
c.overlappingWriteUnion(nullptr);
@@ -378,7 +372,6 @@ class CPPCHECKLIB CheckOther : public Check {
378372
"- assignment in an assert statement\n"
379373
"- free() or delete of an invalid memory location\n"
380374
"- bitwise operation with negative right operand\n"
381-
"- provide wrong dimensioned array to pipe() system command (--std=posix)\n"
382375
"- cast the return values of getc(),fgetc() and getchar() to character and compare it to EOF\n"
383376
"- race condition with non-interlocked access after InterlockedDecrement() call\n"
384377
"- expression 'x = x++;' depends on order of evaluation of side effects\n"

lib/library.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,9 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
782782
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, valueattr);
783783
ac.minsizes.emplace_back(type, 0);
784784
ac.minsizes.back().value = minsizevalue;
785+
const char* baseTypeAttr = argnode->Attribute("baseType");
786+
if (baseTypeAttr)
787+
ac.minsizes.back().baseType = baseTypeAttr;
785788
} else {
786789
const char *argattr = argnode->Attribute("arg");
787790
if (!argattr)

lib/library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ class CPPCHECKLIB Library {
327327
int arg;
328328
int arg2;
329329
long long value;
330+
std::string baseType;
330331
};
331332
std::vector<MinSize> minsizes;
332333

lib/tokenize.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,19 @@ Tokenizer::~Tokenizer()
203203
// SizeOfType - gives the size of a type
204204
//---------------------------------------------------------------------------
205205

206+
nonneg int Tokenizer::sizeOfType(const std::string& type) const
207+
{
208+
const std::map<std::string, int>::const_iterator it = mTypeSize.find(type);
209+
if (it == mTypeSize.end()) {
210+
const Library::PodType* podtype = mSettings->library.podtype(type);
211+
if (!podtype)
212+
return 0;
213+
214+
return podtype->size;
215+
}
216+
return it->second;
217+
}
218+
206219
nonneg int Tokenizer::sizeOfType(const Token *type) const
207220
{
208221
if (!type || type->str().empty())

lib/tokenize.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ class CPPCHECKLIB Tokenizer {
181181
* @param type Token which will contain e.g. "int", "*", or string.
182182
* @return sizeof for given type, or 0 if it can't be calculated.
183183
*/
184-
nonneg int sizeOfType(const Token *type) const;
184+
nonneg int sizeOfType(const Token* type) const;
185+
nonneg int sizeOfType(const std::string& type) const;
185186

186187
void simplifyDebug();
187188
/**

0 commit comments

Comments
 (0)