ticket 155

This commit is contained in:
Sébastien Debrard 2011-01-23 03:37:38 +01:00
parent 8f4ea30792
commit b5cd37e822
3 changed files with 40 additions and 18 deletions

View File

@ -79,24 +79,25 @@ void CheckOther::checkFflushOnInputStream()
} }
void CheckOther::checkSizeofWithSilentArrayPointer() void CheckOther::checkSizeofForArrayParameter()
{ {
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var% ")) if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var% "))
{ {
int tokIdx = 1; int tokIdx = 1;
if (tok->tokAt(tokIdx)->str() == "(") { if (tok->tokAt(tokIdx)->str() == "(")
{
++tokIdx; ++tokIdx;
} }
if (tok->tokAt(tokIdx)->varId() > 0) if (tok->tokAt(tokIdx)->varId() > 0)
{ {
const Token *declTok = Token::findmatch(_tokenizer->tokens(), "%varid% [", tok->tokAt(tokIdx)->varId()); const Token *declTok = Token::findmatch(_tokenizer->tokens(), "%varid%", tok->tokAt(tokIdx)->varId());
if (declTok) if (declTok)
{ {
if (!(Token::simpleMatch(declTok->next()->link(), "] = {")) && !(Token::simpleMatch(declTok->next()->link(), "] ;"))) if ((Token::simpleMatch(declTok->next(), "[")) && !(Token::simpleMatch(declTok->next()->link(), "] = {")) && !(Token::simpleMatch(declTok->next()->link(), "] ;")))
{ {
sizeofWithSilentArrayPointerError(tok); sizeofForArrayParameterError(tok);
} }
} }
} }
@ -482,10 +483,21 @@ void CheckOther::invalidScanf()
} }
} }
void CheckOther::sizeofWithSilentArrayPointerError(const Token *tok) void CheckOther::sizeofForArrayParameterError(const Token *tok)
{ {
reportError(tok, Severity::error, "sizeofwithsilentarraypointer", "silent pointer of array is passed as parameter to the function sizeof."); reportError(tok, Severity::error,
"sizeofwithsilentarraypointer", "Using sizeof for array given as function argument "
"returns the size of pointer.\n"
"Giving array as function parameter and then using sizeof-operator for the array "
"argument. In this case the sizeof-operator returns the size of pointer (in the "
" system). 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::invalidScanfError(const Token *tok) void CheckOther::invalidScanfError(const Token *tok)
{ {

View File

@ -62,7 +62,7 @@ public:
checkOther.sizeofCalculation(); checkOther.sizeofCalculation();
checkOther.checkRedundantAssignmentInSwitch(); checkOther.checkRedundantAssignmentInSwitch();
checkOther.checkAssignmentInAssert(); checkOther.checkAssignmentInAssert();
checkOther.checkSizeofWithSilentArrayPointer(); checkOther.checkSizeofForArrayParameter();
} }
/** @brief Run checks against the simplified token list */ /** @brief Run checks against the simplified token list */
@ -171,8 +171,8 @@ public:
/** @brief %Check for filling zero bytes with memset() */ /** @brief %Check for filling zero bytes with memset() */
void checkMemsetZeroBytes(); void checkMemsetZeroBytes();
/** @brief %Check if parameter of sizeof() is typed as a silent pointer of array */ /** @brief %Check for using sizeof with array given as function argument */
void checkSizeofWithSilentArrayPointer(); void checkSizeofForArrayParameter();
// Error messages.. // Error messages..
void cstyleCastError(const Token *tok); void cstyleCastError(const Token *tok);
@ -197,7 +197,7 @@ public:
void misusedScopeObjectError(const Token *tok, const std::string &varname); void misusedScopeObjectError(const Token *tok, const std::string &varname);
void catchExceptionByValueError(const Token *tok); void catchExceptionByValueError(const Token *tok);
void memsetZeroBytesError(const Token *tok, const std::string &varname); void memsetZeroBytesError(const Token *tok, const std::string &varname);
void sizeofWithSilentArrayPointerError(const Token *tok); void sizeofForArrayParameterError(const Token *tok);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{ {
@ -210,7 +210,7 @@ public:
c.mathfunctionCallError(0); c.mathfunctionCallError(0);
c.fflushOnInputStreamError(0, "stdin"); c.fflushOnInputStreamError(0, "stdin");
c.misusedScopeObjectError(NULL, "varname"); c.misusedScopeObjectError(NULL, "varname");
c.sizeofWithSilentArrayPointerError(0); c.sizeofForArrayParameterError(0);
// style/warning // style/warning
c.cstyleCastError(0); c.cstyleCastError(0);
@ -253,7 +253,7 @@ public:
"* using fflush() on an input stream\n" "* using fflush() on an input stream\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"
"* silent array pointer as parameter of sizeof\n" "* sizeof for array given as function argument\n"
// style // style
"* C-style pointer cast in cpp file\n" "* C-style pointer cast in cpp file\n"

View File

@ -120,7 +120,7 @@ private:
checkOther.sizeofCalculation(); checkOther.sizeofCalculation();
checkOther.checkRedundantAssignmentInSwitch(); checkOther.checkRedundantAssignmentInSwitch();
checkOther.checkAssignmentInAssert(); checkOther.checkAssignmentInAssert();
checkOther.checkSizeofWithSilentArrayPointer(); checkOther.checkSizeofForArrayParameter();
// Simplify token list.. // Simplify token list..
tokenizer.simplifyTokenList(); tokenizer.simplifyTokenList();
@ -1718,19 +1718,29 @@ private:
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n" " std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
"}\n" "}\n"
); );
ASSERT_EQUALS("[test.cpp:2]: (error) silent pointer of array is passed as parameter to the function sizeof.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (error) Using sizeof for array given as "
"function argument returns the size of pointer.\n", errout.str());
check("void f( int a[]) {\n" check("void f( int a[]) {\n"
" std::cout << sizeof a / sizeof(int) << std::endl;\n" " std::cout << sizeof a / sizeof(int) << std::endl;\n"
"}\n" "}\n"
); );
ASSERT_EQUALS("[test.cpp:2]: (error) silent pointer of array is passed as parameter to the function sizeof.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (error) Using sizeof for array given as "
"function argument returns the size of pointer.\n", errout.str());
check("void f( int a[3] ) {\n" check("void f( int a[3] ) {\n"
" std::cout << sizeof(a) / sizeof(int) << std::endl;\n" " std::cout << sizeof(a) / sizeof(int) << std::endl;\n"
"}\n" "}\n"
); );
ASSERT_EQUALS("[test.cpp:2]: (error) silent pointer of array is passed as parameter to the function sizeof.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (error) Using sizeof for array given as "
"function argument returns the size of pointer.\n", errout.str());
check("void f(int *p) {\n"
" p[0] = 0;\n"
" sizeof(p);\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
} }