https://github.com/voyager-jhk updated 
https://github.com/llvm/llvm-project/pull/225048

>From 02be70874b6dfd389c9281d6ef38306748499f56 Mon Sep 17 00:00:00 2001
From: voyager-jhk <[email protected]>
Date: Mon, 21 Sep 2026 17:06:58 +0800
Subject: [PATCH] [analyzer] Preserve LocAsInteger through identity operations

Preserve LocAsInteger values through identity operations on integers
converted from pointers.

This fixes a false positive leak report from unix.Malloc.

Fixes #220972
---
 clang/docs/ReleaseNotes.md                    |  3 +
 .../StaticAnalyzer/Core/SimpleSValBuilder.cpp | 24 ++++++++
 .../Analysis/identity-ops-on-LocAsInteger.c   | 57 +++++++++++++++++++
 3 files changed, 84 insertions(+)
 create mode 100644 clang/test/Analysis/identity-ops-on-LocAsInteger.c

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index db710b64a6ae53..f0f1b7f65c35f7 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -871,6 +871,9 @@ features cannot lower the translation-unit ABI level;
 
 #### Crash and bug fixes
 
+- Fixed a false positive `unix.Malloc` leak report for identity operations on
+  integers converted from pointers.
+
 % comment:
 % This is for the Static Analyzer.
 % Use `####` headings for subsections:
diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 7d154cbc840aca..c742de27e7aaa8 100644
--- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -230,6 +230,25 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
   return makeNonLoc(LHS, op, *ConvertedRHS, resultTy);
 }
 
+// Returns whether X op RHS is equivalent to X.
+static bool isIdentityOperation(BinaryOperator::Opcode op,
+                                const llvm::APSInt &RHS) {
+  switch (op) {
+  case BO_Add:
+  case BO_Sub:
+  case BO_Or:
+  case BO_Xor:
+  case BO_Shl:
+  case BO_Shr:
+    return RHS == 0;
+  case BO_Mul:
+  case BO_Div:
+    return RHS == 1;
+  default:
+    return false;
+  }
+}
+
 // See if Sym is known to be a relation Rel with Bound.
 static bool isInRelation(BinaryOperator::Opcode Rel, SymbolRef Sym,
                          llvm::APSInt Bound, ProgramStateRef State) {
@@ -491,6 +510,11 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
                            rhs.castAs<nonloc::LocAsInteger>().getLoc(),
                            resultTy);
       case nonloc::ConcreteIntKind: {
+        // Preserve the location for identity operations.
+        if (isIdentityOperation(op,
+                                rhs.castAs<nonloc::ConcreteInt>().getValue()))
+          return evalCast(lhs, resultTy, QualType{});
+
         // FIXME: at the moment the implementation
         // of modeling "pointers as integers" is not complete.
         if (!BinaryOperator::isComparisonOp(op))
diff --git a/clang/test/Analysis/identity-ops-on-LocAsInteger.c 
b/clang/test/Analysis/identity-ops-on-LocAsInteger.c
new file mode 100644
index 00000000000000..39f655724f329d
--- /dev/null
+++ b/clang/test/Analysis/identity-ops-on-LocAsInteger.c
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=core,unix.Malloc,debug.ExprInspection
+
+// Identity operations on a LocAsInteger must preserve the original location.
+// GH#220972.
+
+typedef unsigned __INTPTR_TYPE__ uintptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+void *malloc(size_t);
+void free(void *);
+void clang_analyzer_eval(int);
+
+void test_add_zero(void)
+{
+  void *ptr = malloc(16);
+  if (ptr == 0)
+    return;
+
+  uintptr_t value = (uintptr_t)ptr;
+  value += 0;
+  clang_analyzer_eval(value == (uintptr_t)ptr); // expected-warning{{TRUE}}
+
+  free((void *)value); // no-warning
+}
+
+void test_other_identity_ops(void)
+{
+  void *ptr = malloc(16);
+  if (ptr == 0)
+    return;
+
+  uintptr_t value = (uintptr_t)ptr;
+  value -= 0;
+  value |= 0;
+  value ^= 0;
+  value <<= 0;
+  value >>= 0;
+  value *= 1;
+  value /= 1;
+  clang_analyzer_eval(value == (uintptr_t)ptr); // expected-warning{{TRUE}}
+
+  free((void *)value); // no-warning
+}
+
+void test_narrower_result(void)
+{
+  void *ptr = malloc(16);
+  if (ptr == 0)
+    return;
+
+  unsigned value = (unsigned)(uintptr_t)ptr;
+  value += 0;
+  clang_analyzer_eval(value == (unsigned)(uintptr_t)ptr); // 
expected-warning{{TRUE}}
+
+  free(ptr); // no-warning
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to