Skip to content

[clang][dataflow] Add a test demonstrating an issue in unchecked-optional-access-check #110870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 2, 2024

Conversation

jvoung
Copy link
Contributor

@jvoung jvoung commented Oct 2, 2024

createStorageLocation used in transferCallReturningOptional:

Loc = &cast<RecordStorageLocation>(State.Env.createStorageLocation(*E));

can stop recursively creating storage locations when it hits a field of
reference type for a non-optional record:
if (Field->getType()->isReferenceType())

If an optional is reached through that field then it may not have a
storage location by the type we handle has_value in a transfer function.

jvoung added 3 commits October 2, 2024 15:26
…onal-access-check

createStorageLocation used in transferCallReturningOptional:
https://github.com/llvm/llvm-project/blob/09ba83be0ac178851e3c9c9c8fefddbdd4d8353f/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp#L515
can stop recursively creating storage locations when it hits a field of
reference type for a non-optional record:
https://github.com/llvm/llvm-project/blob/3ca5d8082a0c6bd9520544ce3bca11bf3e02a5fa/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp#L67

If an optional is reached through that field then it may not have a
storage location by the type we handle has_value in a transfer function.
@jvoung jvoung marked this pull request as ready for review October 2, 2024 16:18
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html labels Oct 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Oct 2, 2024

@llvm/pr-subscribers-clang

Author: Jan Voung (jvoung)

Changes

createStorageLocation used in transferCallReturningOptional:

Loc = &cast<RecordStorageLocation>(State.Env.createStorageLocation(*E));

can stop recursively creating storage locations when it hits a field of
reference type for a non-optional record:
if (Field->getType()->isReferenceType())

If an optional is reached through that field then it may not have a
storage location by the type we handle has_value in a transfer function.


Full diff: https://github.com/llvm/llvm-project/pull/110870.diff

1 Files Affected:

  • (modified) clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp (+34)
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index 4227a6bfdeba87..877bfce8b27092 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -2873,6 +2873,40 @@ TEST_P(UncheckedOptionalAccessTest, OptionalValueStruct) {
   )");
 }
 
+// FIXME: A case that we should handle but currently don't.
+// When there is a field of type reference to non-optional, we may
+// stop recursively creating storage locations.
+// E.g., the field `second` below in `pair` should eventually lead to
+// the optional `x` in `A`.
+TEST_P(UncheckedOptionalAccessTest, NestedOptionalThroughNonOptionalRefField) {
+  ExpectDiagnosticsFor(R"(
+    #include "unchecked_optional_access_test.h"
+
+    struct A {
+      $ns::$optional<int> x;
+    };
+
+    struct pair {
+      int first;
+      const A &second;
+    };
+
+    struct B {
+      $ns::$optional<pair>& nonConstGetRef();
+    };
+
+    void target(B b) {
+      const auto& maybe_pair = b.nonConstGetRef();
+      if (!maybe_pair.has_value())
+        return;
+
+      if(!maybe_pair->second.x.has_value())
+        return;
+      maybe_pair->second.x.value();  // [[unsafe]]
+    }
+  )");
+}
+
 TEST_P(UncheckedOptionalAccessTest, OptionalValueInitialization) {
   ExpectDiagnosticsFor(
       R"(

@jvoung jvoung requested review from martinboehme and ymand October 2, 2024 16:21
@jvoung jvoung merged commit 39851e3 into llvm:main Oct 2, 2024
12 checks passed
Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this pull request Oct 3, 2024
…onal-access-check (llvm#110870)

createStorageLocation used in transferCallReturningOptional:

https://github.com/llvm/llvm-project/blob/09ba83be0ac178851e3c9c9c8fefddbdd4d8353f/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp#L515
can stop recursively creating storage locations when it hits a field of
reference type for a non-optional record:

https://github.com/llvm/llvm-project/blob/3ca5d8082a0c6bd9520544ce3bca11bf3e02a5fa/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp#L67

If an optional is reached through that field then it may not have a
storage location by the type we handle has_value in a transfer function.
@jvoung jvoung deleted the unchecked_optional_unroll_issue branch October 3, 2024 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants