38 #include <unordered_map> 
   61     logChecker(
"CheckFunctions::checkProhibitedFunctions");
 
   74                                     "Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n" 
   75                                     "The obsolete function 'alloca' is called. In C99 and later it is recommended to use a variable length array or " 
   76                                     "a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons " 
   77                                     "(http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).");
 
   81                                 "Obsolete function 'alloca' called.\n" 
   82                                 "The obsolete function 'alloca' is called. In C++11 and later it is recommended to use std::array<> or " 
   83                                 "a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons " 
   84                                 "(http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).");
 
   86                 if (tok->function() && tok->function()->hasBody())
 
  106     logChecker(
"CheckFunctions::invalidFunctionUsage");
 
  112             const Token * 
const functionToken = tok;
 
  113             const std::vector<const Token *> arguments = 
getArguments(tok);
 
  114             for (
int argnr = 1; argnr <= arguments.size(); ++argnr) {
 
  115                 const Token * 
const argtok = arguments[argnr-1];
 
  139                         if ((valueType->
type == ValueType::Type::CHAR || valueType->
type == ValueType::Type::WCHAR_T || (valueType->
type == ValueType::Type::RECORD && 
Token::Match(argtok, 
"& %var% . %var% ,|)"))) &&
 
  149                     if (variable && variable->
isLocal()
 
  150                         && valueType && (valueType->
type == ValueType::Type::CHAR || valueType->
type == ValueType::Type::WCHAR_T)
 
  161                             varTok = varTok->
tokAt(1);
 
  162                             auto charsUntilFirstZero = 0;
 
  165                                 varTok = varTok->
next();
 
  168                                         varTok = varTok->
next();
 
  171                                     ++charsUntilFirstZero;
 
  177                                 && (count == -1 || (count > 0 && count <= charsUntilFirstZero))) {
 
  180                         } 
else if (count > -1 && 
Token::Match(varTok, 
"= %str%")) {
 
  184                                 if (strSize > count && strTok->
str().find(
'\0') == std::string::npos)
 
  197     std::ostringstream errmsg;
 
  198     errmsg << 
"$symbol:" << functionName << 
'\n';
 
  199     if (invalidValue && invalidValue->
condition)
 
  201                << 
" or $symbol() argument nr " << argnr << 
" can have invalid value.";
 
  203         errmsg << 
"Invalid $symbol() argument nr " << argnr << 
'.';
 
  205         errmsg << 
" The value is " << std::setprecision(10) << (invalidValue->
isIntValue() ? invalidValue->
intvalue : invalidValue->
floatValue) << 
" but the valid values are '" << validstr << 
"'.";
 
  207         errmsg << 
" The value is 0 or 1 (boolean) but the valid values are '" << validstr << 
"'.";
 
  211                     "invalidFunctionArg",
 
  218                     "invalidFunctionArg",
 
  226     std::ostringstream errmsg;
 
  227     errmsg << 
"$symbol:" << functionName << 
'\n';
 
  228     errmsg << 
"Invalid $symbol() argument nr " << argnr << 
". A non-boolean value is required.";
 
  234     std::ostringstream errmsg;
 
  235     errmsg << 
"$symbol:" << functionName << 
'\n';
 
  236     errmsg << 
"Invalid $symbol() argument nr " << argnr << 
". A nul-terminated string is required.";
 
  250     logChecker(
"CheckFunctions::checkIgnoredReturnValue"); 
 
  257                 tok = tok->linkAt(1);
 
  261             if (tok->varId() || tok->isKeyword() || tok->isStandardType() || !
Token::Match(tok, 
"%name% ("))
 
  273             if (!tok->scope()->isExecutable()) {
 
  274                 tok = tok->scope()->bodyEnd;
 
  278             if ((!tok->function() || !
Token::Match(tok->function()->retDef, 
"void %name%")) &&
 
  279                 tok->next()->astOperand1()) {
 
  281                 const bool warn = (tok->function() && tok->function()->isAttributeNodiscard()) || 
 
  302                 "$symbol:" + 
function + 
"\nError code from the return value of function $symbol() is not used.", 
CWE252, 
Certainty::normal);
 
  312     logChecker(
"CheckFunctions::checkMissingReturn");
 
  316         if (!
function || !function->hasBody())
 
  320         if (function->type != Function::Type::eFunction && function->type != Function::Type::eOperatorEqual)
 
  322         if (
Token::Match(function->retDef, 
"%name% (") && function->retDef->isUpperCaseName())
 
  336     for (
const Token *prev = gotoToken; gotoToken; gotoToken = gotoToken->
previous()) {
 
  347     const Token *lastStatement = 
nullptr;
 
  348     while ((tok = tok->
previous()) != 
nullptr) {
 
  349         if (tok->
str() == 
")")
 
  351         if (tok->
str() == 
"{")
 
  352             return lastStatement ? lastStatement : tok->
next();
 
  353         if (tok->
str() == 
"}") {
 
  354             for (
const Token *prev = tok->
link()->previous(); prev && prev->scope() == tok->
scope() && !
Token::Match(prev, 
"[;{}]"); prev = prev->previous()) {
 
  355                 if (prev->isKeyword() && 
Token::Match(prev, 
"return|throw"))
 
  360             if (tok->
scope()->type == Scope::ScopeType::eSwitch) {
 
  362                 bool hasDefault = 
false;
 
  363                 bool reachable = 
false;
 
  364                 for (
const Token *switchToken = tok->
link()->next(); switchToken != tok; switchToken = switchToken->
next()) {
 
  371                     if (switchToken->isKeyword() && 
Token::Match(switchToken, 
"return|throw"))
 
  379                     else if (switchToken->str() == 
"{" && (switchToken->scope()->isLoopScope() || switchToken->scope()->type == Scope::ScopeType::eSwitch))
 
  380                         switchToken = switchToken->
link();
 
  384             } 
else if (tok->
scope()->type == Scope::ScopeType::eIf) {
 
  385                 const Token *condition = tok->
scope()->classDef->next()->astOperand2();
 
  389             } 
else if (tok->
scope()->type == Scope::ScopeType::eElse) {
 
  411             lastStatement = tok->
next();
 
  419                 "Found an exit path from function with non-void return type that has missing return statement", 
CWE758, 
Certainty::normal);
 
  432     logChecker(
"CheckFunctions::checkMathFunctions"); 
 
  439             if (printWarnings && 
Token::Match(tok, 
"%name% ( !!)")) {
 
  440                 if (tok->strAt(-1) != 
"." 
  441                     && 
Token::Match(tok, 
"log|logf|logl|log10|log10f|log10l|log2|log2f|log2l ( %num% )")) {
 
  442                     const std::string& number = tok->strAt(2);
 
  446                 } 
else if (
Token::Match(tok, 
"log1p|log1pf|log1pl ( %num% )")) {
 
  447                     const std::string& number = tok->strAt(2);
 
  453                 else if (
Token::Match(tok, 
"atan2|atan2f|atan2l ( %num% , %num% )")) {
 
  464                 else if (
Token::Match(tok, 
"pow|powf|powl ( %num% , %num% )")) {
 
  490         else if (numParam == 2)
 
  516     logChecker(
"CheckFunctions::memsetZeroBytes"); 
 
  522                 const std::vector<const Token *> &arguments = 
getArguments(tok);
 
  525                 const Token* lastParamTok = arguments[2];
 
  535     const std::string summary(
"memset() called to fill 0 bytes.");
 
  536     const std::string verbose(summary + 
" The second and third arguments might be inverted." 
  537                               " The function memset ( void * ptr, int value, size_t num ) sets the" 
  538                               " first num bytes of the block of memory pointed by ptr to the specified value.");
 
  554     if (!printWarning && !printPortability)
 
  557     logChecker(
"CheckFunctions::memsetInvalid2ndParam"); 
 
  565             const std::vector<const Token *> args = 
getArguments(tok);
 
  566             if (args.size() != 3)
 
  570             const Token * 
const secondParamTok = args[1];
 
  575             if (printPortability && 
astIsFloat(secondParamTok,
false)) {
 
  579             if (printWarning && secondParamTok->
isNumber()) { 
 
  583                 if (value < sCharMin || value > uCharMax)
 
  592     const std::string message(
"The 2nd memset() argument '" + var_value +
 
  593                               "' is a float, its representation is implementation defined.");
 
  594     const std::string verbose(message + 
" memset() is used to set each byte of a block of memory to a specific value and" 
  595                               " the actual representation of a floating-point value is implementation defined.");
 
  601     const std::string message(
"The 2nd memset() argument '" + value + 
"' doesn't fit into an 'unsigned char'.");
 
  602     const std::string verbose(message + 
" The 2nd parameter is passed as an 'int', but the function fills the block of memory using the 'unsigned char' conversion of this value.");
 
  615     bool insideNew = 
false;
 
  617         if (!tok->scope() || !tok->scope()->isExecutable())
 
  620         if (tok->str() == 
"new")
 
  622         else if (tok->str() == 
";")
 
  630         if (tok->varId() != 0 || tok->type() || tok->isStandardType())
 
  633         if (tok->linkAt(1)->strAt(1) == 
"(")
 
  654         if (functionName.empty())
 
  666         const Token* start = tok;
 
  668             start = start->
tokAt(-2);
 
  674                     "checkLibraryFunction",
 
  675                     "--check-library: There is no matching configuration for function " + functionName + 
"()");
 
  690     logChecker(
"CheckFunctions::returnLocalStdMove"); 
 
  698         for (
const Token* ret : rets) {
 
  716                 "returnStdMoveLocal",
 
  717                 "Using std::move for returning object by-value from function will affect copy elision optimization." 
  718                 " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local");
 
  726     logChecker(
"CheckFunctions::useStandardLibrary"); 
 
  729         if (scope.type != Scope::ScopeType::eFor)
 
  732         const Token *forToken = scope.classDef;
 
  749         const auto idxVarId = idxToken->
varId();
 
  757         const auto& secondOp = condToken->
str();
 
  758         const bool isLess = 
"<" == secondOp &&
 
  761         const bool isMore = 
">" == secondOp &&
 
  765         if (!(isLess || isMore))
 
  770         const bool plusOne = stepToken->
isBinaryOp() && stepToken->
str() == 
"+=" &&
 
  773         if (!inc && !plusOne)
 
  778         const Token *tok = scope.bodyStart;
 
  779         const std::string memcpyName = tok->
isCpp() ? 
"std::memcpy" : 
"memcpy";
 
  781         if (
Token::Match(tok, 
"{ (| reinterpret_cast < uint8_t|int8_t|char|void * > ( %var% ) )| [ %varid% ] = " 
  782                          "(| reinterpret_cast < const| uint8_t|int8_t|char|void * > ( %var% ) )| [ %varid% ] ; }", idxVarId)) {
 
  788         if (
Token::Match(tok, 
"{ ( ( uint8_t|int8_t|char|void * ) (| %var% ) )| [ %varid% ] = " 
  789                          "( ( const| uint8_t|int8_t|char|void * ) (| %var% ) )| [ %varid% ] ; }", idxVarId)) {
 
  795         const static std::string memsetName = tok->
isCpp() ? 
"std::memset" : 
"memset";
 
  797         if (
Token::Match(tok, 
"{ ( ( uint8_t|int8_t|char|void * ) (| %var% ) )| [ %varid% ] = %char%|%num% ; }", idxVarId)) {
 
  803         if (
Token::Match(tok, 
"{ ( ( uint8_t|int8_t|char|void * ) (| %var% ) )| [ %varid% ] = " 
  804                          "( const| uint8_t|int8_t|char ) (| %char%|%num% )| ; }", idxVarId)) {
 
  810         if (
Token::Match(tok, 
"{ (| reinterpret_cast < uint8_t|int8_t|char|void * > ( %var% ) )| [ %varid% ] = " 
  811                          "(| static_cast < const| uint8_t|int8_t|char > ( %char%|%num% ) )| ; }", idxVarId)) {
 
  817         if (
Token::Match(tok, 
"{ (| reinterpret_cast < uint8_t|int8_t|char|void * > ( %var% ) )| [ %varid% ] = " 
  818                          "%char%|%num% ; }", idxVarId)) {
 
  828                 "useStandardLibrary",
 
  829                 "Consider using " + expected + 
" instead of loop.");
 
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
 
bool astIsBool(const Token *tok)
Is expression of boolean type?
 
Token * getInitTok(Token *tok)
 
Library::Container::Action astContainerAction(const Token *tok, const Token **ftok)
 
Token * getCondTok(Token *tok)
 
bool astIsFloat(const Token *tok, bool unknown)
Is expression of floating point type?
 
Token * getStepTok(Token *tok)
 
bool isVariablesChanged(const Token *start, const Token *end, int indirect, const std::vector< const Variable * > &vars, const Settings &settings)
 
bool isConstExpression(const Token *tok, const Library &library)
 
Library::Container::Yield astContainerYield(const Token *tok, const Token **ftok)
 
int numberOfArguments(const Token *ftok)
Determines the number of arguments - if token is a function call or macro.
 
#define WRONG_DATA(COND, TOK)
Use WRONG_DATA in checkers to mark conditions that check that data is correct.
 
static const CWE CWE252(252U)
 
static const CWE CWE758(758U)
 
static const CWE CWE687(687U)
 
static const CWE CWE477(477U)
 
static const CWE CWE686(686U)
 
static bool isForwardJump(const Token *gotoToken)
 
static const CWE CWE688(688U)
 
static const CWE CWE628(628U)
 
static const Token * checkMissingReturnScope(const Token *tok, const Library &library)
 
Check for bad function usage.
 
void checkMissingReturn()
Check for missing "return"
 
void checkProhibitedFunctions()
Check for functions that should not be used.
 
void memsetZeroBytes()
Check for filling zero bytes with memset()
 
void ignoredReturnErrorCode(const Token *tok, const std::string &function)
 
void ignoredReturnValueError(const Token *tok, const std::string &function)
 
void invalidFunctionArgError(const Token *tok, const std::string &functionName, int argnr, const ValueFlow::Value *invalidValue, const std::string &validstr)
 
void memsetZeroBytesError(const Token *tok)
 
void useStandardLibrary()
 
void invalidFunctionArgStrError(const Token *tok, const std::string &functionName, nonneg int argnr)
 
void checkIgnoredReturnValue()
Check for ignored return values.
 
void missingReturnError(const Token *tok)
 
void memsetValueOutOfRangeError(const Token *tok, const std::string &value)
 
void invalidFunctionUsage()
Invalid function usage (invalid input value / overlapping data)
 
void checkLibraryMatchFunctions()
–check-library: warn for unconfigured function calls
 
void mathfunctionCallWarning(const Token *tok, const nonneg int numParam=1)
 
void invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr)
 
void useStandardLibraryError(const Token *tok, const std::string &expected)
 
void memsetInvalid2ndParam()
Check for invalid 2nd parameter of memset()
 
void checkMathFunctions()
Check for parameters given to math function that do not make sense
 
void copyElisionError(const Token *tok)
 
void returnLocalStdMove()
Check for copy elision by RVO|NRVO
 
void memsetFloatError(const Token *tok, const std::string &var_value)
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value, std::string bug) const
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
static std::vector< const Token * > findReturns(const Function *f)
 
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
 
static bool returnsVoid(const Function *function, bool unknown=false)
 
Library definitions handling.
 
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
 
const std::string & validarg(const Token *ftok, int argnr) const
 
bool isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const
 
bool isnoreturn(const Token *ftok) const
 
bool isboolargbad(const Token *ftok, int argnr) const
 
bool isnotnoreturn(const Token *ftok) const
 
UseRetValType getUseRetValType(const Token *ftok) const
 
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
 
const WarnInfo * getWarnInfo(const Token *ftok) const
 
bool isargstrz(const Token *ftok, int argnr) const
 
TypeCheck getTypeCheck(std::string check, std::string typeName) const
 
const PodType * podtype(const std::string &name) const
 
std::string getFunctionName(const Token *ftok) const
Get function name for function call.
 
bool isNotLibraryFunction(const Token *ftok) const
 
std::unordered_map< std::string, Function > functions
 
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
 
static bool isFloat(const std::string &str)
 
static bool isNullValue(const std::string &str)
Does the string represent the numerical value of 0? In case leading or trailing white space is provid...
 
static bool isNegative(const std::string &str)
 
static bool isInt(const std::string &str)
 
static double toDoubleNumber(const std::string &str)
for conversion of numeric literals
 
Function * function
function info for this function
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
bool checkLibrary
Check for incomplete info in library files?
 
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
 
bool daca
Are we running from DACA script?
 
SimpleEnableGroup< Severity > severity
 
Standards standards
Struct contains standards settings.
 
bool isEnabled(T flag) const
 
std::vector< const Scope * > functionScopes
Fast access to function scopes.
 
std::list< Scope > scopeList
Information about all namespaces/classes/structures.
 
The token list that the TokenList generates is a linked-list of this class.
 
bool hasKnownValue() const
 
const ValueFlow::Value * getValue(const MathLib::bigint val) const
 
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 hasKnownIntValue() const
 
MathLib::bigint getKnownIntValue() const
 
const Token * getValueTokenMinStrSize(const Settings &settings, MathLib::bigint *path=nullptr) const
 
const ValueType * valueType() const
 
const std::string & strAt(int index) const
 
void astOperand1(Token *tok)
 
std::string expressionString() const
 
static nonneg int getStrArraySize(const Token *tok)
 
const Token * tokAt(int index) const
 
void astOperand2(Token *tok)
 
void scope(const Scope *s)
Associate this token with given scope.
 
void link(Token *linkToToken)
Create link to given token.
 
const ValueFlow::Value * getInvalidValue(const Token *ftok, nonneg int argnr, const Settings &settings) const
 
void variable(const Variable *v)
Associate this token with given variable.
 
bool isComparisonOp() const
 
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
 
static bool isOneNumber(const std::string &s)
Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not?
 
bool isC() const
Is the code C.
 
const SymbolDatabase * getSymbolDatabase() const
 
bool isCPP() const
Is the code CPP.
 
bool errorSeverity() const
 
double floatValue
float value
 
const Token * condition
Condition that this value depends on.
 
long long intvalue
int value (or sometimes bool value?)
 
bool isInconclusive() const
 
enum ValueType::Type type
 
Reference reference
Is the outermost indirection of this type a reference or rvalue.
 
Information about a member variable.
 
bool isLocal() const
Is variable local.
 
const Token * declEndToken() const
Get end token of variable declaration E.g.
 
bool isGlobal() const
Is variable global.
 
bool isConst() const
Is variable const.
 
bool isArray() const
Is variable an array.
 
@ portability
Portability warning.
 
@ information
Checking information.
 
@ performance
Performance warning.
 
@ error
Programming error.
 
std::string eitherTheConditionIsRedundant(const Token *condition)
 
enum Standards::cppstd_t cpp