52 logChecker(
"CheckSizeof::checkSizeofForNumericParameter");
68 "sizeofwithnumericparameter",
"Suspicious usage of 'sizeof' with a numeric constant as parameter.\n"
69 "It is unusual to use a constant value with sizeof. For example, 'sizeof(10)'"
70 " returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 10. 'sizeof('A')'"
82 logChecker(
"CheckSizeof::checkSizeofForArrayParameter");
90 if (varTok->
str() ==
"(") {
91 varTok = varTok->
next();
105 "sizeofwithsilentarraypointer",
"Using 'sizeof' on array given as function argument "
106 "returns size of a pointer.\n"
107 "Using 'sizeof' for array given as function argument returns the size of a pointer. "
108 "It does not return the size of the whole array in bytes as might be "
109 "expected. For example, this code:\n"
110 " int f(char a[100]) {\n"
111 " return sizeof(a);\n"
113 "returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the "
123 logChecker(
"CheckSizeof::checkSizeofForPointerSize");
128 const Token* tokSize;
129 const Token* tokFunc;
130 const Token *variable =
nullptr;
131 const Token *variable2 =
nullptr;
140 else if (tok->strAt(1) ==
")" &&
Token::Match(tok->linkAt(1)->tokAt(-2),
"%var% ="))
143 variable = tok->
link()->tokAt(-3);
144 tokSize = tok->
tokAt(4);
145 tokFunc = tok->
tokAt(2);
147 variable = tok->
tokAt(2);
152 }
else if (
Token::Match(tok,
"memcpy|memcmp|memmove|strncpy|strncmp|strncat (") && tok->strAt(-1) !=
".") {
153 variable = tok->
tokAt(2);
163 if (tokSize && tokFunc->
str() ==
"calloc")
167 const Token *
const paramsListEndTok = tokFunc->
linkAt(1);
168 for (
const Token* tok2 = tokSize; tok2 != paramsListEndTok; tok2 = tok2->
next()) {
177 auto hasMultiplication = [](
const Token* parTok) ->
bool {
179 if (parTok->isArithmeticalOp() && parTok->str() ==
"*") {
181 if (std::any_of(std::begin(szToks), std::end(szToks), [](
const Token* szTok) {
186 parTok = parTok->astParent();
190 if (hasMultiplication(tok2->astParent()))
198 if (!variable || !tokSize)
202 variable = variable->
tokAt(2);
205 variable2 = variable2->
tokAt(2);
227 if (variable ==
nullptr && variable2 ==
nullptr) {
233 for (; tokSize && tokSize->
str() !=
")" && tokSize->
str() !=
"," && tokSize->
str() !=
"sizeof"; tokSize = tokSize->
next()) {}
235 if (tokSize->
str() !=
"sizeof")
240 if (tokLink && tokLink->
strAt(-1) ==
"*") {
248 tokSize = tokSize->
tokAt(3);
250 tokSize = tokSize->
tokAt(2);
252 tokSize = tokSize->
next();
255 tokSize = tokSize->
tokAt(2);
262 if (variable && tokSize->
varId() == variable->
varId())
264 if (variable2 && tokSize->
varId() == variable2->
varId())
273 "Size of pointer '" + varname +
"' used instead of size of its data.\n"
274 "Size of pointer '" + varname +
"' used instead of size of its data. "
275 "This is likely to lead to a buffer overflow. You probably intend to "
282 "Division by result of sizeof(). " + memfunc +
"() expects a size in bytes, did you intend to multiply instead?",
CWE682,
Certainty::normal);
305 "sizeofsizeof",
"Calling 'sizeof' on 'sizeof'.\n"
306 "Calling sizeof for 'sizeof looks like a suspicious code and "
307 "most likely there should be just one 'sizeof'. The current "
328 if (tok->isExpandedMacro() && tok->previous()) {
329 const Token *cast_end = (tok->previous()->str() ==
"(") ? tok->
previous() : tok;
343 else if (tok->next()->isExpandedMacro())
371 if (tok->isExpandedMacro() && tok->previous()) {
372 const Token *cast_end = (tok->previous()->str() ==
"(") ? tok->
previous() : tok;
407 logChecker(
"CheckSizeof::suspiciousSizeofCalculation");
412 if (lPar && lPar->
str() ==
"(") {
441 "divideSizeof",
"Division of result of sizeof() on pointer type.\n"
442 "Division of result of sizeof() on pointer type. sizeof() returns the size of the pointer, "
457 const ValueType *vt = tok->next()->astOperand2()->valueType();
458 if (vt && vt->
type == ValueType::Type::VOID && vt->
pointer == 0U)
460 }
else if (tok->str() ==
"-") {
462 const ValueType *vt1 = tok->astOperand1() ? tok->astOperand1()->valueType() :
nullptr;
463 const ValueType *vt2 = tok->astOperand2() ? tok->astOperand2()->valueType() :
nullptr;
464 const bool op1IsvoidPointer = (vt1 && vt1->
type == ValueType::Type::VOID && vt1->
pointer == 1U);
466 if (op1IsvoidPointer && op2IsIntegral)
469 const ValueType *vt1 = tok->astOperand1() ? tok->astOperand1()->valueType() :
nullptr;
470 const ValueType *vt2 = tok->astOperand2() ? tok->astOperand2()->valueType() :
nullptr;
472 const bool voidpointer1 = (vt1 && vt1->
type == ValueType::Type::VOID && vt1->
pointer == 1U);
473 const bool voidpointer2 = (vt2 && vt2->
type == ValueType::Type::VOID && vt2->
pointer == 1U);
478 if (!tok->isAssignmentOp() && voidpointer2)
486 const std::string message =
"Behaviour of 'sizeof(void)' is not covered by the ISO C standard.";
487 const std::string verbose = message +
" A value for 'sizeof(void)' is defined only as part of a GNU C extension, which defines 'sizeof(void)' to be 1.";
493 const std::string message =
"'*" + varname +
"' is of type 'void', the behaviour of 'sizeof(void)' is not covered by the ISO C standard.";
494 const std::string verbose = message +
" A value for 'sizeof(void)' is defined only as part of a GNU C extension, which defines 'sizeof(void)' to be 1.";
500 const std::string message =
"'$symbol' is of type '" + vartype +
"'. When using void pointers in calculations, the behaviour is undefined.";
501 const std::string verbose = message +
" Arithmetic operations on 'void *' is a GNU C extension, which defines the 'sizeof(void)' to be 1.";
static const CWE CWE682(682U)
static const CWE CWE467(467U)
checks on usage of sizeof() operator
void sizeofVoid()
Check for using sizeof(void)
void sizeofFunction()
Check for function call inside sizeof
void sizeofDereferencedVoidPointerError(const Token *tok, const std::string &varname)
void sizeofForArrayParameterError(const Token *tok)
void sizeofVoidError(const Token *tok)
void checkSizeofForNumericParameter()
Check for using sizeof with numeric given as function argument
void checkSizeofForPointerSize()
Check for using sizeof of a variable when allocating it
void suspiciousSizeofCalculation()
Check for suspicious calculations with sizeof results
void sizeofsizeofError(const Token *tok)
void sizeofForNumericParameterError(const Token *tok)
void divideBySizeofError(const Token *tok, const std::string &memfunc)
void checkSizeofForArrayParameter()
Check for using sizeof with array given as function argument
void divideSizeofError(const Token *tok)
void sizeofsizeof()
Check for 'sizeof sizeof ..'
void multiplySizeofError(const Token *tok)
void sizeofFunctionError(const Token *tok)
void sizeofForPointerError(const Token *tok, const std::string &varname)
void arithOperationsOnVoidPointerError(const Token *tok, const std::string &varname, const std::string &vartype)
void sizeofCalculationError(const Token *tok, bool inconclusive)
void sizeofCalculation()
Check for calculations inside sizeof
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
const Settings *const mSettings
const Tokenizer *const mTokenizer
void logChecker(const char id[])
log checker
const Scope * nestedIn
Scope the function is declared in.
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
std::multimap< std::string, const Function * > functionMap
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
SimpleEnableGroup< Certainty > certainty
SimpleEnableGroup< Severity > severity
bool isEnabled(T flag) const
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
bool isExpandedMacro() const
const ValueType * valueType() const
const std::string & strAt(int index) const
void astOperand1(Token *tok)
bool isCalculation() const
Is current token a calculation? Only true for operands.
void function(const Function *f)
Associate this token with given function.
const Token * tokAt(int index) const
Token::Type tokType() const
void astOperand2(Token *tok)
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
void variable(const Variable *v)
Associate this token with given variable.
const Token * nextArgument() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
void astParent(Token *tok)
const Token * tokens() const
const SymbolDatabase * getSymbolDatabase() const
enum ValueType::Type type
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
Information about a member variable.
bool isArgument() const
Is variable a function argument.
bool isReference() const
Is reference variable.
bool isArray() const
Is variable an array.
bool isPointer() const
Is pointer variable.
const ValueType * valueType() const
@ portability
Portability warning.