CTU: Reuse CheckNullPointer::isPointerDeRef in the nullpointer isUnsafeUsage

This commit is contained in:
Daniel Marjamäki 2018-12-29 09:26:57 +01:00
parent 03ed4afc70
commit d18f5d8709
6 changed files with 37 additions and 29 deletions

View File

@ -672,7 +672,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
const std::map<unsigned int, VarInfo::AllocInfo>::const_iterator var = varInfo->alloctype.find(tok->varId());
if (var != varInfo->alloctype.end()) {
bool unknown = false;
if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok, unknown) && !unknown) {
if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok, unknown, mSettings) && !unknown) {
deallocUseError(tok, tok->str());
} else if (Token::simpleMatch(tok->tokAt(-2), "= &")) {
varInfo->erase(tok->varId());

View File

@ -161,15 +161,37 @@ namespace {
* @param unknown it is not known if there is a pointer dereference (could be reported as a debug message)
* @return true => there is a dereference
*/
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const
{
return isPointerDeRef(tok, unknown, mSettings);
}
bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Settings *settings)
{
unknown = false;
// Is pointer used as function parameter?
if (Token::Match(tok->previous(), "[(,] %name% [,)]") && settings) {
const Token *ftok = tok->previous();
while (ftok && ftok->str() != "(") {
if (ftok->str() == ")")
ftok = ftok->link();
ftok = ftok->previous();
}
if (ftok && ftok->previous()) {
std::list<const Token *> varlist;
parseFunctionCall(*ftok->previous(), varlist, &settings->library);
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
return true;
}
}
}
const Token* parent = tok->astParent();
if (!parent)
return false;
if (parent->str() == "." && parent->astOperand2() == tok)
return isPointerDeRef(parent, unknown);
return isPointerDeRef(parent, unknown, settings);
const bool firstOperand = parent->astOperand1() == tok;
while (parent->str() == "(" && (parent->astOperand2() == nullptr && parent->strAt(1) != ")")) { // Skip over casts
parent = parent->astParent();
@ -339,24 +361,6 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
if (!printInconclusive && value->isInconclusive())
continue;
// Is pointer used as function parameter?
if (Token::Match(tok->previous(), "[(,] %name% [,)]")) {
const Token *ftok = tok->previous();
while (ftok && ftok->str() != "(") {
if (ftok->str() == ")")
ftok = ftok->link();
ftok = ftok->previous();
}
if (!ftok || !ftok->previous())
continue;
std::list<const Token *> varlist;
parseFunctionCall(*ftok->previous(), varlist, &mSettings->library);
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
nullPointerError(tok, tok->str(), value, value->isInconclusive());
}
continue;
}
// Pointer dereference.
bool unknown = false;
if (!isPointerDeRef(tok,unknown)) {
@ -598,13 +602,15 @@ std::string CheckNullPointer::MyFileInfo::toString() const
static bool isUnsafeUsage(const Check *check, const Token *vartok)
{
(void)check;
return Token::Match(vartok->astParent(), "*|[");
const CheckNullPointer *checkNullPointer = dynamic_cast<const CheckNullPointer *>(check);
bool unknown = false;
return checkNullPointer && checkNullPointer->isPointerDeRef(vartok, unknown);
}
Check::FileInfo *CheckNullPointer::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
{
const std::list<CTU::FileInfo::UnsafeUsage> &unsafeUsage = CTU::getUnsafeUsage(tokenizer, settings, nullptr, ::isUnsafeUsage);
CheckNullPointer check(tokenizer, settings, nullptr);
const std::list<CTU::FileInfo::UnsafeUsage> &unsafeUsage = CTU::getUnsafeUsage(tokenizer, settings, &check, ::isUnsafeUsage);
if (unsafeUsage.empty())
return nullptr;

View File

@ -86,7 +86,9 @@ public:
* @param unknown it is not known if there is a pointer dereference (could be reported as a debug message)
* @return true => there is a dereference
*/
static bool isPointerDeRef(const Token *tok, bool &unknown);
bool isPointerDeRef(const Token *tok, bool &unknown) const;
static bool isPointerDeRef(const Token *tok, bool &unknown, const Settings *settings);
/** @brief possible null pointer dereference */
void nullPointer();

View File

@ -962,7 +962,7 @@ void CheckStl::pushback()
// Using invalid pointer..
if (invalidPointer && tok2->varId() == pointerId) {
bool unknown = false;
if (CheckNullPointer::isPointerDeRef(tok2, unknown))
if (CheckNullPointer::isPointerDeRef(tok2, unknown, mSettings))
invalidPointerError(tok2, function->str(), tok2->str());
break;
}

View File

@ -985,7 +985,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc al
}
bool unknown = false;
if (pointer && alloc == NO_ALLOC && CheckNullPointer::isPointerDeRef(vartok, unknown)) {
if (pointer && alloc == NO_ALLOC && CheckNullPointer::isPointerDeRef(vartok, unknown, mSettings)) {
// function parameter?
bool functionParameter = false;
if (Token::Match(vartok->tokAt(-2), "%name% (") || vartok->previous()->str() == ",")

View File

@ -2073,12 +2073,12 @@ private:
"}", true);
ASSERT_EQUALS("[test.cpp:9]: (error) Null pointer dereference: p\n"
"[test.cpp:10]: (error) Null pointer dereference: p\n"
"[test.cpp:11]: (error) Null pointer dereference: p\n"
"[test.cpp:12]: (warning, inconclusive) Possible null pointer dereference: p\n"
"[test.cpp:3]: (error) Null pointer dereference\n"
"[test.cpp:5]: (error) Null pointer dereference\n"
"[test.cpp:7]: (error) Null pointer dereference\n"
"[test.cpp:8]: (error) Null pointer dereference\n"
/*"[test.cpp:11]: (error) Possible null pointer dereference: p\n"
"[test.cpp:12]: (error) Possible null pointer dereference: p\n"*/
, errout.str());
check("void f(std::string s1) {\n"