70 const std::vector<const Token *> args =
getArguments(&tok);
72 for (
int argnr = 1; argnr <= args.size(); ++argnr) {
73 const Token *param = args[argnr - 1];
85 if (formatStringArgNr < 0 || formatStringArgNr >= args.size())
89 if (
Token::Match(&tok,
"snprintf|vsnprintf|fnprintf|vfnprintf") && args.size() > 1 && !(args[1] && args[1]->hasKnownIntValue() && args[1]->getKnownIntValue() == 0))
90 var.push_back(args[0]);
94 const std::string &formatString = args[formatStringArgNr]->strValue();
95 int argnr = formatStringArgNr + 1;
99 for (std::string::const_iterator i = formatString.cbegin(); i != formatString.cend(); ++i) {
102 }
else if (percent) {
105 bool _continue =
false;
106 while (!std::isalpha((
unsigned char)*i)) {
114 if (i == formatString.end())
120 if (argnr < args.size() && (*i ==
'n' || *i ==
's' || scan))
121 var.push_back(args[argnr]);
131 const std::set<std::string> stl_stream = {
132 "fstream",
"ifstream",
"iostream",
"istream",
133 "istringstream",
"ofstream",
"ostream",
"ostringstream",
134 "stringstream",
"wistringstream",
"wostringstream",
"wstringstream"
159 while (ftok && ftok->
str() !=
"(") {
160 if (ftok->
str() ==
")")
165 std::list<const Token *> varlist;
167 if (std::find(varlist.cbegin(), varlist.cend(), tok) != varlist.cend()) {
173 if (tok->
str() ==
"(" && !tok->
scope()->isExecutable())
182 const bool firstOperand = parent->
astOperand1() == tok;
198 if (firstOperand && parent->
str() ==
"[" && !addressOf)
202 const Token *parent2 = parent;
205 if (parent2 != parent && parent2 && parent2->
isUnaryOp(
"&"))
209 if (firstOperand && parent->
originalName() ==
"->" && !addressOf)
234 const Token* tok2 = parent;
235 for (; tok2; tok2 = tok2->
previous()) {
241 if (tok2 && tok2->
varId() != 0) {
250 if (
Token::Match(parent,
"+|==|!=") || (parent->
str() ==
"=" && !firstOperand)) {
277 return (var->isPointer() || var->isSmartPointer());
288 tok = tok->next()->link();
296 (tok->str() ==
"." &&
isNullablePointer(tok->astOperand2()) && tok->astOperand2()->getValue(0)))
308 bool unknown =
false;
326 const std::set<std::string> stl_istream = {
327 "fstream",
"ifstream",
"iostream",
"istream",
328 "istringstream",
"stringstream",
"wistringstream",
"wstringstream"
335 logChecker(
"CheckNullPointer::nullConstantDereference");
367 std::list<const Token *> var;
371 for (
const Token *vartok : var) {
372 if (vartok->hasKnownIntValue() && vartok->getKnownIntValue() == 0)
376 }
else if (
Token::Match(tok,
"std :: string|wstring ( 0|NULL|nullptr )"))
380 const std::vector<const Token *> &args =
getArguments(tok);
381 for (
int argnr = 0; argnr < args.size(); ++argnr) {
382 const Token *argtok = args[argnr];
385 if (argtok->
values().front().intvalue != 0)
394 for (; tok2; tok2 = tok2->
previous()) {
402 if (tok2 && tok2->
varId() != 0) {
410 const Token *tokNull =
nullptr;
411 if (
Token::Match(tok,
"0|NULL|nullptr ==|!=|>|>=|<|<= %var%")) {
416 }
else if (
Token::Match(tok,
"%var% ==|!=|>|>=|<|<= 0|NULL|nullptr") ||
417 Token::Match(tok,
"%var% =|+ 0|NULL|nullptr )|]|,|;|+")) {
419 tokNull = tok->
tokAt(2);
430 const std::string errmsgdefarg(
"$symbol:" + varname +
"\nPossible null pointer dereference if the default parameter value is used: $symbol");
454 std::string errmsg = std::string(value->
isKnown() ?
"Null" :
"Possible null") +
" pointer dereference";
455 if (!varname.empty())
456 errmsg =
"$symbol:" + varname +
'\n' + errmsg +
": $symbol";
474 const Token *pointerOperand;
475 const Token *numericOperand;
476 if (tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->pointer != 0) {
479 }
else if (tok->astOperand2() && tok->astOperand2()->valueType() && tok->astOperand2()->valueType()->pointer != 0) {
487 if (numValue && numValue->
intvalue == 0)
506 if (tok && tok->
str()[0] ==
'-')
507 return "subtraction";
508 if (tok && tok->
str()[0] ==
'+')
518 if (tok && tok->
str()[0] ==
'-') {
519 errmsg =
"Overflow in pointer arithmetic, NULL pointer is subtracted.";
521 errmsg =
"Pointer " +
arithmetic +
" with NULL pointer.";
526 "nullPointerArithmetic",
537 if (tok && tok->
str()[0] ==
'-') {
545 "nullPointerArithmeticRedundantCheck",
555 bool unknown =
false;
562 inline namespace CheckNullPointer_internal
571 std::list<CTU::FileInfo::UnsafeUsage> unsafeUsage;
574 std::string
toString()
const override
584 if (unsafeUsage.empty())
587 auto *fileInfo =
new MyFileInfo;
588 fileInfo->unsafeUsage = unsafeUsage;
595 if (unsafeUsage.empty())
598 auto *fileInfo =
new MyFileInfo;
599 fileInfo->unsafeUsage = unsafeUsage;
607 bool foundErrors =
false;
612 logChecker(
"CheckNullPointer::analyseWholeProgram");
614 const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> callsMap = ctu->
getCallsMap();
617 const MyFileInfo *fi =
dynamic_cast<const MyFileInfo*
>(fi1);
625 const std::list<ErrorMessage::FileLocation> &locationList =
629 "Dereferencing argument ARG that is null",
632 if (locationList.empty())
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
bool astIsPointer(const Token *tok)
bool astIsSmartPointer(const Token *tok)
const Token * astParentSkipParens(const Token *tok)
bool astIsRHS(const Token *tok)
bool isUnevaluated(const Token *tok)
static bool isNullablePointer(const Token *tok)
static const CWE CWE_NULL_POINTER_DEREFERENCE(476U)
static bool checkNullpointerFunctionCallPlausibility(const Function *func, unsigned int arg)
static const CWE CWE_INCORRECT_CALCULATION(682U)
static std::string arithmeticTypeString(const Token *tok)
static bool isUnsafeUsage(const Settings &settings, const Token *vartok, MathLib::bigint *value)
static std::list< ErrorMessage::FileLocation > getErrorPath(InvalidValueType invalidValue, const UnsafeUsage &unsafeUsage, const std::map< std::string, std::list< const CallBase * >> &callsMap, const char info[], const FunctionCall **const functionCallPtr, bool warning)
std::map< std::string, std::list< const CallBase * > > getCallsMap() const
check for null pointer dereferencing
static void parseFunctionCall(const Token &tok, std::list< const Token * > &var, const Library &library)
parse a function call and extract information about variable usage
void nullPointerByDeRefAndChec()
Does one part of the check for nullPointer().
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override
void nullPointer()
possible null pointer dereference
void pointerArithmeticError(const Token *tok, const ValueFlow::Value *value, bool inconclusive)
Check::FileInfo * getFileInfo(const Tokenizer &tokenizer, const Settings &settings) const override
Parse current TU and extract file info.
void redundantConditionWarning(const Token *tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive)
void arithmetic()
undefined null pointer arithmetic
void nullConstantDereference()
dereferencing null constant (after Tokenizer::simplifyKnownVariables)
void nullPointerError(const Token *tok)
bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list< Check::FileInfo * > &fileInfo, const Settings &settings, ErrorLogger &errorLogger) override
Analyse all file infos for all TU.
bool isPointerDeRef(const Token *tok, bool &unknown) const
Is there a pointer dereference? Everything that should result in a nullpointer dereference error mess...
Base class used for whole-program analysis.
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
This is an interface, which the class responsible of error logging should implement.
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
Wrapper for error messages, provided by reportErr()
const Variable * getArgumentVar(nonneg int num) const
nonneg int argCount() const
const Token * token
function name token in implementation
bool isConstructor() const
Library definitions handling.
bool isnullargbad(const Token *ftok, int argnr) const
bool formatstr_function(const Token *ftok) const
int formatstr_argno(const Token *ftok) const
bool formatstr_scan(const Token *ftok) const
Function * function
function info for this function
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
This is just a container for general settings so that we don't need to pass individual values to func...
bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const
Returns true if given value can be shown.
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.
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.
const std::string & originalName() const
bool hasKnownIntValue() const
const ValueType * valueType() const
const std::string & strAt(int index) const
void astOperand1(Token *tok)
void function(const Function *f)
Associate this token with given function.
bool isUnaryOp(const std::string &s) const
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.
void variable(const Variable *v)
Associate this token with given variable.
const std::list< ValueFlow::Value > & values() 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)
The main purpose is to tokenize the source code.
const Token * tokens() const
const SymbolDatabase * getSymbolDatabase() const
bool defaultArg
Is this value passed as default parameter to the function?
const Token * condition
Condition that this value depends on.
long long intvalue
int value (or sometimes bool value?)
bool isInconclusive() const
Information about a member variable.
bool isArrayOrPointer() const
Is array or pointer variable.
bool isStlType() const
Checks if the variable is an STL type ('std::') E.g.
bool isArray() const
Is variable an array.
const Token * typeStartToken() const
Get type start token.
bool isPointer() const
Is pointer variable.
bool isStlStringType() const
Checks if the variable is an STL type ('std::') E.g.
std::string toString(Color c)
static const std::string emptyString
std::list< ErrorPathItem > ErrorPath
@ error
Programming error.
CPPCHECKLIB std::list< FileInfo::UnsafeUsage > getUnsafeUsage(const Tokenizer &tokenizer, const Settings &settings, bool(*isUnsafeUsage)(const Settings &settings, const Token *argtok, MathLib::bigint *value))
CPPCHECKLIB std::string toString(const std::list< FileInfo::UnsafeUsage > &unsafeUsage)
CPPCHECKLIB std::list< FileInfo::UnsafeUsage > loadUnsafeUsageListFromXml(const tinyxml2::XMLElement *xmlElement)
std::string eitherTheConditionIsRedundant(const Token *condition)
std::string myArgumentName