Moved checks related to sizeof usage from checkother into new file
This commit is contained in:
parent
42fcb04d0c
commit
994c429b7d
|
@ -499,35 +499,6 @@ void CheckOther::invalidPointerCastError(const Token* tok, const std::string& fr
|
||||||
reportError(tok, Severity::warning, "invalidPointerCast", "Casting between " + from + "* and " + to + "* which have an incompatible binary data representation.");
|
reportError(tok, Severity::warning, "invalidPointerCast", "Casting between " + from + "* and " + to + "* which have an incompatible binary data representation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void CheckOther::checkSizeofForNumericParameter()
|
|
||||||
{
|
|
||||||
if (!_settings->isEnabled("warning"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
|
||||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
|
||||||
if (Token::Match(tok, "sizeof ( %num% )") ||
|
|
||||||
Token::Match(tok, "sizeof %num%")) {
|
|
||||||
sizeofForNumericParameterError(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::sizeofForNumericParameterError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"sizeofwithnumericparameter", "Suspicious usage of 'sizeof' with a numeric constant as parameter.\n"
|
|
||||||
"It is unusual to use a constant value with sizeof. For example, 'sizeof(10)'"
|
|
||||||
" returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 10. 'sizeof('A')'"
|
|
||||||
" and 'sizeof(char)' can return different results.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// This check detects errors on POSIX systems, when a pipe command called
|
// This check detects errors on POSIX systems, when a pipe command called
|
||||||
// with a wrong dimensioned file descriptor array. The pipe command requires
|
// with a wrong dimensioned file descriptor array. The pipe command requires
|
||||||
|
@ -604,140 +575,6 @@ void CheckOther::checkSleepTimeError(const Token *tok, const std::string &strDim
|
||||||
"The argument of usleep must be less than 1000000, but " + strDim + " is provided.");
|
"The argument of usleep must be less than 1000000, but " + strDim + " is provided.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void CheckOther::checkSizeofForArrayParameter()
|
|
||||||
{
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
|
||||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
|
||||||
if (Token::Match(tok, "sizeof ( %var% )") ||
|
|
||||||
Token::Match(tok, "sizeof %var% !![")) {
|
|
||||||
const Token* varTok = tok->next();
|
|
||||||
if (varTok->str() == "(") {
|
|
||||||
varTok = varTok->next();
|
|
||||||
}
|
|
||||||
if (varTok->varId() > 0) {
|
|
||||||
const Variable *var = varTok->variable();
|
|
||||||
if (var && var->isArray() && var->isArgument()) {
|
|
||||||
sizeofForArrayParameterError(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::sizeofForArrayParameterError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::error,
|
|
||||||
"sizeofwithsilentarraypointer", "Using 'sizeof' on array given as function argument "
|
|
||||||
"returns size of a pointer.\n"
|
|
||||||
"Using 'sizeof' for array given as function argument returns the size of a pointer. "
|
|
||||||
"It does not return the size of the whole array in bytes as might be "
|
|
||||||
"expected. For example, this code:\n"
|
|
||||||
" int f(char a[100]) {\n"
|
|
||||||
" return sizeof(a);\n"
|
|
||||||
" }\n"
|
|
||||||
"returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the "
|
|
||||||
"size of the array in bytes)."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::checkSizeofForPointerSize()
|
|
||||||
{
|
|
||||||
if (!_settings->isEnabled("warning"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
|
||||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
|
||||||
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
|
||||||
const Token *tokVar;
|
|
||||||
const Token *variable;
|
|
||||||
const Token *variable2 = 0;
|
|
||||||
|
|
||||||
// Find any function that may use sizeof on a pointer
|
|
||||||
// Once leaving those tests, it is mandatory to have:
|
|
||||||
// - variable matching the used pointer
|
|
||||||
// - tokVar pointing on the argument where sizeof may be used
|
|
||||||
if (Token::Match(tok, "[*;{}] %var% = malloc|alloca (")) {
|
|
||||||
variable = tok->next();
|
|
||||||
tokVar = tok->tokAt(5);
|
|
||||||
|
|
||||||
} else if (Token::Match(tok, "[*;{}] %var% = calloc (")) {
|
|
||||||
variable = tok->next();
|
|
||||||
tokVar = tok->tokAt(5)->nextArgument();
|
|
||||||
|
|
||||||
} else if (Token::simpleMatch(tok, "memset (")) {
|
|
||||||
variable = tok->tokAt(2);
|
|
||||||
tokVar = variable->tokAt(2)->nextArgument();
|
|
||||||
|
|
||||||
// The following tests can be inconclusive in case the variable in sizeof
|
|
||||||
// is constant string by intention
|
|
||||||
} else if (!_settings->inconclusive) {
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else if (Token::Match(tok, "memcpy|memcmp|memmove|strncpy|strncmp|strncat (")) {
|
|
||||||
variable = tok->tokAt(2);
|
|
||||||
variable2 = variable->nextArgument();
|
|
||||||
tokVar = variable2->nextArgument();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the variables are in the symbol database
|
|
||||||
// Also ensure the variables are pointers
|
|
||||||
// Only keep variables which are pointers
|
|
||||||
const Variable *var = variable->variable();
|
|
||||||
if (!var || !var->isPointer() || var->isArray()) {
|
|
||||||
variable = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variable2) {
|
|
||||||
var = variable2->variable();
|
|
||||||
if (!var || !var->isPointer() || var->isArray()) {
|
|
||||||
variable2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no pointer variable at this point, there is
|
|
||||||
// no need to continue
|
|
||||||
if (variable == 0 && variable2 == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump to the next sizeof token in the function and in the parameter
|
|
||||||
// This is to allow generic operations with sizeof
|
|
||||||
for (; tokVar && tokVar->str() != ")" && tokVar->str() != "," && tokVar->str() != "sizeof"; tokVar = tokVar->next()) {}
|
|
||||||
|
|
||||||
// Now check for the sizeof usage. Once here, everything using sizeof(varid) or sizeof(&varid)
|
|
||||||
// looks suspicious
|
|
||||||
// Do it for first variable
|
|
||||||
if (variable && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable->varId()) ||
|
|
||||||
Token::Match(tokVar, "sizeof &| %varid%", variable->varId()))) {
|
|
||||||
sizeofForPointerError(variable, variable->str());
|
|
||||||
} else if (variable2 && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable2->varId()) ||
|
|
||||||
Token::Match(tokVar, "sizeof &| %varid%", variable2->varId()))) {
|
|
||||||
sizeofForPointerError(variable2, variable2->str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::sizeofForPointerError(const Token *tok, const std::string &varname)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning, "pointerSize",
|
|
||||||
"Size of pointer '" + varname + "' used instead of size of its data.\n"
|
|
||||||
"Size of pointer '" + varname + "' used instead of size of its data. "
|
|
||||||
"This is likely to lead to a buffer overflow. You probably intend to "
|
|
||||||
"write 'sizeof(*" + varname + ")'.", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Detect redundant assignments: x = 0; x = 4;
|
// Detect redundant assignments: x = 0; x = 4;
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -3265,59 +3102,6 @@ void CheckOther::moduloAlwaysTrueFalseError(const Token* tok, const std::string&
|
||||||
"Comparison of modulo result is predetermined, because it is always less than " + maxVal + ".");
|
"Comparison of modulo result is predetermined, because it is always less than " + maxVal + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CheckOther::sizeofsizeof()
|
|
||||||
{
|
|
||||||
if (!_settings->isEnabled("warning"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
if (Token::Match(tok, "sizeof (| sizeof")) {
|
|
||||||
sizeofsizeofError(tok);
|
|
||||||
tok = tok->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::sizeofsizeofError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"sizeofsizeof", "Calling 'sizeof' on 'sizeof'.\n"
|
|
||||||
"Calling sizeof for 'sizeof looks like a suspicious code and "
|
|
||||||
"most likely there should be just one 'sizeof'. The current "
|
|
||||||
"code is equivalent to 'sizeof(size_t)'");
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CheckOther::sizeofCalculation()
|
|
||||||
{
|
|
||||||
if (!_settings->isEnabled("warning"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
|
||||||
const Token* const end = tok->linkAt(1);
|
|
||||||
for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) {
|
|
||||||
if (tok2->isConstOp() && (!tok2->isExpandedMacro() || _settings->inconclusive) && !Token::Match(tok2, ">|<|&") && (Token::Match(tok2->previous(), "%var%") || tok2->str() != "*")) {
|
|
||||||
if (!(Token::Match(tok2->previous(), "%type%") || Token::Match(tok2->next(), "%type%"))) {
|
|
||||||
sizeofCalculationError(tok2, tok2->isExpandedMacro());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (tok2->type() == Token::eIncDecOp)
|
|
||||||
sizeofCalculationError(tok2, tok2->isExpandedMacro());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::sizeofCalculationError(const Token *tok, bool inconclusive)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"sizeofCalculation", "Found calculation inside sizeof().", inconclusive);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Check for code like:
|
// Check for code like:
|
||||||
// seteuid(geteuid()) or setuid(getuid()), which first gets and then sets the
|
// seteuid(geteuid()) or setuid(getuid()), which first gets and then sets the
|
||||||
|
@ -3347,42 +3131,6 @@ void CheckOther::redundantGetAndSetUserIdError(const Token *tok)
|
||||||
"by get(e)uid() and then set with set(e)uid().", false);
|
"by get(e)uid() and then set with set(e)uid().", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Check for code like sizeof()*sizeof() or sizeof(ptr)/value
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void CheckOther::suspiciousSizeofCalculation()
|
|
||||||
{
|
|
||||||
if (!_settings->isEnabled("warning") || !_settings->inconclusive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
|
||||||
const Token* const end = tok->linkAt(1);
|
|
||||||
const Variable* var = end->previous()->variable();
|
|
||||||
if (end->strAt(-1) == "*" || (var && var->isPointer() && !var->isArray())) {
|
|
||||||
if (end->strAt(1) == "/")
|
|
||||||
divideSizeofError(tok);
|
|
||||||
} else if (Token::simpleMatch(end, ") * sizeof"))
|
|
||||||
multiplySizeofError(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::multiplySizeofError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::divideSizeofError(const Token *tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"divideSizeof", "Division of result of sizeof() on pointer type.\n"
|
|
||||||
"Division of result of sizeof() on pointer type. sizeof() returns the size of the pointer, "
|
|
||||||
"not the size of the memory area it points to.", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Check testing sign of unsigned variables and pointers.
|
// Check testing sign of unsigned variables and pointers.
|
||||||
|
|
|
@ -57,16 +57,10 @@ public:
|
||||||
checkOther.checkUnsignedDivision();
|
checkOther.checkUnsignedDivision();
|
||||||
checkOther.checkCharVariable();
|
checkOther.checkCharVariable();
|
||||||
checkOther.strPlusChar();
|
checkOther.strPlusChar();
|
||||||
checkOther.sizeofsizeof();
|
|
||||||
checkOther.sizeofCalculation();
|
|
||||||
checkOther.suspiciousSizeofCalculation();
|
|
||||||
checkOther.checkRedundantAssignment();
|
checkOther.checkRedundantAssignment();
|
||||||
checkOther.checkRedundantAssignmentInSwitch();
|
checkOther.checkRedundantAssignmentInSwitch();
|
||||||
checkOther.checkSuspiciousCaseInSwitch();
|
checkOther.checkSuspiciousCaseInSwitch();
|
||||||
checkOther.checkAssignmentInAssert();
|
checkOther.checkAssignmentInAssert();
|
||||||
checkOther.checkSizeofForArrayParameter();
|
|
||||||
checkOther.checkSizeofForPointerSize();
|
|
||||||
checkOther.checkSizeofForNumericParameter();
|
|
||||||
checkOther.checkSelfAssignment();
|
checkOther.checkSelfAssignment();
|
||||||
checkOther.checkDuplicateIf();
|
checkOther.checkDuplicateIf();
|
||||||
checkOther.checkDuplicateBranch();
|
checkOther.checkDuplicateBranch();
|
||||||
|
@ -171,18 +165,9 @@ public:
|
||||||
/** @brief %Check for parameters given to cctype function that do make error*/
|
/** @brief %Check for parameters given to cctype function that do make error*/
|
||||||
void checkCCTypeFunctions();
|
void checkCCTypeFunctions();
|
||||||
|
|
||||||
/** @brief %Check for 'sizeof sizeof ..' */
|
|
||||||
void sizeofsizeof();
|
|
||||||
|
|
||||||
/** @brief %Check for calculations inside sizeof */
|
|
||||||
void sizeofCalculation();
|
|
||||||
|
|
||||||
/** @brief % Check for seteuid(geteuid()) or setuid(getuid())*/
|
/** @brief % Check for seteuid(geteuid()) or setuid(getuid())*/
|
||||||
void redundantGetAndSetUserId();
|
void redundantGetAndSetUserId();
|
||||||
|
|
||||||
/** @brief %Check for suspicious calculations with sizeof results */
|
|
||||||
void suspiciousSizeofCalculation();
|
|
||||||
|
|
||||||
/** @brief copying to memory or assigning to a variable twice */
|
/** @brief copying to memory or assigning to a variable twice */
|
||||||
void checkRedundantAssignment();
|
void checkRedundantAssignment();
|
||||||
|
|
||||||
|
@ -213,15 +198,6 @@ public:
|
||||||
/** @brief %Check for filling zero bytes with memset() */
|
/** @brief %Check for filling zero bytes with memset() */
|
||||||
void checkMemsetZeroBytes();
|
void checkMemsetZeroBytes();
|
||||||
|
|
||||||
/** @brief %Check for using sizeof with array given as function argument */
|
|
||||||
void checkSizeofForArrayParameter();
|
|
||||||
|
|
||||||
/** @brief %Check for using sizeof of a variable when allocating it */
|
|
||||||
void checkSizeofForPointerSize();
|
|
||||||
|
|
||||||
/** @brief %Check for using sizeof with numeric given as function argument */
|
|
||||||
void checkSizeofForNumericParameter();
|
|
||||||
|
|
||||||
/** @brief %Check for using bad usage of strncmp and substr */
|
/** @brief %Check for using bad usage of strncmp and substr */
|
||||||
void checkIncorrectStringCompare();
|
void checkIncorrectStringCompare();
|
||||||
|
|
||||||
|
@ -293,11 +269,7 @@ private:
|
||||||
void clarifyCalculationError(const Token *tok, const std::string &op);
|
void clarifyCalculationError(const Token *tok, const std::string &op);
|
||||||
void clarifyConditionError(const Token *tok, bool assign, bool boolop);
|
void clarifyConditionError(const Token *tok, bool assign, bool boolop);
|
||||||
void clarifyStatementError(const Token* tok);
|
void clarifyStatementError(const Token* tok);
|
||||||
void sizeofsizeofError(const Token *tok);
|
|
||||||
void sizeofCalculationError(const Token *tok, bool inconclusive);
|
|
||||||
void redundantGetAndSetUserIdError(const Token *tok);
|
void redundantGetAndSetUserIdError(const Token *tok);
|
||||||
void multiplySizeofError(const Token *tok);
|
|
||||||
void divideSizeofError(const Token *tok);
|
|
||||||
void cstyleCastError(const Token *tok);
|
void cstyleCastError(const Token *tok);
|
||||||
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive);
|
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive);
|
||||||
void dangerousUsageStrtolError(const Token *tok, const std::string& funcname);
|
void dangerousUsageStrtolError(const Token *tok, const std::string& funcname);
|
||||||
|
@ -326,9 +298,6 @@ private:
|
||||||
void redundantConditionError(const Token *tok, const std::string &text);
|
void redundantConditionError(const Token *tok, const std::string &text);
|
||||||
void misusedScopeObjectError(const Token *tok, const std::string &varname);
|
void misusedScopeObjectError(const Token *tok, const std::string &varname);
|
||||||
void memsetZeroBytesError(const Token *tok, const std::string &varname);
|
void memsetZeroBytesError(const Token *tok, const std::string &varname);
|
||||||
void sizeofForArrayParameterError(const Token *tok);
|
|
||||||
void sizeofForPointerError(const Token *tok, const std::string &varname);
|
|
||||||
void sizeofForNumericParameterError(const Token *tok);
|
|
||||||
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
||||||
void incorrectStringBooleanError(const Token *tok, const std::string& string);
|
void incorrectStringBooleanError(const Token *tok, const std::string& string);
|
||||||
void duplicateIfError(const Token *tok1, const Token *tok2);
|
void duplicateIfError(const Token *tok1, const Token *tok2);
|
||||||
|
@ -360,9 +329,6 @@ private:
|
||||||
c.zerodivError(0);
|
c.zerodivError(0);
|
||||||
c.mathfunctionCallError(0);
|
c.mathfunctionCallError(0);
|
||||||
c.misusedScopeObjectError(NULL, "varname");
|
c.misusedScopeObjectError(NULL, "varname");
|
||||||
c.sizeofForArrayParameterError(0);
|
|
||||||
c.sizeofForPointerError(0, "varname");
|
|
||||||
c.sizeofForNumericParameterError(0);
|
|
||||||
c.doubleFreeError(0, "varname");
|
c.doubleFreeError(0, "varname");
|
||||||
c.invalidPointerCastError(0, "float", "double", false);
|
c.invalidPointerCastError(0, "float", "double", false);
|
||||||
c.negativeBitwiseShiftError(0);
|
c.negativeBitwiseShiftError(0);
|
||||||
|
@ -385,10 +351,6 @@ private:
|
||||||
c.charBitOpError(0);
|
c.charBitOpError(0);
|
||||||
c.variableScopeError(0, "varname");
|
c.variableScopeError(0, "varname");
|
||||||
c.strPlusCharError(0);
|
c.strPlusCharError(0);
|
||||||
c.sizeofsizeofError(0);
|
|
||||||
c.sizeofCalculationError(0, false);
|
|
||||||
c.multiplySizeofError(0);
|
|
||||||
c.divideSizeofError(0);
|
|
||||||
c.redundantAssignmentInSwitchError(0, 0, "var");
|
c.redundantAssignmentInSwitchError(0, 0, "var");
|
||||||
c.redundantCopyInSwitchError(0, 0, "var");
|
c.redundantCopyInSwitchError(0, 0, "var");
|
||||||
c.switchCaseFallThrough(0);
|
c.switchCaseFallThrough(0);
|
||||||
|
@ -435,9 +397,6 @@ private:
|
||||||
"* division with zero\n"
|
"* division with zero\n"
|
||||||
"* scoped object destroyed immediately after construction\n"
|
"* scoped object destroyed immediately after construction\n"
|
||||||
"* assignment in an assert statement\n"
|
"* assignment in an assert statement\n"
|
||||||
"* sizeof for array given as function argument\n"
|
|
||||||
"* sizeof for numeric given as function argument\n"
|
|
||||||
"* using sizeof(pointer) instead of the size of pointed data\n"
|
|
||||||
"* incorrect length arguments for 'substr' and 'strncmp'\n"
|
"* incorrect length arguments for 'substr' and 'strncmp'\n"
|
||||||
"* free() or delete of an invalid memory location\n"
|
"* free() or delete of an invalid memory location\n"
|
||||||
"* double free() or double closedir()\n"
|
"* double free() or double closedir()\n"
|
||||||
|
@ -467,9 +426,6 @@ private:
|
||||||
"* redundant pre/post operation in a switch statement\n"
|
"* redundant pre/post operation in a switch statement\n"
|
||||||
"* redundant bitwise operation in a switch statement\n"
|
"* redundant bitwise operation in a switch statement\n"
|
||||||
"* redundant strcpy in a switch statement\n"
|
"* redundant strcpy in a switch statement\n"
|
||||||
"* look for 'sizeof sizeof ..'\n"
|
|
||||||
"* look for calculations inside sizeof()\n"
|
|
||||||
"* look for suspicious calculations with sizeof()\n"
|
|
||||||
"* assignment of a variable to itself\n"
|
"* assignment of a variable to itself\n"
|
||||||
"* Suspicious case labels in switch()\n"
|
"* Suspicious case labels in switch()\n"
|
||||||
"* Suspicious equality comparisons\n"
|
"* Suspicious equality comparisons\n"
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
|
* Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#include "checksizeof.h"
|
||||||
|
#include "symboldatabase.h"
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Register this check class (by creating a static instance of it)
|
||||||
|
namespace {
|
||||||
|
CheckSizeof instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void CheckSizeof::checkSizeofForNumericParameter()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("warning"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "sizeof ( %num% )") ||
|
||||||
|
Token::Match(tok, "sizeof %num%")) {
|
||||||
|
sizeofForNumericParameterError(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::sizeofForNumericParameterError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning,
|
||||||
|
"sizeofwithnumericparameter", "Suspicious usage of 'sizeof' with a numeric constant as parameter.\n"
|
||||||
|
"It is unusual to use a constant value with sizeof. For example, 'sizeof(10)'"
|
||||||
|
" returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 10. 'sizeof('A')'"
|
||||||
|
" and 'sizeof(char)' can return different results.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void CheckSizeof::checkSizeofForArrayParameter()
|
||||||
|
{
|
||||||
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "sizeof ( %var% )") ||
|
||||||
|
Token::Match(tok, "sizeof %var% !![")) {
|
||||||
|
const Token* varTok = tok->next();
|
||||||
|
if (varTok->str() == "(") {
|
||||||
|
varTok = varTok->next();
|
||||||
|
}
|
||||||
|
if (varTok->varId() > 0) {
|
||||||
|
const Variable *var = varTok->variable();
|
||||||
|
if (var && var->isArray() && var->isArgument()) {
|
||||||
|
sizeofForArrayParameterError(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::sizeofForArrayParameterError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::error,
|
||||||
|
"sizeofwithsilentarraypointer", "Using 'sizeof' on array given as function argument "
|
||||||
|
"returns size of a pointer.\n"
|
||||||
|
"Using 'sizeof' for array given as function argument returns the size of a pointer. "
|
||||||
|
"It does not return the size of the whole array in bytes as might be "
|
||||||
|
"expected. For example, this code:\n"
|
||||||
|
" int f(char a[100]) {\n"
|
||||||
|
" return sizeof(a);\n"
|
||||||
|
" }\n"
|
||||||
|
"returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the "
|
||||||
|
"size of the array in bytes)."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::checkSizeofForPointerSize()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("warning"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
const Token *tokVar;
|
||||||
|
const Token *variable;
|
||||||
|
const Token *variable2 = 0;
|
||||||
|
|
||||||
|
// Find any function that may use sizeof on a pointer
|
||||||
|
// Once leaving those tests, it is mandatory to have:
|
||||||
|
// - variable matching the used pointer
|
||||||
|
// - tokVar pointing on the argument where sizeof may be used
|
||||||
|
if (Token::Match(tok, "[*;{}] %var% = malloc|alloca (")) {
|
||||||
|
variable = tok->next();
|
||||||
|
tokVar = tok->tokAt(5);
|
||||||
|
|
||||||
|
} else if (Token::Match(tok, "[*;{}] %var% = calloc (")) {
|
||||||
|
variable = tok->next();
|
||||||
|
tokVar = tok->tokAt(5)->nextArgument();
|
||||||
|
|
||||||
|
} else if (Token::simpleMatch(tok, "memset (")) {
|
||||||
|
variable = tok->tokAt(2);
|
||||||
|
tokVar = variable->tokAt(2)->nextArgument();
|
||||||
|
|
||||||
|
// The following tests can be inconclusive in case the variable in sizeof
|
||||||
|
// is constant string by intention
|
||||||
|
} else if (!_settings->inconclusive) {
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (Token::Match(tok, "memcpy|memcmp|memmove|strncpy|strncmp|strncat (")) {
|
||||||
|
variable = tok->tokAt(2);
|
||||||
|
variable2 = variable->nextArgument();
|
||||||
|
tokVar = variable2->nextArgument();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the variables are in the symbol database
|
||||||
|
// Also ensure the variables are pointers
|
||||||
|
// Only keep variables which are pointers
|
||||||
|
const Variable *var = variable->variable();
|
||||||
|
if (!var || !var->isPointer() || var->isArray()) {
|
||||||
|
variable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variable2) {
|
||||||
|
var = variable2->variable();
|
||||||
|
if (!var || !var->isPointer() || var->isArray()) {
|
||||||
|
variable2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no pointer variable at this point, there is
|
||||||
|
// no need to continue
|
||||||
|
if (variable == 0 && variable2 == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump to the next sizeof token in the function and in the parameter
|
||||||
|
// This is to allow generic operations with sizeof
|
||||||
|
for (; tokVar && tokVar->str() != ")" && tokVar->str() != "," && tokVar->str() != "sizeof"; tokVar = tokVar->next()) {}
|
||||||
|
|
||||||
|
// Now check for the sizeof usage. Once here, everything using sizeof(varid) or sizeof(&varid)
|
||||||
|
// looks suspicious
|
||||||
|
// Do it for first variable
|
||||||
|
if (variable && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable->varId()) ||
|
||||||
|
Token::Match(tokVar, "sizeof &| %varid%", variable->varId()))) {
|
||||||
|
sizeofForPointerError(variable, variable->str());
|
||||||
|
} else if (variable2 && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable2->varId()) ||
|
||||||
|
Token::Match(tokVar, "sizeof &| %varid%", variable2->varId()))) {
|
||||||
|
sizeofForPointerError(variable2, variable2->str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::sizeofForPointerError(const Token *tok, const std::string &varname)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning, "pointerSize",
|
||||||
|
"Size of pointer '" + varname + "' used instead of size of its data.\n"
|
||||||
|
"Size of pointer '" + varname + "' used instead of size of its data. "
|
||||||
|
"This is likely to lead to a buffer overflow. You probably intend to "
|
||||||
|
"write 'sizeof(*" + varname + ")'.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CheckSizeof::sizeofsizeof()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("warning"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "sizeof (| sizeof")) {
|
||||||
|
sizeofsizeofError(tok);
|
||||||
|
tok = tok->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::sizeofsizeofError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning,
|
||||||
|
"sizeofsizeof", "Calling 'sizeof' on 'sizeof'.\n"
|
||||||
|
"Calling sizeof for 'sizeof looks like a suspicious code and "
|
||||||
|
"most likely there should be just one 'sizeof'. The current "
|
||||||
|
"code is equivalent to 'sizeof(size_t)'");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CheckSizeof::sizeofCalculation()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("warning"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
|
const Token* const end = tok->linkAt(1);
|
||||||
|
for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) {
|
||||||
|
if (tok2->isConstOp() && (!tok2->isExpandedMacro() || _settings->inconclusive) && !Token::Match(tok2, ">|<|&") && (Token::Match(tok2->previous(), "%var%") || tok2->str() != "*")) {
|
||||||
|
if (!(Token::Match(tok2->previous(), "%type%") || Token::Match(tok2->next(), "%type%"))) {
|
||||||
|
sizeofCalculationError(tok2, tok2->isExpandedMacro());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (tok2->type() == Token::eIncDecOp)
|
||||||
|
sizeofCalculationError(tok2, tok2->isExpandedMacro());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::sizeofCalculationError(const Token *tok, bool inconclusive)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning,
|
||||||
|
"sizeofCalculation", "Found calculation inside sizeof().", inconclusive);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Check for code like sizeof()*sizeof() or sizeof(ptr)/value
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CheckSizeof::suspiciousSizeofCalculation()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("warning") || !_settings->inconclusive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
|
const Token* const end = tok->linkAt(1);
|
||||||
|
const Variable* var = end->previous()->variable();
|
||||||
|
if (end->strAt(-1) == "*" || (var && var->isPointer() && !var->isArray())) {
|
||||||
|
if (end->strAt(1) == "/")
|
||||||
|
divideSizeofError(tok);
|
||||||
|
} else if (Token::simpleMatch(end, ") * sizeof"))
|
||||||
|
multiplySizeofError(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::multiplySizeofError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning,
|
||||||
|
"multiplySizeof", "Multiplying sizeof() with sizeof() indicates a logic error.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckSizeof::divideSizeofError(const Token *tok)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::warning,
|
||||||
|
"divideSizeof", "Division of result of sizeof() on pointer type.\n"
|
||||||
|
"Division of result of sizeof() on pointer type. sizeof() returns the size of the pointer, "
|
||||||
|
"not the size of the memory area it points to.", true);
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
|
* Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#ifndef CheckSizeofH
|
||||||
|
#define CheckSizeofH
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "check.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
class Token;
|
||||||
|
class Function;
|
||||||
|
class Variable;
|
||||||
|
|
||||||
|
/// @addtogroup Checks
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief checks on usage of sizeof() operator */
|
||||||
|
|
||||||
|
class CPPCHECKLIB CheckSizeof : public Check {
|
||||||
|
public:
|
||||||
|
/** @brief This constructor is used when registering the CheckClass */
|
||||||
|
CheckSizeof() : Check(myName())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/** @brief This constructor is used when running checks. */
|
||||||
|
CheckSizeof(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger)
|
||||||
|
: Check(myName(), tokenizer, settings, errorLogger)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/** @brief Run checks against the normal token list */
|
||||||
|
void runChecks(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) {
|
||||||
|
CheckSizeof checkSizeof(tokenizer, settings, errorLogger);
|
||||||
|
|
||||||
|
// Checks
|
||||||
|
checkSizeof.sizeofsizeof();
|
||||||
|
checkSizeof.sizeofCalculation();
|
||||||
|
checkSizeof.suspiciousSizeofCalculation();
|
||||||
|
checkSizeof.checkSizeofForArrayParameter();
|
||||||
|
checkSizeof.checkSizeofForPointerSize();
|
||||||
|
checkSizeof.checkSizeofForNumericParameter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Run checks against the simplified token list */
|
||||||
|
void runSimplifiedChecks(const Tokenizer*, const Settings*, ErrorLogger*) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief %Check for 'sizeof sizeof ..' */
|
||||||
|
void sizeofsizeof();
|
||||||
|
|
||||||
|
/** @brief %Check for calculations inside sizeof */
|
||||||
|
void sizeofCalculation();
|
||||||
|
|
||||||
|
/** @brief %Check for suspicious calculations with sizeof results */
|
||||||
|
void suspiciousSizeofCalculation();
|
||||||
|
|
||||||
|
/** @brief %Check for using sizeof with array given as function argument */
|
||||||
|
void checkSizeofForArrayParameter();
|
||||||
|
|
||||||
|
/** @brief %Check for using sizeof of a variable when allocating it */
|
||||||
|
void checkSizeofForPointerSize();
|
||||||
|
|
||||||
|
/** @brief %Check for using sizeof with numeric given as function argument */
|
||||||
|
void checkSizeofForNumericParameter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Error messages..
|
||||||
|
void sizeofsizeofError(const Token* tok);
|
||||||
|
void sizeofCalculationError(const Token* tok, bool inconclusive);
|
||||||
|
void multiplySizeofError(const Token* tok);
|
||||||
|
void divideSizeofError(const Token* tok);
|
||||||
|
void sizeofForArrayParameterError(const Token* tok);
|
||||||
|
void sizeofForPointerError(const Token* tok, const std::string &varname);
|
||||||
|
void sizeofForNumericParameterError(const Token* tok);
|
||||||
|
|
||||||
|
void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const {
|
||||||
|
CheckSizeof c(0, settings, errorLogger);
|
||||||
|
|
||||||
|
c.sizeofForArrayParameterError(0);
|
||||||
|
c.sizeofForPointerError(0, "varname");
|
||||||
|
c.sizeofForNumericParameterError(0);
|
||||||
|
c.sizeofsizeofError(0);
|
||||||
|
c.sizeofCalculationError(0, false);
|
||||||
|
c.multiplySizeofError(0);
|
||||||
|
c.divideSizeofError(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string myName() {
|
||||||
|
return "Sizeof";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string classInfo() const {
|
||||||
|
return "sizeof() usage checks\n"
|
||||||
|
|
||||||
|
"* sizeof for array given as function argument\n"
|
||||||
|
"* sizeof for numeric given as function argument\n"
|
||||||
|
"* using sizeof(pointer) instead of the size of pointed data\n"
|
||||||
|
"* look for 'sizeof sizeof ..'\n"
|
||||||
|
"* look for calculations inside sizeof()\n"
|
||||||
|
"* look for suspicious calculations with sizeof()\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/// @}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#endif
|
|
@ -52,6 +52,7 @@
|
||||||
<ClCompile Include="checkobsoletefunctions.cpp" />
|
<ClCompile Include="checkobsoletefunctions.cpp" />
|
||||||
<ClCompile Include="checkother.cpp" />
|
<ClCompile Include="checkother.cpp" />
|
||||||
<ClCompile Include="checkpostfixoperator.cpp" />
|
<ClCompile Include="checkpostfixoperator.cpp" />
|
||||||
|
<ClCompile Include="checksizeof.cpp" />
|
||||||
<ClCompile Include="checkstl.cpp" />
|
<ClCompile Include="checkstl.cpp" />
|
||||||
<ClCompile Include="checkuninitvar.cpp" />
|
<ClCompile Include="checkuninitvar.cpp" />
|
||||||
<ClCompile Include="checkunusedfunctions.cpp" />
|
<ClCompile Include="checkunusedfunctions.cpp" />
|
||||||
|
@ -90,6 +91,7 @@
|
||||||
<ClInclude Include="checkobsoletefunctions.h" />
|
<ClInclude Include="checkobsoletefunctions.h" />
|
||||||
<ClInclude Include="checkother.h" />
|
<ClInclude Include="checkother.h" />
|
||||||
<ClInclude Include="checkpostfixoperator.h" />
|
<ClInclude Include="checkpostfixoperator.h" />
|
||||||
|
<ClInclude Include="checksizeof.h" />
|
||||||
<ClInclude Include="checkstl.h" />
|
<ClInclude Include="checkstl.h" />
|
||||||
<ClInclude Include="checkuninitvar.h" />
|
<ClInclude Include="checkuninitvar.h" />
|
||||||
<ClInclude Include="checkunusedfunctions.h" />
|
<ClInclude Include="checkunusedfunctions.h" />
|
||||||
|
|
|
@ -116,6 +116,9 @@
|
||||||
<ClCompile Include="checkbool.cpp">
|
<ClCompile Include="checkbool.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="checksizeof.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="checkbufferoverrun.h">
|
<ClInclude Include="checkbufferoverrun.h">
|
||||||
|
@ -232,6 +235,9 @@
|
||||||
<ClInclude Include="checkbool.h">
|
<ClInclude Include="checkbool.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="checksizeof.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<ResourceCompile Include="version.rc" />
|
||||||
|
|
|
@ -81,9 +81,6 @@ private:
|
||||||
TEST_CASE(mathfunctionCall1);
|
TEST_CASE(mathfunctionCall1);
|
||||||
TEST_CASE(cctypefunctionCall);
|
TEST_CASE(cctypefunctionCall);
|
||||||
|
|
||||||
TEST_CASE(sizeofsizeof);
|
|
||||||
TEST_CASE(sizeofCalculation);
|
|
||||||
|
|
||||||
TEST_CASE(switchRedundantAssignmentTest);
|
TEST_CASE(switchRedundantAssignmentTest);
|
||||||
TEST_CASE(switchRedundantOperationTest);
|
TEST_CASE(switchRedundantOperationTest);
|
||||||
TEST_CASE(switchRedundantBitwiseOperationTest);
|
TEST_CASE(switchRedundantBitwiseOperationTest);
|
||||||
|
@ -123,13 +120,8 @@ private:
|
||||||
|
|
||||||
TEST_CASE(memsetZeroBytes);
|
TEST_CASE(memsetZeroBytes);
|
||||||
|
|
||||||
TEST_CASE(sizeofForArrayParameter);
|
|
||||||
TEST_CASE(sizeofForNumericParameter);
|
|
||||||
|
|
||||||
TEST_CASE(redundantGetAndSetUserId);
|
TEST_CASE(redundantGetAndSetUserId);
|
||||||
|
|
||||||
TEST_CASE(suspiciousSizeofCalculation);
|
|
||||||
|
|
||||||
TEST_CASE(clarifyCalculation);
|
TEST_CASE(clarifyCalculation);
|
||||||
TEST_CASE(clarifyStatement);
|
TEST_CASE(clarifyStatement);
|
||||||
|
|
||||||
|
@ -156,7 +148,6 @@ private:
|
||||||
|
|
||||||
TEST_CASE(alwaysTrueFalseStringCompare);
|
TEST_CASE(alwaysTrueFalseStringCompare);
|
||||||
TEST_CASE(suspiciousStringCompare);
|
TEST_CASE(suspiciousStringCompare);
|
||||||
TEST_CASE(checkPointerSizeof);
|
|
||||||
TEST_CASE(checkSignOfUnsignedVariable);
|
TEST_CASE(checkSignOfUnsignedVariable);
|
||||||
TEST_CASE(checkSignOfPointer);
|
TEST_CASE(checkSignOfPointer);
|
||||||
|
|
||||||
|
@ -1533,49 +1524,6 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Passing value -10000 to isgraph() causes undefined behavior which may lead to a crash.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) Passing value -10000 to isgraph() causes undefined behavior which may lead to a crash.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sizeofsizeof() {
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" int i = sizeof sizeof char;\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
|
||||||
|
|
||||||
check("void foo()\n"
|
|
||||||
"{\n"
|
|
||||||
" int i = sizeof (sizeof long);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
|
||||||
|
|
||||||
check("void foo(long *p)\n"
|
|
||||||
"{\n"
|
|
||||||
" int i = sizeof (sizeof (p));\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void sizeofCalculation() {
|
|
||||||
check("int a, b; int a,sizeof(a+b)");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
|
||||||
|
|
||||||
check("int a, b; sizeof(a*b)");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
|
||||||
|
|
||||||
check("int a, b; sizeof(-a)");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
|
||||||
|
|
||||||
check("int a, b; sizeof(*a)");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("sizeof(void * const)");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("sizeof(foo++)");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
|
||||||
|
|
||||||
check("sizeof(--foo)");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void switchRedundantAssignmentTest() {
|
void switchRedundantAssignmentTest() {
|
||||||
|
|
||||||
check("void foo()\n"
|
check("void foo()\n"
|
||||||
|
@ -3891,168 +3839,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sizeofForArrayParameter() {
|
|
||||||
check("void f() {\n"
|
|
||||||
" int a[10];\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" unsigned int a = 2;\n"
|
|
||||||
" unsigned int b = 2;\n"
|
|
||||||
" int c[(a+b)];\n"
|
|
||||||
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" unsigned int a = { 2 };\n"
|
|
||||||
" unsigned int b[] = { 0 };\n"
|
|
||||||
" int c[a[b[0]]];\n"
|
|
||||||
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" unsigned int a[] = { 1 };\n"
|
|
||||||
" unsigned int b = 2;\n"
|
|
||||||
" int c[(a[0]+b)];\n"
|
|
||||||
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int a[] = { 1, 2, 3 };\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int a[3] = { 1, 2, 3 };\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f( int a[]) {\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
|
||||||
"function argument returns size of a pointer.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f( int a[]) {\n"
|
|
||||||
" std::cout << sizeof a / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
|
||||||
"function argument returns size of a pointer.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f( int a[3] ) {\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
|
||||||
"function argument returns size of a pointer.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f(int *p) {\n"
|
|
||||||
" p[0] = 0;\n"
|
|
||||||
" int unused = sizeof(p);\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" char p[] = \"test\";\n"
|
|
||||||
" int unused = sizeof(p);\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
// ticket #2495
|
|
||||||
check("void f() {\n"
|
|
||||||
" static float col[][3]={\n"
|
|
||||||
" {1,0,0},\n"
|
|
||||||
" {0,0,1},\n"
|
|
||||||
" {0,1,0},\n"
|
|
||||||
" {1,0,1},\n"
|
|
||||||
" {1,0,1},\n"
|
|
||||||
" {1,0,1},\n"
|
|
||||||
" };\n"
|
|
||||||
" const int COL_MAX=sizeof(col)/sizeof(col[0]);\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
// ticket #155
|
|
||||||
check("void f() {\n"
|
|
||||||
" char buff1[1024*64],buff2[sizeof(buff1)*2];\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
// ticket #2510
|
|
||||||
check("void f( int a[], int b) {\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
|
||||||
"function argument returns size of a pointer.\n", errout.str());
|
|
||||||
|
|
||||||
// ticket #2510
|
|
||||||
check("void f( int a[3] , int b[2] ) {\n"
|
|
||||||
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
|
||||||
"function argument returns size of a pointer.\n", errout.str());
|
|
||||||
|
|
||||||
// ticket #2510
|
|
||||||
check("void f() {\n"
|
|
||||||
" char buff1[1024*64],buff2[sizeof(buff1)*(2+1)];\n"
|
|
||||||
"}\n"
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void sizeofForNumericParameter() {
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::cout << sizeof(10) << std::endl;\n"
|
|
||||||
"}\n",
|
|
||||||
NULL, true
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::cout << sizeof(-10) << std::endl;\n"
|
|
||||||
"}\n",
|
|
||||||
NULL, true
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::cout << sizeof 10 << std::endl;\n"
|
|
||||||
"}\n",
|
|
||||||
NULL, true
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::cout << sizeof -10 << std::endl;\n"
|
|
||||||
"}\n",
|
|
||||||
NULL, true
|
|
||||||
);
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void redundantGetAndSetUserId() {
|
void redundantGetAndSetUserId() {
|
||||||
check("seteuid(geteuid());\n", NULL, false , false, true);
|
check("seteuid(geteuid());\n", NULL, false , false, true);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
||||||
|
@ -4073,37 +3859,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void suspiciousSizeofCalculation() {
|
|
||||||
check("int* p;\n"
|
|
||||||
"return sizeof(p)/5;");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Division of result of sizeof() on pointer type.\n", errout.str());
|
|
||||||
|
|
||||||
check("unknown p;\n"
|
|
||||||
"return sizeof(p)/5;");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("return sizeof(unknown)/5;");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("int p;\n"
|
|
||||||
"return sizeof(p)/5;");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("int* p[5];\n"
|
|
||||||
"return sizeof(p)/5;");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
|
|
||||||
check("return sizeof(foo)*sizeof(bar);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Multiplying sizeof() with sizeof() indicates a logic error.\n", errout.str());
|
|
||||||
|
|
||||||
check("return (foo)*sizeof(bar);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("return sizeof(foo)*bar;");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void clarifyCalculation() {
|
void clarifyCalculation() {
|
||||||
check("int f(char c) {\n"
|
check("int f(char c) {\n"
|
||||||
" return 10 * (c == 0) ? 1 : 2;\n"
|
" return 10 * (c == 0) ? 1 : 2;\n"
|
||||||
|
@ -4933,208 +4688,6 @@ private:
|
||||||
errout.str());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkPointerSizeof() {
|
|
||||||
check("void f() {\n"
|
|
||||||
" char *x = malloc(10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(*x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(&x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(100 * sizeof(x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(x) * 100);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof *x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(100 * sizeof x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = calloc(1, sizeof(*x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = calloc(1, sizeof *x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = calloc(1, sizeof(x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = calloc(1, sizeof x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = calloc(1, sizeof(int));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" char x[10];\n"
|
|
||||||
" memset(x, 0, sizeof(x));\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" char* x[10];\n"
|
|
||||||
" memset(x, 0, sizeof(x));\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" char x[10];\n"
|
|
||||||
" memset(x, 0, sizeof x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" memset(x, 0, sizeof(int));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" memset(x, 0, sizeof(*x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" memset(x, 0, sizeof *x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" memset(x, 0, sizeof x);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int));\n"
|
|
||||||
" memset(x, 0, sizeof(x));\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int) * 10);\n"
|
|
||||||
" memset(x, 0, sizeof(x) * 10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int) * 10);\n"
|
|
||||||
" memset(x, 0, sizeof x * 10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int) * 10);\n"
|
|
||||||
" memset(x, 0, sizeof(*x) * 10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int) * 10);\n"
|
|
||||||
" memset(x, 0, sizeof *x * 10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" int *x = malloc(sizeof(int) * 10);\n"
|
|
||||||
" memset(x, 0, sizeof(int) * 10);\n"
|
|
||||||
" free(x);\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int fun(const char *buf1)\n"
|
|
||||||
"{\n"
|
|
||||||
" const char *buf1_ex = \"foobarbaz\";\n"
|
|
||||||
" return strncmp(buf1, buf1_ex, sizeof(buf1_ex)) == 0;\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Size of pointer 'buf1_ex' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int fun(const char *buf1) {\n"
|
|
||||||
" return strncmp(buf1, foo(buf2), sizeof(buf1)) == 0;\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'buf1' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
// #ticket 3874
|
|
||||||
check("void f()\n"
|
|
||||||
"{\n"
|
|
||||||
" int * pIntArray[10];\n"
|
|
||||||
" memset(pIntArray, 0, sizeof(pIntArray));\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_signOfUnsignedVariable(const char code[], bool inconclusive=false) {
|
void check_signOfUnsignedVariable(const char code[], bool inconclusive=false) {
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
<ClCompile Include="testpreprocessor.cpp" />
|
<ClCompile Include="testpreprocessor.cpp" />
|
||||||
<ClCompile Include="testrunner.cpp" />
|
<ClCompile Include="testrunner.cpp" />
|
||||||
<ClCompile Include="testsimplifytokens.cpp" />
|
<ClCompile Include="testsimplifytokens.cpp" />
|
||||||
|
<ClCompile Include="testsizeof.cpp" />
|
||||||
<ClCompile Include="teststl.cpp" />
|
<ClCompile Include="teststl.cpp" />
|
||||||
<ClCompile Include="testsuite.cpp" />
|
<ClCompile Include="testsuite.cpp" />
|
||||||
<ClCompile Include="testsuppressions.cpp" />
|
<ClCompile Include="testsuppressions.cpp" />
|
||||||
|
|
|
@ -169,6 +169,9 @@
|
||||||
<ClCompile Include="testbool.cpp">
|
<ClCompile Include="testbool.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="testsizeof.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="options.h">
|
<ClInclude Include="options.h">
|
||||||
|
|
|
@ -0,0 +1,491 @@
|
||||||
|
/*
|
||||||
|
* Cppcheck - A tool for static C/C++ code analysis
|
||||||
|
* Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "tokenize.h"
|
||||||
|
#include "checksizeof.h"
|
||||||
|
#include "testsuite.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
|
class TestSizeof : public TestFixture {
|
||||||
|
public:
|
||||||
|
TestSizeof() : TestFixture("TestSizeof")
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
TEST_CASE(sizeofsizeof);
|
||||||
|
TEST_CASE(sizeofCalculation);
|
||||||
|
TEST_CASE(checkPointerSizeof);
|
||||||
|
TEST_CASE(sizeofForArrayParameter);
|
||||||
|
TEST_CASE(sizeofForNumericParameter);
|
||||||
|
TEST_CASE(suspiciousSizeofCalculation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check(const char code[]) {
|
||||||
|
// Clear the error buffer..
|
||||||
|
errout.str("");
|
||||||
|
|
||||||
|
Settings settings;
|
||||||
|
settings.addEnabled("warning");
|
||||||
|
settings.inconclusive = true;
|
||||||
|
|
||||||
|
// Tokenize..
|
||||||
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
|
||||||
|
// Check...
|
||||||
|
CheckSizeof checkSizeof(&tokenizer, &settings, this);
|
||||||
|
checkSizeof.runChecks(&tokenizer, &settings, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sizeofsizeof() {
|
||||||
|
check("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int i = sizeof sizeof char;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" int i = sizeof (sizeof long);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(long *p)\n"
|
||||||
|
"{\n"
|
||||||
|
" int i = sizeof (sizeof (p));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling 'sizeof' on 'sizeof'.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void sizeofCalculation() {
|
||||||
|
check("int a, b; int a,sizeof(a+b)");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
||||||
|
|
||||||
|
check("int a, b; sizeof(a*b)");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
||||||
|
|
||||||
|
check("int a, b; sizeof(-a)");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
||||||
|
|
||||||
|
check("int a, b; sizeof(*a)");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("sizeof(void * const)");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("sizeof(foo++)");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
||||||
|
|
||||||
|
check("sizeof(--foo)");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Found calculation inside sizeof().\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void sizeofForArrayParameter() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" int a[10];\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" unsigned int a = 2;\n"
|
||||||
|
" unsigned int b = 2;\n"
|
||||||
|
" int c[(a+b)];\n"
|
||||||
|
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" unsigned int a = { 2 };\n"
|
||||||
|
" unsigned int b[] = { 0 };\n"
|
||||||
|
" int c[a[b[0]]];\n"
|
||||||
|
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" unsigned int a[] = { 1 };\n"
|
||||||
|
" unsigned int b = 2;\n"
|
||||||
|
" int c[(a[0]+b)];\n"
|
||||||
|
" std::cout << sizeof(c) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int a[] = { 1, 2, 3 };\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int a[3] = { 1, 2, 3 };\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f( int a[]) {\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
||||||
|
"function argument returns size of a pointer.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f( int a[]) {\n"
|
||||||
|
" std::cout << sizeof a / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
||||||
|
"function argument returns size of a pointer.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f( int a[3] ) {\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
||||||
|
"function argument returns size of a pointer.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(int *p) {\n"
|
||||||
|
" p[0] = 0;\n"
|
||||||
|
" int unused = sizeof(p);\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char p[] = \"test\";\n"
|
||||||
|
" int unused = sizeof(p);\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// ticket #2495
|
||||||
|
check("void f() {\n"
|
||||||
|
" static float col[][3]={\n"
|
||||||
|
" {1,0,0},\n"
|
||||||
|
" {0,0,1},\n"
|
||||||
|
" {0,1,0},\n"
|
||||||
|
" {1,0,1},\n"
|
||||||
|
" {1,0,1},\n"
|
||||||
|
" {1,0,1},\n"
|
||||||
|
" };\n"
|
||||||
|
" const int COL_MAX=sizeof(col)/sizeof(col[0]);\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// ticket #155
|
||||||
|
check("void f() {\n"
|
||||||
|
" char buff1[1024*64],buff2[sizeof(buff1)*2];\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// ticket #2510
|
||||||
|
check("void f( int a[], int b) {\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
||||||
|
"function argument returns size of a pointer.\n", errout.str());
|
||||||
|
|
||||||
|
// ticket #2510
|
||||||
|
check("void f( int a[3] , int b[2] ) {\n"
|
||||||
|
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Using 'sizeof' on array given as "
|
||||||
|
"function argument returns size of a pointer.\n", errout.str());
|
||||||
|
|
||||||
|
// ticket #2510
|
||||||
|
check("void f() {\n"
|
||||||
|
" char buff1[1024*64],buff2[sizeof(buff1)*(2+1)];\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sizeofForNumericParameter() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" std::cout << sizeof(10) << std::endl;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" std::cout << sizeof(-10) << std::endl;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" std::cout << sizeof 10 << std::endl;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" std::cout << sizeof -10 << std::endl;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void suspiciousSizeofCalculation() {
|
||||||
|
check("int* p;\n"
|
||||||
|
"return sizeof(p)/5;");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Division of result of sizeof() on pointer type.\n", errout.str());
|
||||||
|
|
||||||
|
check("unknown p;\n"
|
||||||
|
"return sizeof(p)/5;");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("return sizeof(unknown)/5;");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("int p;\n"
|
||||||
|
"return sizeof(p)/5;");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("int* p[5];\n"
|
||||||
|
"return sizeof(p)/5;");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
|
||||||
|
check("return sizeof(foo)*sizeof(bar);");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Multiplying sizeof() with sizeof() indicates a logic error.\n", errout.str());
|
||||||
|
|
||||||
|
check("return (foo)*sizeof(bar);");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("return sizeof(foo)*bar;");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPointerSizeof() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *x = malloc(10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(*x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(&x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(100 * sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(x) * 100);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof *x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(100 * sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(*x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof *x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(int));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char x[10];\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char* x[10];\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char x[10];\n"
|
||||||
|
" memset(x, 0, sizeof x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(int));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(*x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof *x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(x) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof x * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(*x) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof *x * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(int) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check(
|
||||||
|
"int fun(const char *buf1)\n"
|
||||||
|
"{\n"
|
||||||
|
" const char *buf1_ex = \"foobarbaz\";\n"
|
||||||
|
" return strncmp(buf1, buf1_ex, sizeof(buf1_ex)) == 0;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Size of pointer 'buf1_ex' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check(
|
||||||
|
"int fun(const char *buf1) {\n"
|
||||||
|
" return strncmp(buf1, foo(buf2), sizeof(buf1)) == 0;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'buf1' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
// #ticket 3874
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" int * pIntArray[10];\n"
|
||||||
|
" memset(pIntArray, 0, sizeof(pIntArray));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue