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

@ -2833,8 +2833,10 @@ int numberOfArguments(const Token* ftok) {
int numberOfArgumentsWithoutAst(const Token* start)
{
int arguments=0;
const Token* const openBracket = start->next();
int arguments = 0;
const Token* openBracket = start->next();
while (Token::simpleMatch(openBracket, ")"))
openBracket = openBracket->next();
if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->next()->str()!=")") {
const Token* argument=openBracket->next();
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
{
if (!Token::Match(ftok, "%name% (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2()))
if (!Token::Match(ftok, "%name% )| (") && (ftok->strAt(-1) != "&" || ftok->previous()->astOperand2()))
return "";
// 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
{
if (functionName.empty())
return false;
const int callargs = numberOfArgumentsWithoutAst(ftok);
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it == functions.cend())

View File

@ -8163,7 +8163,7 @@ void Tokenizer::simplifyDeclspec()
void Tokenizer::simplifyAttribute()
{
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))
tok->isAttributePure(true);
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;
}
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?
if (!Token::Match(parent, "{|("))
@ -470,7 +470,8 @@ static const Token *getCastTypeStartToken(const Token *parent)
return parent->astOperand1();
if (parent->str() != "(")
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();
if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
return parent->astOperand1()->tokAt(2);
@ -603,7 +604,8 @@ static void setTokenValue(Token* tok,
return !Token::simpleMatch(p, ",");
});
// 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);
return;
}
@ -729,7 +731,7 @@ static void setTokenValue(Token* tok,
}
// 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) &&
Token::simpleMatch(parent->astOperand1(), "dynamic_cast"))
return;

View File

@ -2838,14 +2838,21 @@ private:
ASSERT_EQUALS("[test.cpp:7]: (warning) Possible null pointer dereference: p\n", errout.str());
}
void nullpointer_cast() { // #4692
check("char *nasm_skip_spaces(const char *p) {\n"
void nullpointer_cast() {
check("char *nasm_skip_spaces(const char *p) {\n" // #4692
" if (p)\n"
" while (*p && nasm_isspace(*p))\n"
" p++;\n"
" return p;\n"
"}");
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