Skip to content

Commit 52264b9

Browse files
Fix #11401 nullpointer dereference with alignof (#4601)
* 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.
1 parent 8465d90 commit 52264b9

2 files changed

Lines changed: 58 additions & 5 deletions

File tree

‎lib/checknullpointer.cpp‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const
150150
return isPointerDeRef(tok, unknown, mSettings);
151151
}
152152

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

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

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

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

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

353355
else if (Token::simpleMatch(tok, "* 0")) {

‎test/testnullpointer.cpp‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class TestNullPointer : public TestFixture {
153153
TEST_CASE(scanf_with_invalid_va_argument);
154154
TEST_CASE(nullpointer_in_return);
155155
TEST_CASE(nullpointer_in_typeid);
156+
TEST_CASE(nullpointer_in_alignof); // #11401
156157
TEST_CASE(nullpointer_in_for_loop);
157158
TEST_CASE(nullpointerDelete);
158159
TEST_CASE(nullpointerSubFunction);
@@ -3413,7 +3414,48 @@ class TestNullPointer : public TestFixture {
34133414
" return typeid(*c) == typeid(*c);\n"
34143415
"}", true);
34153416
ASSERT_EQUALS("", errout.str());
3417+
}
3418+
3419+
void nullpointer_in_alignof() // #11401
3420+
{
3421+
check("size_t foo() {\n"
3422+
" char* c = 0;\n"
3423+
" return alignof(*c);\n"
3424+
"}", true);
3425+
ASSERT_EQUALS("", errout.str());
3426+
3427+
check("size_t foo() {\n"
3428+
" return alignof(*0);\n"
3429+
"}", true);
3430+
ASSERT_EQUALS("", errout.str());
34163431

3432+
check("void foo(int *p) {\n"
3433+
" f(alignof(*p));\n"
3434+
" if (p) {}\n"
3435+
" return;\n"
3436+
"}");
3437+
ASSERT_EQUALS("", errout.str());
3438+
3439+
check("size_t foo() {\n"
3440+
" char* c = 0;\n"
3441+
" return _Alignof(*c);\n"
3442+
"}", true);
3443+
ASSERT_EQUALS("", errout.str());
3444+
3445+
check("size_t foo() {\n"
3446+
" return _alignof(*0);\n"
3447+
"}", true);
3448+
ASSERT_EQUALS("", errout.str());
3449+
3450+
check("size_t foo() {\n"
3451+
" return __alignof(*0);\n"
3452+
"}", true);
3453+
ASSERT_EQUALS("", errout.str());
3454+
3455+
check("size_t foo() {\n"
3456+
" return __alignof__(*0);\n"
3457+
"}", true);
3458+
ASSERT_EQUALS("", errout.str());
34173459
}
34183460

34193461
void nullpointer_in_for_loop() {
@@ -4350,6 +4392,15 @@ class TestNullPointer : public TestFixture {
43504392
" f(NULL);\n"
43514393
"}\n");
43524394
ASSERT_EQUALS("", errout.str());
4395+
4396+
ctu("size_t f(int* p) {\n"
4397+
" size_t len = alignof(*p);\n"
4398+
" return len;\n"
4399+
"}\n"
4400+
"void g() {\n"
4401+
" f(NULL);\n"
4402+
"}\n");
4403+
ASSERT_EQUALS("", errout.str());
43534404
}
43544405
};
43554406

0 commit comments

Comments
 (0)