[clang] [analyzer] fix crash on binding to symbolic region with `void *` type (PR #107572)

Pavel Skripkin via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 6 05:22:43 PDT 2024


https://github.com/pskrgag created https://github.com/llvm/llvm-project/pull/107572

As reported in https://github.com/llvm/llvm-project/pull/103714#issuecomment-2295769193. CSA crashes on trying to bind value to symbolic region with `void *`. This happens when such region gets passed as inline asm input and engine tries to bind `UnknownVal` to that region.

Fix it by changing type from void to char before calling `GetElementZeroRegion`

>From 0e8db855a1bde0692260f5aa26c245328a358a50 Mon Sep 17 00:00:00 2001
From: Pavel Skripkin <paskripkin at gmail.com>
Date: Fri, 6 Sep 2024 15:15:52 +0300
Subject: [PATCH] clang/csa: fix crash on bind to symbolic region with void *

---
 clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 12 ++++++++++--
 clang/test/Analysis/asm.cpp                   |  9 +++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index ba29c123139016..a523daad28736f 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2380,8 +2380,16 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
 
   // Binding directly to a symbolic region should be treated as binding
   // to element 0.
-  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
-    R = GetElementZeroRegion(SR, SR->getPointeeStaticType());
+  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+    // Symbolic region with void * type may appear as input for inline asm
+    // block. In such case CSA cannot reason about region content and just
+    // assumes it has UnknownVal()
+    QualType PT = SR->getPointeeStaticType();
+    if (PT->isVoidType())
+      PT = StateMgr.getContext().CharTy;
+
+    R = GetElementZeroRegion(SR, PT);
+  }
 
   assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
          "'this' pointer is not an l-value and is not assignable");
diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index b17ab04994d249..0abaa96b0ae79e 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -40,3 +40,12 @@ void testInlineAsmMemcpyUninit(void)
     MyMemcpy(&a[1], &b[1], sizeof(b) - sizeof(b[1]));
     c = a[0]; // expected-warning{{Assigned value is garbage or undefined}}
 }
+
+void *globalPtr;
+
+void testNoCrash()
+{
+  // Use global pointer to make it symbolic. Then engine will try to bind
+  // value to first element of type void * and should not crash.
+  asm ("" : : "a"(globalPtr)); // no crash
+}



More information about the cfe-commits mailing list