[clang] [analyzer] Do not reason about locations passed as inline asm input (PR #103714)
Pavel Skripkin via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 14 05:50:19 PDT 2024
https://github.com/pskrgag updated https://github.com/llvm/llvm-project/pull/103714
>From e528b0ded1a9815195e33d141a9e8ce05fb26cd1 Mon Sep 17 00:00:00 2001
From: Pavel Skripkin <paskripkin at gmail.com>
Date: Wed, 14 Aug 2024 10:50:24 +0300
Subject: [PATCH 1/2] clang/csa: stop reasoning about pointers passed inside
inline assembly
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 8 +++++
clang/test/Analysis/asm.cpp | 36 +++++++++++++++++++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 686310d38ebd58..d64134102d96c7 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3807,6 +3807,14 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
}
+ // Do not reason about locations passed inside inline assembly.
+ for (const Expr *O : A->inputs()) {
+ SVal X = state->getSVal(O, Pred->getLocationContext());
+
+ if (std::optional<Loc> LV = X.getAs<Loc>())
+ state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
+ }
+
Bldr.generateNode(A, Pred, state);
}
diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index 1180063502168f..5d158b62e7221f 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -fheinous-gnu-extensions -w %s -verify
+// RUN: %clang_analyze_cc1 -triple=x86_64-unknown-unknown \
+// RUN: -analyzer-checker debug.ExprInspection,core -fheinous-gnu-extensions -w %s -verify
int clang_analyzer_eval(int);
@@ -10,3 +11,36 @@ void testRValueOutput() {
clang_analyzer_eval(global == 1); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(ref == 1); // expected-warning{{UNKNOWN}}
}
+
+void *MyMemcpy(void *d, const void *s, const int n) {
+ asm volatile (
+ "cld\n rep movsb\n"
+ :: "S" (s), "D" (d), "c" (n) : "memory"
+ );
+
+ return d;
+}
+
+void testInlineAsmMemcpy(void)
+{
+ int a, b = 10, c;
+
+ MyMemcpy(&a, &b, sizeof(b));
+ c = a; // no-warning
+}
+
+void testInlineAsmMemcpyArray(void)
+{
+ int a[10], b[10] = {}, c;
+
+ MyMemcpy(&a, &b, sizeof(b));
+ c = a[8]; // no-warning
+}
+
+void testInlineAsmMemcpyUninit(void)
+{
+ int a[10], b[10] = {}, c;
+
+ MyMemcpy(&a[1], &b[1], sizeof(b) - sizeof(b[1]));
+ c = a[0]; // expected-warning{{Assigned value is garbage or undefined}}
+}
>From 70f9323c183fd1703f31e098bf3b3ac43dc7dc7d Mon Sep 17 00:00:00 2001
From: Pavel Skripkin <paskripkin at gmail.com>
Date: Wed, 14 Aug 2024 15:49:21 +0300
Subject: [PATCH 2/2] fix naming and remove newlines after declarations in test
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 4 ++--
clang/test/Analysis/asm.cpp | 4 ----
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index d64134102d96c7..493914f88ba9a5 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3808,8 +3808,8 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
}
// Do not reason about locations passed inside inline assembly.
- for (const Expr *O : A->inputs()) {
- SVal X = state->getSVal(O, Pred->getLocationContext());
+ for (const Expr *I : A->inputs()) {
+ SVal X = state->getSVal(I, Pred->getLocationContext());
if (std::optional<Loc> LV = X.getAs<Loc>())
state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
diff --git a/clang/test/Analysis/asm.cpp b/clang/test/Analysis/asm.cpp
index 5d158b62e7221f..3181aea870c8aa 100644
--- a/clang/test/Analysis/asm.cpp
+++ b/clang/test/Analysis/asm.cpp
@@ -17,14 +17,12 @@ void *MyMemcpy(void *d, const void *s, const int n) {
"cld\n rep movsb\n"
:: "S" (s), "D" (d), "c" (n) : "memory"
);
-
return d;
}
void testInlineAsmMemcpy(void)
{
int a, b = 10, c;
-
MyMemcpy(&a, &b, sizeof(b));
c = a; // no-warning
}
@@ -32,7 +30,6 @@ void testInlineAsmMemcpy(void)
void testInlineAsmMemcpyArray(void)
{
int a[10], b[10] = {}, c;
-
MyMemcpy(&a, &b, sizeof(b));
c = a[8]; // no-warning
}
@@ -40,7 +37,6 @@ void testInlineAsmMemcpyArray(void)
void testInlineAsmMemcpyUninit(void)
{
int a[10], b[10] = {}, c;
-
MyMemcpy(&a[1], &b[1], sizeof(b) - sizeof(b[1]));
c = a[0]; // expected-warning{{Assigned value is garbage or undefined}}
}
More information about the cfe-commits
mailing list