Skip to content

Commit

Permalink
Fix #11401 nullpointer dereference with alignof (danmar#4601)
Browse files Browse the repository at this point in the history
* checknullpointer: Don't report dereference with alignof

* Refactor unevaluating operator check in checknullpointer

Unifying these ensures the different checks treat the operators the
same.

* Fix FP with _Alignof and null pointer

Just like alignof, _Alignof does not evaluate its operand.

* CheckNullPointer: Also support compiler specific alignof

This fixes #11401 which is about __alignof__. For good measure, also add
the microsoft extensions __alignof and _alignof.
  • Loading branch information
rikardfalkeborn authored Nov 27, 2022
1 parent 8465d90 commit 52264b9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
12 changes: 7 additions & 5 deletions lib/checknullpointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const
return isPointerDeRef(tok, unknown, mSettings);
}

static bool isUnevaluated(const Token* tok) {
return tok && Token::Match(tok->previous(), "sizeof|decltype (");
static bool isUnevaluatedOperator(const Token* tok)
{
return Token::Match(tok, "sizeof|decltype|typeid|typeof|alignof|_Alignof|_alignof|__alignof|__alignof__ (");
}

bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Settings *settings)
Expand Down Expand Up @@ -190,7 +191,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set
return false;

// Dereferencing pointer..
if (parent->isUnaryOp("*") && !isUnevaluated(parent->astParent())) {
const Token* grandParent = parent->astParent();
if (parent->isUnaryOp("*") && !(grandParent && isUnevaluatedOperator(grandParent->previous()))) {
// declaration of function pointer
if (tok->variable() && tok->variable()->nameToken() == tok)
return false;
Expand Down Expand Up @@ -288,7 +290,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive));

for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "sizeof|decltype|typeid|typeof (")) {
if (isUnevaluatedOperator(tok)) {
tok = tok->next()->link();
continue;
}
Expand Down Expand Up @@ -347,7 +349,7 @@ void CheckNullPointer::nullConstantDereference()
tok = scope->function->token; // Check initialization list

for (; tok != scope->bodyEnd; tok = tok->next()) {
if (Token::Match(tok, "sizeof|decltype|typeid|typeof ("))
if (isUnevaluatedOperator(tok))
tok = tok->next()->link();

else if (Token::simpleMatch(tok, "* 0")) {
Expand Down
51 changes: 51 additions & 0 deletions test/testnullpointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class TestNullPointer : public TestFixture {
TEST_CASE(scanf_with_invalid_va_argument);
TEST_CASE(nullpointer_in_return);
TEST_CASE(nullpointer_in_typeid);
TEST_CASE(nullpointer_in_alignof); // #11401
TEST_CASE(nullpointer_in_for_loop);
TEST_CASE(nullpointerDelete);
TEST_CASE(nullpointerSubFunction);
Expand Down Expand Up @@ -3413,7 +3414,48 @@ class TestNullPointer : public TestFixture {
" return typeid(*c) == typeid(*c);\n"
"}", true);
ASSERT_EQUALS("", errout.str());
}

void nullpointer_in_alignof() // #11401
{
check("size_t foo() {\n"
" char* c = 0;\n"
" return alignof(*c);\n"
"}", true);
ASSERT_EQUALS("", errout.str());

check("size_t foo() {\n"
" return alignof(*0);\n"
"}", true);
ASSERT_EQUALS("", errout.str());

check("void foo(int *p) {\n"
" f(alignof(*p));\n"
" if (p) {}\n"
" return;\n"
"}");
ASSERT_EQUALS("", errout.str());

check("size_t foo() {\n"
" char* c = 0;\n"
" return _Alignof(*c);\n"
"}", true);
ASSERT_EQUALS("", errout.str());

check("size_t foo() {\n"
" return _alignof(*0);\n"
"}", true);
ASSERT_EQUALS("", errout.str());

check("size_t foo() {\n"
" return __alignof(*0);\n"
"}", true);
ASSERT_EQUALS("", errout.str());

check("size_t foo() {\n"
" return __alignof__(*0);\n"
"}", true);
ASSERT_EQUALS("", errout.str());
}

void nullpointer_in_for_loop() {
Expand Down Expand Up @@ -4350,6 +4392,15 @@ class TestNullPointer : public TestFixture {
" f(NULL);\n"
"}\n");
ASSERT_EQUALS("", errout.str());

ctu("size_t f(int* p) {\n"
" size_t len = alignof(*p);\n"
" return len;\n"
"}\n"
"void g() {\n"
" f(NULL);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
};

Expand Down

0 comments on commit 52264b9

Please sign in to comment.