[clang] [clang] LazyOffsetPtr: Use native pointer width (PR #111995)

A. Wilcox via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 11 05:59:50 PDT 2024


https://github.com/awilfox created https://github.com/llvm/llvm-project/pull/111995

On big-endian systems, narrow casting will read the higher bits of the value.  LazyOffsetPtr's `getAddressOfPointer` returns the address-of `Ptr` which was unconditionally a 64-bit value.  On 32-bit big endian systems, reading this value as a 32-bit pointer returns invalid data.

Fixes: bc73ef0031 ("PR60985: Fix merging of lambda closure types across modules.")
Closes: #111993

>From 3c9198421a44f32d00c2ebe4ee0bf5a6ec67e9ac Mon Sep 17 00:00:00 2001
From: "A. Wilcox" <AWilcox at Wilcox-Tech.com>
Date: Fri, 11 Oct 2024 07:54:43 -0500
Subject: [PATCH] [clang] LazyOffsetPtr: Use native pointer width

On big-endian systems, narrow casting will read the higher bits of the
value.  LazyOffsetPtr's `getAddressOfPointer` returns the address-of
`Ptr` which was unconditionally a 64-bit value.  On 32-bit big endian
systems, reading this value as a 32-bit pointer returns invalid data.

Fixes: bc73ef0031 ("PR60985: Fix merging of lambda closure types across modules.")
Closes: #111993
---
 clang/include/clang/AST/ExternalASTSource.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h
index 385c32edbae0fd..f5ce1a916fbee8 100644
--- a/clang/include/clang/AST/ExternalASTSource.h
+++ b/clang/include/clang/AST/ExternalASTSource.h
@@ -326,25 +326,25 @@ struct LazyOffsetPtr {
   ///
   /// If the low bit is clear, a pointer to the AST node. If the low
   /// bit is set, the upper 63 bits are the offset.
-  mutable uint64_t Ptr = 0;
+  mutable uintptr_t Ptr = 0;
 
 public:
   LazyOffsetPtr() = default;
-  explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {}
+  explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uintptr_t>(Ptr)) {}
 
-  explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
-    assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+  explicit LazyOffsetPtr(uintptr_t Offset) : Ptr((Offset << 1) | 0x01) {
+    assert((Offset << 1 >> 1) == Offset && "Offsets must fit in addressable bits");
     if (Offset == 0)
       Ptr = 0;
   }
 
   LazyOffsetPtr &operator=(T *Ptr) {
-    this->Ptr = reinterpret_cast<uint64_t>(Ptr);
+    this->Ptr = reinterpret_cast<uintptr_t>(Ptr);
     return *this;
   }
 
-  LazyOffsetPtr &operator=(uint64_t Offset) {
-    assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+  LazyOffsetPtr &operator=(uintptr_t Offset) {
+    assert((Offset << 1 >> 1) == Offset && "Offsets must fit in addressable bits");
     if (Offset == 0)
       Ptr = 0;
     else
@@ -375,7 +375,7 @@ struct LazyOffsetPtr {
     if (isOffset()) {
       assert(Source &&
              "Cannot deserialize a lazy pointer without an AST source");
-      Ptr = reinterpret_cast<uint64_t>((Source->*Get)(OffsT(Ptr >> 1)));
+      Ptr = reinterpret_cast<uintptr_t>((Source->*Get)(OffsT(Ptr >> 1)));
     }
     return reinterpret_cast<T*>(Ptr);
   }



More information about the cfe-commits mailing list