Fix #11449 Function call not recognized with extra parentheses / FP nullPointer (#4703)

This commit is contained in:
chrchr-github 2023-01-18 20:38:37 +01:00 committed by GitHub
parent dfd3e8ac55
commit 3076f9def1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 10 deletions

View File

@ -2834,7 +2834,9 @@ int numberOfArguments(const Token* ftok) {
int numberOfArgumentsWithoutAst(const Token* start) int numberOfArgumentsWithoutAst(const Token* start)
{ {
int arguments = 0; int arguments = 0;
const Token* const openBracket = start->next(); const Token* openBracket = start->next();
while (Token::simpleMatch(openBracket, ")"))
openBracket = openBracket->next();
if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->next()->str()!=")") { if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->next()->str()!=")") {
const Token* argument=openBracket->next(); const Token* argument=openBracket->next();
while (argument) { while (argument) {

View File

@ -982,7 +982,7 @@ std::string Library::getFunctionName(const Token *ftok, bool *error) const
std::string Library::getFunctionName(const Token *ftok) const std::string Library::getFunctionName(const Token *ftok) const
{ {
if (!Token::Match(ftok, "%name% (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2())) if (!Token::Match(ftok, "%name% )| (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2()))
return ""; return "";
// Lookup function name using AST.. // Lookup function name using AST..
@ -1228,6 +1228,8 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
bool Library::matchArguments(const Token *ftok, const std::string &functionName) const bool Library::matchArguments(const Token *ftok, const std::string &functionName) const
{ {
if (functionName.empty())
return false;
const int callargs = numberOfArgumentsWithoutAst(ftok); const int callargs = numberOfArgumentsWithoutAst(ftok);
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName); const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it == functions.cend()) if (it == functions.cend())

View File

@ -8163,7 +8163,7 @@ void Tokenizer::simplifyDeclspec()
void Tokenizer::simplifyAttribute() void Tokenizer::simplifyAttribute()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "%type% (") && !mSettings->library.isNotLibraryFunction(tok)) { if (!tok->isKeyword() && Token::Match(tok, "%type% (") && !mSettings->library.isNotLibraryFunction(tok)) {
if (mSettings->library.isFunctionConst(tok->str(), true)) if (mSettings->library.isFunctionConst(tok->str(), true))
tok->isAttributePure(true); tok->isAttributePure(true);
if (mSettings->library.isFunctionConst(tok->str(), false)) if (mSettings->library.isFunctionConst(tok->str(), false))

View File

@ -459,7 +459,7 @@ void combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Val
result->path = value1.path; result->path = value1.path;
} }
static const Token *getCastTypeStartToken(const Token *parent) static const Token *getCastTypeStartToken(const Token *parent, const Settings* settings)
{ {
// TODO: This might be a generic utility function? // TODO: This might be a generic utility function?
if (!Token::Match(parent, "{|(")) if (!Token::Match(parent, "{|("))
@ -470,7 +470,8 @@ static const Token *getCastTypeStartToken(const Token *parent)
return parent->astOperand1(); return parent->astOperand1();
if (parent->str() != "(") if (parent->str() != "(")
return nullptr; return nullptr;
if (!parent->astOperand2() && Token::Match(parent,"( %name%")) if (!parent->astOperand2() && Token::Match(parent, "( %name%") &&
(parent->next()->isStandardType() || settings->library.isNotLibraryFunction(parent->next())))
return parent->next(); return parent->next();
if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <")) if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
return parent->astOperand1()->tokAt(2); return parent->astOperand1()->tokAt(2);
@ -603,7 +604,8 @@ static void setTokenValue(Token* tok,
return !Token::simpleMatch(p, ","); return !Token::simpleMatch(p, ",");
}); });
// Ensure that the comma isn't a function call // Ensure that the comma isn't a function call
if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{"))) { if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{") &&
(!Token::Match(callParent, "( %name%") || settings->library.isNotLibraryFunction(callParent->next())))) {
setTokenValue(parent, std::move(value), settings); setTokenValue(parent, std::move(value), settings);
return; return;
} }
@ -729,7 +731,7 @@ static void setTokenValue(Token* tok,
} }
// cast.. // cast..
if (const Token *castType = getCastTypeStartToken(parent)) { if (const Token *castType = getCastTypeStartToken(parent, settings)) {
if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) && if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) &&
Token::simpleMatch(parent->astOperand1(), "dynamic_cast")) Token::simpleMatch(parent->astOperand1(), "dynamic_cast"))
return; return;

View File

@ -2838,14 +2838,21 @@ private:
ASSERT_EQUALS("[test.cpp:7]: (warning) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (warning) Possible null pointer dereference: p\n", errout.str());
} }
void nullpointer_cast() { // #4692 void nullpointer_cast() {
check("char *nasm_skip_spaces(const char *p) {\n" check("char *nasm_skip_spaces(const char *p) {\n" // #4692
" if (p)\n" " if (p)\n"
" while (*p && nasm_isspace(*p))\n" " while (*p && nasm_isspace(*p))\n"
" p++;\n" " p++;\n"
" return p;\n" " return p;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f(char* origin) {\n" // #11449
" char* cp = (strchr)(origin, '\\0');\n"
" if (cp[-1] != '/')\n"
" *cp++ = '/';\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void nullpointer_castToVoid() { // #3771 void nullpointer_castToVoid() { // #3771