Skip to content

Commit 42f418d

Browse files
committed
- Improved nullpointer check: Fixed cppcheck-opensource#1171
- Improved accuracy of function analysis in symboldatabase - Code cleanups
1 parent 15669d2 commit 42f418d

5 files changed

Lines changed: 130 additions & 155 deletions

File tree

lib/checknullpointer.cpp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -115,28 +115,31 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
115115
functionNames2_nullptr.insert("modf");
116116
}
117117

118+
if (Token::Match(&tok, "%var% ( )") || !tok.tokAt(2))
119+
return;
120+
121+
const Token* firstParam = tok.tokAt(2);
122+
const Token* secondParam = firstParam->nextArgument();
123+
118124
// 1st parameter..
119-
if ((Token::Match(&tok, "%var% ( %var% ,|)") && tok.tokAt(2)->varId() > 0) ||
120-
(value == 0 && Token::Match(&tok, "%var% ( 0 ,|)"))) {
125+
if ((Token::Match(firstParam, "%var% ,|)") && firstParam->varId() > 0) ||
126+
(value == 0 && Token::Match(firstParam, "0 ,|)"))) {
121127
if (functionNames1_all.find(tok.str()) != functionNames1_all.end())
122-
var.push_back(tok.tokAt(2));
128+
var.push_back(firstParam);
123129
else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
124-
var.push_back(tok.tokAt(2));
125-
else if (value != 0 && Token::simpleMatch(&tok, "fflush"))
126-
var.push_back(tok.tokAt(2));
127-
else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && tok.strAt(4) != "0") // Only if length is not zero
128-
var.push_back(tok.tokAt(2));
130+
var.push_back(firstParam);
131+
else if (value != 0 && tok.str() == "fflush")
132+
var.push_back(firstParam);
133+
else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero
134+
var.push_back(firstParam);
129135
}
130136

131137
// 2nd parameter..
132-
if (Token::Match(&tok, "%var% ( !!)")) {
133-
const Token* secondParameter = tok.tokAt(2)->nextArgument();
134-
if (secondParameter && ((value == 0 && secondParameter->str() == "0") || (Token::Match(secondParameter, "%var%") && secondParameter->varId() > 0))) {
135-
if (functionNames2_all.find(tok.str()) != functionNames2_all.end())
136-
var.push_back(secondParameter);
137-
else if (value == 0 && functionNames2_nullptr.find(tok.str()) != functionNames2_nullptr.end())
138-
var.push_back(secondParameter);
139-
}
138+
if (secondParam && ((value == 0 && secondParam->str() == "0") || (Token::Match(secondParam, "%var%") && secondParam->varId() > 0))) {
139+
if (functionNames2_all.find(tok.str()) != functionNames2_all.end())
140+
var.push_back(secondParam);
141+
else if (value == 0 && functionNames2_nullptr.find(tok.str()) != functionNames2_nullptr.end())
142+
var.push_back(secondParam);
140143
}
141144

142145
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf")) {
@@ -145,25 +148,22 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
145148
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf");
146149

147150
if (Token::Match(&tok, "printf|scanf ( %str%")) {
148-
formatString = tok.strAt(2);
149-
if (tok.strAt(3) == ",")
150-
argListTok = tok.tokAt(4);
151-
else
152-
argListTok = 0;
153-
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %any%")) {
154-
const Token* formatStringTok = tok.tokAt(2)->nextArgument(); // Find second parameter (format string)
155-
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
151+
formatString = firstParam->strValue();
152+
argListTok = secondParam;
153+
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf")) {
154+
const Token* formatStringTok = secondParam; // Find second parameter (format string)
155+
if (formatStringTok && formatStringTok->str()[0] == '"') {
156156
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
157-
formatString = formatStringTok->str();
157+
formatString = formatStringTok->strValue();
158158
}
159-
} else if (Token::Match(&tok, "snprintf|fnprintf ( %any%")) {
160-
const Token* formatStringTok = tok.tokAt(2);
161-
for (int i = 0; i < 2 && formatStringTok; i++) {
159+
} else if (Token::Match(&tok, "snprintf|fnprintf")) {
160+
const Token* formatStringTok = secondParam;
161+
for (int i = 0; i < 1 && formatStringTok; i++) {
162162
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
163163
}
164-
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
164+
if (formatStringTok && formatStringTok->str()[0] == '"') {
165165
argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
166-
formatString = formatStringTok->str();
166+
formatString = formatStringTok->strValue();
167167
}
168168
}
169169

@@ -191,7 +191,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
191191
continue;
192192

193193
if ((*i == 'n' || *i == 's' || scan) && (!scan || value == 0)) {
194-
if ((value == 0 && argListTok->str() == "0") || (Token::Match(argListTok, "%var%") && argListTok->varId() > 0)) {
194+
if ((value == 0 && argListTok->str() == "0") || (argListTok->varId() > 0)) {
195195
var.push_back(argListTok);
196196
}
197197
}
@@ -1026,7 +1026,13 @@ void CheckNullPointer::nullConstantDereference()
10261026
else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]")))
10271027
nullPointerError(tok);
10281028

1029-
else if (Token::Match(tok->previous(), "[={};] %var% (")) {
1029+
else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) {
1030+
if (Token::Match(tok->tokAt(2), "0 )")) {
1031+
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
1032+
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::"))
1033+
nullPointerError(tok);
1034+
}
1035+
10301036
std::list<const Token *> var;
10311037
parseFunctionCall(*tok, var, 0);
10321038

@@ -1038,11 +1044,6 @@ void CheckNullPointer::nullConstantDereference()
10381044
}
10391045
} else if (Token::simpleMatch(tok, "std :: string ( 0 )"))
10401046
nullPointerError(tok);
1041-
else if (Token::Match(tok, "%var% ( 0 )")) {
1042-
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId());
1043-
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "const| std :: string !!::"))
1044-
nullPointerError(tok);
1045-
}
10461047

10471048
unsigned int ovarid = 0;
10481049
if (Token::Match(tok, "0 ==|!= %var%"))

0 commit comments

Comments
 (0)