You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: test/testnullpointer.cpp
+75Lines changed: 75 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -143,6 +143,8 @@ class TestNullPointer : public TestFixture {
143
143
TEST_CASE(nullpointer103);
144
144
TEST_CASE(nullpointer104); // #13881
145
145
TEST_CASE(nullpointer105); // #13861
146
+
TEST_CASE(nullpointer106); // #13682
147
+
TEST_CASE(nullpointer107); // #13682 (no false positive past unrelated conditions)
146
148
TEST_CASE(nullpointer_addressOf); // address of
147
149
TEST_CASE(nullpointerSwitch); // #2626
148
150
TEST_CASE(nullpointer_cast); // #4692
@@ -2966,6 +2968,79 @@ class TestNullPointer : public TestFixture {
2966
2968
ASSERT_EQUALS("", errout_str());
2967
2969
}
2968
2970
2971
+
voidnullpointer106() // #13682
2972
+
{
2973
+
// An unrelated condition between the null check and the dereference must not stop the analysis
2974
+
check("struct S {\n"
2975
+
" bool b;\n"
2976
+
" bool f() const;\n"
2977
+
"};\n"
2978
+
"void f(const S* p, const S* o) {\n"
2979
+
" const S* p1 = p;\n"
2980
+
" if (p1 && p1->f())\n"
2981
+
" return;\n"
2982
+
" if (p == o)\n"
2983
+
" return;\n"
2984
+
" if (p1->b) {}\n"
2985
+
"}\n");
2986
+
ASSERT_EQUALS(
2987
+
"[test.cpp:7:9] -> [test.cpp:11:9]: (warning) Either the condition 'p1' is redundant or there is possible null pointer dereference: p1. [nullPointerRedundantCheck]\n",
2988
+
errout_str());
2989
+
}
2990
+
2991
+
voidnullpointer107() // #13682 - don't flow past a condition that doesn't reference the pointer
2992
+
{
2993
+
// The pointer's null-ness is cached in a boolean; the guard 'if (!ok)' makes the deref safe but
2994
+
// cppcheck cannot follow that correlation during forward analysis -> must not warn (no false positive)
2995
+
check("struct S { void g(); bool f() const; };\n"
2996
+
"void f(S* p) {\n"
2997
+
" bool ok = (p != nullptr);\n"
2998
+
" if (p && p->f())\n"
2999
+
" return;\n"
3000
+
" if (!ok)\n"
3001
+
" return;\n"
3002
+
" p->g();\n"
3003
+
"}\n");
3004
+
ASSERT_EQUALS("", errout_str());
3005
+
3006
+
// A guard on an unrelated boolean (that the caller may use to imply validity) is not something
3007
+
// cppcheck can follow -> stay conservative and do not warn
3008
+
check("struct S { void g(); bool f() const; };\n"
3009
+
"void f(S* p, bool valid) {\n"
3010
+
" S* p1 = p;\n"
3011
+
" if (p1 && p1->f())\n"
3012
+
" return;\n"
3013
+
" if (!valid)\n"
3014
+
" return;\n"
3015
+
" p1->g();\n"
3016
+
"}\n");
3017
+
ASSERT_EQUALS("", errout_str());
3018
+
3019
+
// A guard on a different pointer must not be assumed to constrain this one
3020
+
check("struct S { void g(); bool f() const; };\n"
3021
+
"void f(S* p, S* q) {\n"
3022
+
" S* p1 = p;\n"
3023
+
" if (p1 && p1->f())\n"
3024
+
" return;\n"
3025
+
" if (!q)\n"
3026
+
" return;\n"
3027
+
" p1->g();\n"
3028
+
"}\n");
3029
+
ASSERT_EQUALS("", errout_str());
3030
+
3031
+
// A direct null guard on the pointer (or its alias) is still handled and must not warn
0 commit comments