Skip to content

Commit 3076f9d

Browse files
Fix #11449 Function call not recognized with extra parentheses / FP nullPointer (danmar#4703)
1 parent dfd3e8a commit 3076f9d

File tree

5 files changed

+23
-10
lines changed

5 files changed

+23
-10
lines changed

lib/astutils.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,8 +2833,10 @@ int numberOfArguments(const Token* ftok) {
28332833

28342834
int numberOfArgumentsWithoutAst(const Token* start)
28352835
{
2836-
int arguments=0;
2837-
const Token* const openBracket = start->next();
2836+
int arguments = 0;
2837+
const Token* openBracket = start->next();
2838+
while (Token::simpleMatch(openBracket, ")"))
2839+
openBracket = openBracket->next();
28382840
if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->next()->str()!=")") {
28392841
const Token* argument=openBracket->next();
28402842
while (argument) {

lib/library.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ std::string Library::getFunctionName(const Token *ftok, bool *error) const
982982

983983
std::string Library::getFunctionName(const Token *ftok) const
984984
{
985-
if (!Token::Match(ftok, "%name% (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2()))
985+
if (!Token::Match(ftok, "%name% )| (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2()))
986986
return "";
987987

988988
// Lookup function name using AST..
@@ -1228,6 +1228,8 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
12281228

12291229
bool Library::matchArguments(const Token *ftok, const std::string &functionName) const
12301230
{
1231+
if (functionName.empty())
1232+
return false;
12311233
const int callargs = numberOfArgumentsWithoutAst(ftok);
12321234
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
12331235
if (it == functions.cend())

lib/tokenize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8163,7 +8163,7 @@ void Tokenizer::simplifyDeclspec()
81638163
void Tokenizer::simplifyAttribute()
81648164
{
81658165
for (Token *tok = list.front(); tok; tok = tok->next()) {
8166-
if (Token::Match(tok, "%type% (") && !mSettings->library.isNotLibraryFunction(tok)) {
8166+
if (!tok->isKeyword() && Token::Match(tok, "%type% (") && !mSettings->library.isNotLibraryFunction(tok)) {
81678167
if (mSettings->library.isFunctionConst(tok->str(), true))
81688168
tok->isAttributePure(true);
81698169
if (mSettings->library.isFunctionConst(tok->str(), false))

lib/valueflow.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ void combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Val
459459
result->path = value1.path;
460460
}
461461

462-
static const Token *getCastTypeStartToken(const Token *parent)
462+
static const Token *getCastTypeStartToken(const Token *parent, const Settings* settings)
463463
{
464464
// TODO: This might be a generic utility function?
465465
if (!Token::Match(parent, "{|("))
@@ -470,7 +470,8 @@ static const Token *getCastTypeStartToken(const Token *parent)
470470
return parent->astOperand1();
471471
if (parent->str() != "(")
472472
return nullptr;
473-
if (!parent->astOperand2() && Token::Match(parent,"( %name%"))
473+
if (!parent->astOperand2() && Token::Match(parent, "( %name%") &&
474+
(parent->next()->isStandardType() || settings->library.isNotLibraryFunction(parent->next())))
474475
return parent->next();
475476
if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
476477
return parent->astOperand1()->tokAt(2);
@@ -603,7 +604,8 @@ static void setTokenValue(Token* tok,
603604
return !Token::simpleMatch(p, ",");
604605
});
605606
// Ensure that the comma isn't a function call
606-
if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{"))) {
607+
if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{") &&
608+
(!Token::Match(callParent, "( %name%") || settings->library.isNotLibraryFunction(callParent->next())))) {
607609
setTokenValue(parent, std::move(value), settings);
608610
return;
609611
}
@@ -729,7 +731,7 @@ static void setTokenValue(Token* tok,
729731
}
730732

731733
// cast..
732-
if (const Token *castType = getCastTypeStartToken(parent)) {
734+
if (const Token *castType = getCastTypeStartToken(parent, settings)) {
733735
if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) &&
734736
Token::simpleMatch(parent->astOperand1(), "dynamic_cast"))
735737
return;

test/testnullpointer.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2838,14 +2838,21 @@ class TestNullPointer : public TestFixture {
28382838
ASSERT_EQUALS("[test.cpp:7]: (warning) Possible null pointer dereference: p\n", errout.str());
28392839
}
28402840

2841-
void nullpointer_cast() { // #4692
2842-
check("char *nasm_skip_spaces(const char *p) {\n"
2841+
void nullpointer_cast() {
2842+
check("char *nasm_skip_spaces(const char *p) {\n" // #4692
28432843
" if (p)\n"
28442844
" while (*p && nasm_isspace(*p))\n"
28452845
" p++;\n"
28462846
" return p;\n"
28472847
"}");
28482848
ASSERT_EQUALS("", errout.str());
2849+
2850+
check("void f(char* origin) {\n" // #11449
2851+
" char* cp = (strchr)(origin, '\\0');\n"
2852+
" if (cp[-1] != '/')\n"
2853+
" *cp++ = '/';\n"
2854+
"}\n");
2855+
ASSERT_EQUALS("", errout.str());
28492856
}
28502857

28512858
void nullpointer_castToVoid() { // #3771

0 commit comments

Comments
 (0)