62     if (tok2 && tok2->
str() == 
"(") {
 
   64         tok2 = tok2 ? tok2->
next() : 
nullptr;
 
   68     if (tok2->
str() == 
"::")
 
   76         if (reallocType != 
No)
 
   79         if (tok2->
isCpp() && tok2->
str() == 
"new") {
 
   86                 typeTok = typeTok->
tokAt(2);
 
   87             const Scope* classScope = 
nullptr;
 
   88             if (typeTok->
type() && typeTok->
type()->isClassType()) {
 
   89                 classScope = typeTok->
type()->classScope;
 
   91                 classScope = typeTok->
function()->nestedIn;
 
   99             if (
Token::Match(tok2, 
"open|openat|creat|mkstemp|mkostemp|socket (")) {
 
  103                 if (tok2->
str() == 
"open" && num != 2 && num != 3)
 
  128         tok2 = tok2->
tokAt(2);
 
  136     if (callstack && std::find(callstack->cbegin(), callstack->cend(), func) != callstack->cend())
 
  139     std::list<const Function*> cs;
 
  143     callstack->push_back(func);
 
  152     if (tok2 && tok2->
str() == 
"(") {
 
  154         tok2 = tok2 ? tok2->
next() : 
nullptr;
 
  169     while (arg && arg->
isCast())
 
  173     if (varid > 0 && !
Token::Match(arg, 
"%varid% [,)]", varid))
 
  177     if (realloctype > 0) {
 
  195         if (vartok && vartok->
varId() == varid) {
 
  196             if (tok->
strAt(1) == 
"[")
 
  202     if (tok->
str() == 
"::")
 
  211             const Token* vartok = tok2;
 
  213                 vartok = vartok->
tokAt(2);
 
  220                     if (tok->
str() == 
"close")
 
  222                     if (tok->
str() == 
"pclose")
 
  228                 if (dealloctype > 0) {
 
  285     std::list<const Token *> callstack;
 
  288         callstack.push_back(tok);
 
  290     reportErr(callstack, severity, 
id, msg, cwe);
 
  309     reportErr(tok, 
Severity::error, 
"memleakOnRealloc", 
"$symbol:" + varname + 
"\nCommon " + reallocfunction + 
" mistake: \'$symbol\' nulled but not freed upon failure", 
CWE(401U));
 
  314     std::string errmsg(
"Resource leak");
 
  315     if (!varname.empty())
 
  316         errmsg = 
"$symbol:" + varname + 
'\n' + errmsg + 
": $symbol";
 
  322     reportErr(tok, 
Severity::error, 
"deallocuse", 
"$symbol:" + varname + 
"\nDereferencing '$symbol' after it is deallocated / released", 
CWE(416U));
 
  327     reportErr(callstack, 
Severity::error, 
"mismatchAllocDealloc", 
"$symbol:" + varname + 
"\nMismatching allocation and deallocation: $symbol", 
CWE(762U));
 
  340         if (tok2->str() == 
"{" && !tok2->scope()->isExecutable())
 
  342         if (tok2->str() == 
"return") {
 
  347             if (tok2->scope() != func->
functionScope || !tok2->astOperand1())
 
  378         if (!tok->isC() && 
Token::Match(tok, 
"[(,] %varid% [,)]", varid)) {
 
  387         if (allocType == 
No && tok->str() == 
"return")
 
  404     return vartok && (vartok->
varId() == varid);
 
  407 static bool ifvar(
const Token *tok, 
nonneg int varid, 
const std::string &comp, 
const std::string &rhs)
 
  414     if (!condition || condition->
str() == 
"&&")
 
  418     return (vartok && vartok->
varId() == varid);
 
  430     logChecker(
"CheckMemoryLeakInFunction::checkReallocUsage");
 
  438             if (tok->varId() > 0 && 
Token::Match(tok, 
"%name% =")) {
 
  442                 while (parTok && parTok->
isCast())
 
  458                 while (arg && arg->
isCast())
 
  460                 const Token* tok2 = tok;
 
  469                 if (!(tok->varId() == arg->
varId() && tok->variable() && !tok->variable()->isArgument()))
 
  482                 const Token* tokEndRealloc = reallocTok->
linkAt(1);
 
  531     const std::string& varname = tokVarname->
str();
 
  532     const int varid = tokVarname->
varId();
 
  533     const std::string& classname = scope->
className;
 
  539     bool allocInConstructor = 
false;
 
  540     bool deallocInDestructor = 
false;
 
  548                 deallocInDestructor = 
true;
 
  568                     if (tok->strAt(-1) == 
"=")
 
  573                     if (tok->strAt(-1) == 
"::" &&
 
  577                     const Token* allocTok = tok->
tokAt(body ? 2 : 3);
 
  578                     if (tok->astParent() && tok->astParent()->str() == 
"[" && tok->astParent()->astParent())
 
  579                         allocTok = tok->
astParent()->astParent()->astOperand2();
 
  584                             allocInConstructor = 
true;
 
  586                         if (memberAlloc != 
No && memberAlloc != alloc)
 
  604                 if (destructor && tok->str() == varname)
 
  608                         deallocInDestructor = 
true;
 
  618                     memberDealloc = dealloc;
 
  629     if (allocInConstructor && !deallocInDestructor) {
 
  642                 "$symbol:" + classname + 
"\n" 
  643                 "$symbol:" + varname + 
"\n" 
  644                 "Class '" + classname + 
"' is unsafe, '" + varname + 
"' can leak by wrong usage.\n" 
  645                 "The class '" + classname + 
"' is unsafe, wrong usage can cause memory/resource leaks for '" + varname + 
"'. This can for instance be fixed by adding proper cleanup in the destructor.", 
CWE398, 
Certainty::normal);
 
  657     const int varid = classtok->
varId();
 
  669             } 
else if (
Token::Match(tok2, 
"%type% :: %varid% =", varid) &&
 
  690     logChecker(
"CheckMemoryLeakStructMember::check");
 
  694         if (!var || (!var->isLocal() && !(var->isArgument() && var->scope())) || var->isStatic())
 
  696         if (var->isReference() || (var->valueType() && var->valueType()->pointer > 1))
 
  698         if (var->typeEndToken()->isStandardType())
 
  711         if (
Token::Match(tok2, 
"= %varid% [;=]", declarationId))
 
  734     int indentlevel2 = 0;
 
  736     auto deallocInFunction = [
this](
const Token* tok, 
int structid) -> 
bool {
 
  742         bool deallocated = 
false;
 
  744         for (
const Token* tok2 = tok; tok2 != end; tok2 = tok2->
next()) {
 
  745             if (
Token::Match(tok2, 
"[(,] &| %varid% [,)]", structid)) {
 
  751             if (
Token::Match(tok2, 
"[(,] &| %varid% . %name% [,)]", structid)) {
 
  762     auto isMemberAssignment = [](
const Token* varTok, 
int varId) -> std::pair<const Token*, const Token*> {
 
  763         if (varTok->
varId() != varId)
 
  765         const Token* top = varTok;
 
  774         while (dot && dot->
str() != 
".")
 
  780     std::pair<const Token*, const Token*> assignToks;
 
  785     for (
const Token *tok2 = tokStart; tok2 && tok2 != variable->
scope()->
bodyEnd; tok2 = tok2->
next()) {
 
  786         if (tok2->str() == 
"{")
 
  789         else if (tok2->str() == 
"}") {
 
  790             if (indentlevel2 == 0)
 
  801         else if ((assignToks = isMemberAssignment(tok2, variable->
declarationId())).first && assignToks.first->varId()) {
 
  802             if (
getAllocationType(assignToks.second, assignToks.first->varId()) == AllocType::No)
 
  814             const int structmemberid(assignToks.first->varId());
 
  817             int indentlevel3 = indentlevel2;
 
  818             for (
const Token *tok3 = tok2; tok3; tok3 = tok3->
next()) {
 
  819                 if (tok3->str() == 
"{")
 
  822                 else if (tok3->str() == 
"}") {
 
  823                     if (indentlevel3 == 0) {
 
  833                     if (indentlevel3 == 0)
 
  840                         if (tok3->str() == 
"return")
 
  842                         else if (tok3->str() == 
"{" || tok3->str() == 
"}")
 
  846                     if (!ret || !tok3 || tok3->str() != 
"}")
 
  854                     if (indentlevel2 == 0)
 
  861                          notvar(tok3->next()->astOperand2(), structmemberid)) {
 
  863                     tok3 = tok3->next()->link();
 
  870                     tok3 = tok3->next()->link();
 
  874                 else if (
ifvar(tok3, structmemberid, 
"!=", 
"0")) {
 
  876                     tok3 = tok3->next()->link();
 
  879                     int indentlevel4 = 0;
 
  880                     for (
const Token *tok4 = tok3; tok4; tok4 = tok4->
next()) {
 
  881                         if (tok4->str() == 
"{")
 
  883                         else if (tok4->str() == 
"}") {
 
  885                             if (indentlevel4 == 0)
 
  893                     if (indentlevel4 > 0)
 
  898                 else if ((tok3->scope()->type != Scope::ScopeType::eLambda || tok3->scope() == variable->
scope()) && tok3->str() == 
"return") {
 
  900                     if (!
Token::Match(tok3, 
"return %varid% ;", structid) &&
 
  902                         !(
Token::Match(tok3, 
"return %varid% . %var%", structid) && tok3->tokAt(3)->varId() == structmemberid) &&
 
  903                         !(
Token::Match(tok3, 
"return %name% (") && tok3->astOperand1() && deallocInFunction(tok3->astOperand1(), structid))) {
 
  912                 } 
else if (
Token::Match(tok3, 
"= %var% . %varid% ;", structmemberid)) {
 
  917                 else if (tok3->str() == 
"goto")
 
  922                     if (deallocInFunction(tok3, structid))
 
  975         const std::string& functionName = tok->str();
 
  976         if ((tok->isCpp() && functionName == 
"delete") ||
 
  977             functionName == 
"return")
 
  985         const std::vector<const Token *> args = 
getArguments(tok);
 
  987         for (
const Token* arg : args) {
 
  989             if (arg->isOp() && !(tok->isKeyword() && arg->str() == 
"*")) 
 
  991             while (arg->astOperand1()) {
 
  994                 arg = arg->astOperand1();
 
 1004                 if (bail && typeTok->
type() && typeTok->
type()->classScope &&
 
 1005                     typeTok->
type()->classScope->numConstructors == 0 &&
 
 1006                     typeTok->
type()->classScope->getDestructor() == 
nullptr) {
 
 1014             if (tok->function()) {
 
 1015                 const Variable* argvar = tok->function()->getArgumentVar(argnr);
 
 1034         const bool isNew = tok->isCpp() && tok->str() == 
"new";
 
 1042         if (allocType == 
No)
 
 1045         if (tok != tok->next()->astOperand1() && !isNew)
 
 1054         const Token *parent = isNew ? tok->
astParent() : tok->next()->astParent();
 
 1055         while (parent && parent->
isCast())
 
 1064         if (!parent && warn) {
 
 1070         } 
else if (
Token::Match(parent, 
"%comp%|!|,|%oror%|&&|:")) {
 
 1073             if (parent->
str() == 
":") {
 
 1102     logChecker(
"CheckMemoryLeakNoVar::checkForUnsafeArgAlloc");
 
 1107             const Token* pointerType = 
nullptr;
 
 1108             const Token* functionCalled = 
nullptr;
 
 1112                 const Function *func = tok2->function();
 
 1117                 } 
else if (!isNothrow) {
 
 1119                         functionCalled = tok2;
 
 1121                         functionCalled = tok2;
 
 1125             if (pointerType && functionCalled) {
 
 1126                 std::string functionName = functionCalled->
str();
 
 1127                 if (functionCalled->
strAt(1) == 
"<") {
 
 1128                     functionName += 
'<';
 
 1129                     for (
const Token* tok2 = functionCalled->
tokAt(2); tok2 != functionCalled->
next()->
link(); tok2 = tok2->next())
 
 1130                         functionName += tok2->str();
 
 1131                     functionName += 
'>';
 
 1133                 std::string objectTypeName;
 
 1134                 for (
const Token* tok2 = pointerType->
tokAt(2); tok2 != pointerType->
next()->
link(); tok2 = tok2->next())
 
 1135                     objectTypeName += tok2->str();
 
 1155     const std::string factoryFunc = ptrType == 
"shared_ptr" ? 
"make_shared" : 
"make_unique";
 
 1157                 "$symbol:" + funcName + 
"\n" 
 1158                 "Unsafe allocation. If $symbol() throws, memory could be leaked. Use " + factoryFunc + 
"<" + objType + 
">() instead.",
 
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
Is given syntax tree a variable comparison against value.
 
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
 
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
 
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
 
int numberOfArguments(const Token *ftok)
Determines the number of arguments - if token is a function call or macro.
 
static const CWE CWE398(398U)
 
static bool notvar(const Token *tok, nonneg int varid)
 
static const CWE CWE772(772U)
 
static const CWE CWE771(771U)
 
static bool ifvar(const Token *tok, nonneg int varid, const std::string &comp, const std::string &rhs)
 
static const CWE CWE401(401U)
 
Check class variables, variables that are allocated in the constructor should be deallocated in the d...
 
void unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname)
 
void variable(const Scope *scope, const Token *tokVarname)
 
void checkPublicFunctions(const Scope *scope, const Token *classtok)
Public functions: possible double-allocation.
 
void publicAllocationError(const Token *tok, const std::string &varname)
 
CheckMemoryLeakInFunction detects when a function variable is allocated but not deallocated properly.
 
void checkReallocUsage()
Checking for a memory leak caused by improper realloc usage.
 
detect simple memory leaks (address not taken)
 
void returnValueNotUsedError(const Token *tok, const std::string &alloc)
 
void checkForUnusedReturnValue(const Scope *scope)
Check if a call to an allocation function like malloc() is made and its return value is not assigned.
 
void functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall)
 
void unsafeArgAllocError(const Token *tok, const std::string &funcName, const std::string &ptrType, const std::string &objType)
 
void checkForUnreleasedInputArgument(const Scope *scope)
Check if an input argument to a function is the return value of an allocation function like malloc(),...
 
void checkForUnsafeArgAlloc(const Scope *scope)
Check if an exception could cause a leak in an argument constructed with shared_ptr/unique_ptr.
 
detect simple memory leaks for struct members
 
void checkStructVariable(const Variable *const variable) const
 
bool isMalloc(const Variable *variable) const
Is local variable allocated with malloc?
 
AllocType functionReturnType(const Function *func, std::list< const Function * > *callstack=nullptr) const
What type of allocated memory does the given function return?
 
void memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype) const
 
void deallocuseError(const Token *tok, const std::string &varname) const
 
AllocType getAllocationType(const Token *tok2, nonneg int varid, std::list< const Function * > *callstack=nullptr) const
Get type of allocation at given position.
 
AllocType getDeallocationType(const Token *tok, nonneg int varid) const
Get type of deallocation at given position.
 
AllocType getReallocationType(const Token *tok2, nonneg int varid) const
Get type of reallocation at given position.
 
bool isReopenStandardStream(const Token *tok) const
Check if token reopens a standard stream.
 
const Settings *const mSettings_
Enabled standards.
 
const Tokenizer *const mTokenizer_
For access to the tokens.
 
void resourceLeakError(const Token *tok, const std::string &varname) const
Report that there is a resource leak (fopen/popen/etc)
 
void mismatchAllocDealloc(const std::list< const Token * > &callstack, const std::string &varname) const
 
bool isOpenDevNull(const Token *tok) const
Check if token opens /dev/null.
 
ErrorLogger *const mErrorLogger_
ErrorLogger used to report errors.
 
void reportErr(const Token *tok, Severity severity, const std::string &id, const std::string &msg, const CWE &cwe) const
Report error.
 
AllocType
What type of allocation are used.
 
void memleakUponReallocFailureError(const Token *tok, const std::string &reallocfunction, const std::string &varname) const
 
void memleakError(const Token *tok, const std::string &varname) const
Report that there is a memory leak (new/malloc/etc)
 
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
 
const Settings *const mSettings
 
static void writeToErrorList(const ErrorMessage &errmsg)
Write given error to stdout in xml format.
 
const Tokenizer *const mTokenizer
 
void logChecker(const char id[])
log checker
 
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
 
Wrapper for error messages, provided by reportErr()
 
AccessControl access
public/protected/private
 
const Scope * functionScope
scope of function body
 
Type type
constructor, destructor, ...
 
const Token * arg
function argument start '('
 
bool isDestructor() const
 
bool isConstructor() const
 
bool isAttributeNothrow() const
 
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
 
int getAllocId(const Token *tok, int arg) const
get allocation id for function
 
static bool ismemory(const int id)
is allocation type memory?
 
int getDeallocId(const Token *tok, int arg) const
get deallocation id for function
 
bool isLeakIgnore(const std::string &functionName) const
 
bool isnotnoreturn(const Token *ftok) const
 
int getReallocId(const Token *tok, int arg) const
get reallocation id for function
 
const AllocFunc * getAllocFuncInfo(const Token *tok) const
get allocation info for function
 
const AllocFunc * getReallocFuncInfo(const Token *tok) const
get reallocation info for function
 
int deallocId(const char name[]) const
get deallocation id for function by name (deprecated, use other alloc)
 
const PodType * podtype(const std::string &name) const
 
const AllocFunc * getDeallocFuncInfo(const Token *tok) const
get deallocation info for function
 
const Container * detectContainer(const Token *typeStart) const
 
std::list< Function > functionList
 
std::list< Variable > varlist
 
const Function * getDestructor() const
 
const Token * bodyStart
'{' token
 
const Token * bodyEnd
'}' token
 
nonneg int numConstructors
 
bool hasLib(const std::string &lib) const
Is library specified?
 
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
 
SimpleEnableGroup< Certainty > certainty
 
SimpleEnableGroup< Severity > severity
 
bool isEnabled(T flag) const
 
const std::vector< const Variable * > & variableList() const
 
std::vector< const Scope * > functionScopes
Fast access to function scopes.
 
std::vector< const Scope * > classAndStructScopes
Fast access to class and struct 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.
 
const std::string & originalName() const
 
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
 
bool hasKnownIntValue() const
 
MathLib::bigint getKnownIntValue() const
 
const std::string & strAt(int index) const
 
void astOperand1(Token *tok)
 
void function(const Function *f)
Associate this token with given function.
 
std::string expressionString() const
 
bool isUnaryOp(const std::string &s) const
 
const Token * tokAt(int index) const
 
void astOperand2(Token *tok)
 
void link(Token *linkToToken)
Create link to given token.
 
const Token * linkAt(int index) const
 
void type(const ::Type *t)
Associate this token with given type.
 
bool isStandardType() 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)
 
bool isScopeNoReturn(const Token *endScopeToken, bool *unknown=nullptr) const
Check if inner scope ends with a call to a noreturn function.
 
TokenList list
Token list: stores all tokens.
 
bool isC() const
Is the code C.
 
const SymbolDatabase * getSymbolDatabase() const
 
bool isCPP() const
Is the code CPP.
 
std::vector< BaseInfo > derivedFrom
 
enum ValueType::Type type
 
MathLib::bigint typeSize(const Platform &platform, bool p=false) const
 
Information about a member variable.
 
bool isArgument() const
Is variable a function argument.
 
bool isArrayOrPointer() const
Is array or pointer variable.
 
bool isLocal() const
Is variable local.
 
const Type * type() const
Get Type pointer of known type.
 
const Scope * scope() const
Get Scope pointer of enclosing scope.
 
const Scope * typeScope() const
Get Scope pointer of known type.
 
const std::string & name() const
Get name string.
 
bool isPointerArray() const
Is variable an array of pointers.
 
const Token * nameToken() const
Get name token.
 
bool isPrivate() const
Is variable private.
 
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
 
const Token * typeStartToken() const
Get type start token.
 
bool isPointer() const
Is pointer variable.
 
bool isStatic() const
Is variable static.
 
const ValueType * valueType() const
 
Severity
enum class for severity.
 
@ error
Programming error.
 
static constexpr char CWE[]