[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