[clang] [analyzer] fix crash on binding to symbolic region with `void *` type (PR #107572)
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 9 07:06:50 PDT 2024
https://github.com/steakhal 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/2] 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/2] 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>}}}
}
More information about the cfe-commits
mailing list