[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
Mon Sep 9 08:48:06 PDT 2024


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

>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 1/4] 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
+}

>From 106e2d4a50b1208829e70317a059136de0354a47 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Mon, 9 Sep 2024 16:06:41 +0200
Subject: [PATCH 2/4] Apply suggestions from code review

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

diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index a523daad28736f..c257a87dff385b 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2380,15 +2380,11 @@ 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)) {
-    // 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);
+  if (const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
+    QualType Ty = SymReg->getPointeeStaticType();
+    if (Ty->isVoidType())
+      Ty = StateMgr.getContext().CharTy;
+    R = GetElementZeroRegion(SymReg, Ty);
   }
 
   assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index 0abaa96b0ae79e..4ec119400d2a04 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -41,11 +41,12 @@ void testInlineAsmMemcpyUninit(void)
     c = a[0]; // expected-warning{{Assigned value is garbage or undefined}}
 }
 
-void *globalPtr;
-
-void testNoCrash()
+void testAsmWithVoidPtrArgument()
 {
-  // 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
+  extern void *globalVoidPtr;
+  clang_analyzer_dump(*(int *)globalVoidPtr); // expected-warning-re {{reg_${{[0-9]+}}<int Element{SymRegion{reg_${{[0-9]+}}<void * globalVoidPtr>},0 S64b,int}>}}
+  clang_analyzer_dump_ptr(globalVoidPtr); // expected-warning-re {{&SymRegion{reg_${{[0-9]+}}<void * globalVoidPtr>}}}
+  asm ("" : : "a"(globalVoidPtr)); // no crash
+  clang_analyzer_dump(*(int *)globalVoidPtr); // expected-warning {{Unknown}}
+  clang_analyzer_dump_ptr(globalVoidPtr); // expected-warning-re {{&SymRegion{reg_${{[0-9]+}}<void * globalVoidPtr>}}}
 }

>From 39a1411d31302c39f1ba288872311982192afcca Mon Sep 17 00:00:00 2001
From: Pavel Skripkin <paskripkin at gmail.com>
Date: Mon, 9 Sep 2024 17:43:53 +0300
Subject: [PATCH 3/4] add missing declarations

---
 clang/test/Analysis/asm.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index 4ec119400d2a04..e18b9c0e866c69 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -3,6 +3,9 @@
 
 int clang_analyzer_eval(int);
 
+void clang_analyzer_dump(int);
+void clang_analyzer_dump_ptr(void *);
+
 int global;
 void testRValueOutput() {
   int &ref = global;

>From 5d21e797d62ef543064fb24e564575e8ca048625 Mon Sep 17 00:00:00 2001
From: Pavel Skripkin <paskripkin at gmail.com>
Date: Mon, 9 Sep 2024 18:47:47 +0300
Subject: [PATCH 4/4] remove extra newline

---
 clang/test/Analysis/asm.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index e18b9c0e866c69..e0691dc4d794f5 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -2,7 +2,6 @@
 // RUN:      -analyzer-checker debug.ExprInspection,core -Wno-error=invalid-gnu-asm-cast -w %s -verify
 
 int clang_analyzer_eval(int);
-
 void clang_analyzer_dump(int);
 void clang_analyzer_dump_ptr(void *);
 



More information about the cfe-commits mailing list