Skip to content

Commit 0fa37d5

Browse files
author
Your Name
committed
Terser comments
1 parent 12496fb commit 0fa37d5

1 file changed

Lines changed: 10 additions & 23 deletions

File tree

test/testnullpointer.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2988,10 +2988,9 @@ class TestNullPointer : public TestFixture {
29882988
errout_str());
29892989
}
29902990

2991-
void nullpointer107() // #13682 - don't flow past a condition that doesn't reference the pointer
2991+
void nullpointer107() // #13682 - guards that depend on the pointer indirectly
29922992
{
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)
2993+
// cached null-check 'ok'; guard 'if (!ok)' is safe -> no FP
29952994
check("struct S { void g(); bool f() const; };\n"
29962995
"void f(S* p) {\n"
29972996
" bool ok = (p != nullptr);\n"
@@ -3003,8 +3002,7 @@ class TestNullPointer : public TestFixture {
30033002
"}\n");
30043003
ASSERT_EQUALS("", errout_str());
30053004

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
3005+
// unrelated bool guard -> conservative, no FP
30083006
check("struct S { void g(); bool f() const; };\n"
30093007
"void f(S* p, bool valid) {\n"
30103008
" S* p1 = p;\n"
@@ -3016,7 +3014,7 @@ class TestNullPointer : public TestFixture {
30163014
"}\n");
30173015
ASSERT_EQUALS("", errout_str());
30183016

3019-
// A guard on a different pointer must not be assumed to constrain this one
3017+
// guard on a different pointer -> no FP
30203018
check("struct S { void g(); bool f() const; };\n"
30213019
"void f(S* p, S* q) {\n"
30223020
" S* p1 = p;\n"
@@ -3028,7 +3026,7 @@ class TestNullPointer : public TestFixture {
30283026
"}\n");
30293027
ASSERT_EQUALS("", errout_str());
30303028

3031-
// A direct null guard on the pointer (or its alias) is still handled and must not warn
3029+
// direct null guard on the alias -> no FP
30323030
check("struct S { void g(); bool f() const; };\n"
30333031
"void f(S* p) {\n"
30343032
" S* p1 = p;\n"
@@ -3040,10 +3038,7 @@ class TestNullPointer : public TestFixture {
30403038
"}\n");
30413039
ASSERT_EQUALS("", errout_str());
30423040

3043-
// 'if (ok) return;' means the surviving path has ok==false, i.e. p==nullptr, so 'p->g()'
3044-
// dereferences a null pointer. ProgramMemory cannot evaluate the cached 'ok' (== (p != nullptr))
3045-
// during forward analysis, so the conditionReferencesValue() guard stops the analysis here and the
3046-
// definite null dereference is missed. This should warn once ProgramMemory can follow 'ok'.
3041+
// FN: 'if (ok)' => survivor has p==nullptr, but the cached 'ok' is not followed -> should warn
30473042
check("struct S { void g(); bool f() const; };\n"
30483043
"void f(S* p) {\n"
30493044
" bool ok = (p != nullptr);\n"
@@ -3058,10 +3053,7 @@ class TestNullPointer : public TestFixture {
30583053
"",
30593054
errout_str());
30603055

3061-
// 'q' aliases 'p' (symbolic q==p), so the guard 'if (q)' constrains 'p'. Modifying 'q' via sink()
3062-
// drops the symbolic relationship; conditionReferencesValue() only inspects symbolic values, so it
3063-
// no longer sees that the guard relates to 'p', stops the analysis, and the possible null
3064-
// dereference of 'p' is missed. A more robust dependency check (not symbolic-only) should warn.
3056+
// FN: sink(q) drops the q==p symbolic, so guard 'if (q)' is no longer seen to relate to p -> should warn
30653057
check("struct S { void g(); bool f() const; };\n"
30663058
"void sink(S*&);\n"
30673059
"void f(S* p) {\n"
@@ -3078,13 +3070,8 @@ class TestNullPointer : public TestFixture {
30783070
"",
30793071
errout_str());
30803072

3081-
// These are dereferences that are actually safe, but the dependency that makes them safe is hidden
3082-
// behind a conditional modification. ProgramMemory tracks 'q'/'ok' and would normally evaluate the
3083-
// guard, but a conditional modification ('if (c) ...') makes it stop tracking the value, so the guard
3084-
// can no longer be evaluated during forward analysis. Without conditionReferencesValue() the possible
3085-
// null value would flow past the guard and produce a false positive; these must stay warning-free.
3086-
3087-
// symbolic substitution: 'q == p', conditionally re-assigned to 'p' (value preserved)
3073+
// a conditional modification makes ProgramMemory drop the guard (FP-prone) -> must stay quiet:
3074+
// alias 'q==p' re-assigned to p under a condition
30883075
check("struct S { void g(); bool f() const; };\n"
30893076
"void f(S* p, bool c) {\n"
30903077
" S* q = p;\n"
@@ -3098,7 +3085,7 @@ class TestNullPointer : public TestFixture {
30983085
"}\n");
30993086
ASSERT_EQUALS("", errout_str());
31003087

3101-
// conditional assignment of a cached condition: 'ok == (p != nullptr)', conditionally refreshed
3088+
// cached 'ok' refreshed under a condition
31023089
check("struct S { void g(); bool f() const; };\n"
31033090
"void f(S* p, bool c) {\n"
31043091
" bool ok = (p != nullptr);\n"

0 commit comments

Comments
 (0)