https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/155157

We need to use the base offset in both cases.
Also, add additional assertions to make sure we don't miss this case again.

Fixes #155132

>From c466589f26780f35a317a6743ea675e89ea73764 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sun, 24 Aug 2025 12:25:34 +0200
Subject: [PATCH] [clang][bytecode] Fix incorrect offset in elem()

We need to use the base offset in both cases.
Also, add additional assertions to make sure we don't miss this case
again.

Fixes #155132
---
 clang/lib/AST/ByteCode/EvaluationResult.cpp |  4 ++--
 clang/lib/AST/ByteCode/Pointer.h            | 17 +++++++++++------
 clang/test/AST/ByteCode/invalid.cpp         |  8 ++++++++
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp 
b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index b11531f4296a2..5110e243d167c 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -178,8 +178,8 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
 static void collectBlocks(const Pointer &Ptr,
                           llvm::SetVector<const Block *> &Blocks) {
   auto isUsefulPtr = [](const Pointer &P) -> bool {
-    return P.isLive() && !P.isZero() && !P.isDummy() && P.isDereferencable() &&
-           !P.isUnknownSizeArray() && !P.isOnePastEnd();
+    return P.isLive() && P.isBlockPointer() && !P.isZero() && !P.isDummy() &&
+           P.isDereferencable() && !P.isUnknownSizeArray() && 
!P.isOnePastEnd();
   };
 
   if (!isUsefulPtr(Ptr))
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 0ce54ab0a17df..825a92b4424cb 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -696,15 +696,20 @@ class Pointer {
     assert(asBlockPointer().Pointee);
     assert(isDereferencable());
     assert(getFieldDesc()->isPrimitiveArray());
+    assert(I < getFieldDesc()->getNumElems());
 
     unsigned ElemByteOffset = I * getFieldDesc()->getElemSize();
-    if (isArrayRoot())
-      return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() +
-                                    asBlockPointer().Base + sizeof(InitMapPtr) 
+
-                                    ElemByteOffset);
+    if (isArrayRoot()) {
+      unsigned ReadOffset = BS.Base + sizeof(InitMapPtr) + ElemByteOffset;
+      assert(ReadOffset + sizeof(T) <=
+             BS.Pointee->getDescriptor()->getAllocSize());
+      return *reinterpret_cast<T *>(BS.Pointee->rawData() + ReadOffset);
+    }
 
-    return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset 
+
-                                  ElemByteOffset);
+    unsigned ReadOffset = BS.Base + ElemByteOffset;
+    assert(ReadOffset + sizeof(T) <=
+           BS.Pointee->getDescriptor()->getAllocSize());
+    return *reinterpret_cast<T *>(BS.Pointee->rawData() + ReadOffset);
   }
 
   /// Whether this block can be read from at all. This is only true for
diff --git a/clang/test/AST/ByteCode/invalid.cpp 
b/clang/test/AST/ByteCode/invalid.cpp
index 2a6c2d13e8467..affb40eada870 100644
--- a/clang/test/AST/ByteCode/invalid.cpp
+++ b/clang/test/AST/ByteCode/invalid.cpp
@@ -58,3 +58,11 @@ namespace Casts {
   /// Just make sure this doesn't crash.
   float PR9558 = reinterpret_cast<const float&>("asd");
 }
+
+
+/// This used to crash in collectBlock().
+struct S {
+};
+S s;
+S *sp[2] = {&s, &s};
+S *&spp = sp[1];

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

Reply via email to