tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, cor3ntin.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This commit is a bit ugly at the moment since I'm gathering feedback.

The APFloats we use to implement the `Floating` type might heap-allocate stuff 
to represent large values. When we then later write those to bytecode (via 
`BytecodeEmitter`, not `EvalEmitter`), that heap allocation is dangling.

So, for code like

  constexpr long double f() {
    const long double L = __LDBL_MAX__;
  
    return L;
  };
  static_assert(f() == __LDBL_MAX__);

asan would complain:

  READ of size 8 at 0x602000001610 thread T0
      #0 0x7f525300b911 in llvm::APInt::tcAssign(unsigned long*, unsigned long 
const*, unsigned int) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APInt.cpp:2331:14
      #1 0x7f5252f3f640 in 
llvm::detail::IEEEFloat::copySignificand(llvm::detail::IEEEFloat const&) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:878:3
      #2 0x7f5252f3f42c in 
llvm::detail::IEEEFloat::assign(llvm::detail::IEEEFloat const&) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:871:5
      #3 0x7f5252f46828 in 
llvm::detail::IEEEFloat::IEEEFloat(llvm::detail::IEEEFloat const&) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1143:3
      #4 0x7f5295e12913 in 
llvm::APFloat::Storage::Storage(llvm::APFloat::Storage const&) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:805:20
      #5 0x7f5295e01d3a in llvm::APFloat::APFloat(llvm::APFloat const&) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:928:3
      #6 0x7f5297d56584 in 
clang::interp::Floating::Floating(clang::interp::Floating const&) 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7
      #7 0x7f5297ea1fa0 in clang::interp::Floating 
llvm::support::endian::read<clang::interp::Floating, 1ul>(void const*, 
llvm::support::endianness) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:70:32
      #8 0x7f5297ea1e14 in clang::interp::Floating 
llvm::support::endian::read<clang::interp::Floating, 
(llvm::support::endianness)2, 1ul>(void const*) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:77:10
      #9 0x7f5297ea1d06 in 
std::enable_if<!std::is_pointer<clang::interp::Floating>::value, 
clang::interp::Floating>::type 
clang::interp::CodePtr::read<clang::interp::Floating>() 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Source.h:53:15
      #10 0x7f52981e7601 in clang::interp::Floating 
clang::interp::ReadArg<clang::interp::Floating>(clang::interp::InterpState&, 
clang::interp::CodePtr&) 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Interp.h:1894:17
  [...]
  
  freed by thread T0 here:
      #0 0x3d2511 in operator delete[](void*) 
(/home/tbaeder/code/llvm-project/build/bin/clang-17+0x3d2511) (BuildId: 
88c1d01099b49a9ebf7bd913e201002fedf14f9b)
      #1 0x7f5252f3eff9 in llvm::detail::IEEEFloat::freeSignificand() 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:861:5
      #2 0x7f5252f46968 in llvm::detail::IEEEFloat::~IEEEFloat() 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1150:27
      #3 0x7f5295e11ad1 in llvm::APFloat::Storage::~Storage() 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:793:14
      #4 0x7f5295e01d9c in llvm::APFloat::~APFloat() 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:931:22
      #5 0x7f5297d5ddb8 in clang::interp::Floating::~Floating() 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7
      #6 0x7f5297ea1fe7 in clang::interp::Floating 
llvm::support::endian::read<clang::interp::Floating, 1ul>(void const*, 
llvm::support::endianness) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:71:1
  [...]
  
  previously allocated by thread T0 here:
      #0 0x3d1cb1 in operator new[](unsigned long) 
(/home/tbaeder/code/llvm-project/build/bin/clang-17+0x3d1cb1) (BuildId: 
88c1d01099b49a9ebf7bd913e201002fedf14f9b)
      #1 0x7f5252f3ed6a in 
llvm::detail::IEEEFloat::initialize(llvm::fltSemantics const*) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:856:25
      #2 0x7f5252f467e7 in 
llvm::detail::IEEEFloat::IEEEFloat(llvm::detail::IEEEFloat const&) 
/home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1142:3
      #3 0x7f5295e12913 in 
llvm::APFloat::Storage::Storage(llvm::APFloat::Storage const&) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:805:20
      #4 0x7f5295e01d3a in llvm::APFloat::APFloat(llvm::APFloat const&) 
/home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:928:3
      #5 0x7f5297d56584 in 
clang::interp::Floating::Floating(clang::interp::Floating const&) 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7
      #6 0x7f5297d17f93 in void 
emit<clang::interp::Floating>(clang::interp::Program&, 
std::__debug::vector<std::byte, std::allocator<std::byte>>&, 
clang::interp::Floating const&, bool&) 
/home/tbaeder/code/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp:202:32

So, this patch adds specialized `readArg()` and `emit()` versions for 
`Floating` that serializes the `APFloat`.

I'm not really sure if this is the best way to go though.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155165

Files:
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/Source.h
  clang/test/AST/Interp/floats.cpp

Index: clang/test/AST/Interp/floats.cpp
===================================================================
--- clang/test/AST/Interp/floats.cpp
+++ clang/test/AST/Interp/floats.cpp
@@ -140,4 +140,11 @@
 
 namespace LongDouble {
   constexpr long double ld = 3.1425926539;
+
+  constexpr long double f() {
+    const long double L = __LDBL_MAX__;
+
+    return L;
+  };
+  static_assert(f() == __LDBL_MAX__);
 }
Index: clang/lib/AST/Interp/Source.h
===================================================================
--- clang/lib/AST/Interp/Source.h
+++ clang/lib/AST/Interp/Source.h
@@ -60,6 +60,7 @@
   /// Constructor used by Function to generate pointers.
   CodePtr(const std::byte *Ptr) : Ptr(Ptr) {}
   /// Pointer into the code owned by a function.
+public:
   const std::byte *Ptr;
 };
 
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -1895,6 +1895,12 @@
   }
 }
 
+template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
+  Floating F = Floating::deserialize(OpPC.Ptr);
+  OpPC += align(F.bytesToSerialize());
+  return F;
+}
+
 } // namespace interp
 } // namespace clang
 
Index: clang/lib/AST/Interp/Floating.h
===================================================================
--- clang/lib/AST/Interp/Floating.h
+++ clang/lib/AST/Interp/Floating.h
@@ -124,6 +124,26 @@
     llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8);
   }
 
+  size_t bytesToSerialize() const {
+    return sizeof(llvm::fltSemantics *) +
+           (APFloat::semanticsSizeInBits(F.getSemantics()) / 8);
+  }
+
+  void serialize(std::byte *Buff) const {
+    // Semantics followed by an APInt.
+    *reinterpret_cast<const llvm::fltSemantics **>(Buff) = &F.getSemantics();
+
+    llvm::APInt API = F.bitcastToAPInt();
+    llvm::StoreIntToMemory(API, (uint8_t *)(Buff + sizeof(void *)),
+                           bitWidth() / 8);
+  }
+
+  static Floating deserialize(const std::byte *Buff) {
+    const llvm::fltSemantics *Sem;
+    std::memcpy((void *)&Sem, Buff, sizeof(void *));
+    return bitcastFromMemory(Buff + sizeof(void *), *Sem);
+  }
+
   // -------
 
   static APFloat::opStatus add(const Floating &A, const Floating &B,
Index: clang/lib/AST/Interp/ByteCodeEmitter.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -206,6 +206,25 @@
   }
 }
 
+template <>
+void emit(Program &P, std::vector<std::byte> &Code, const Floating &Val,
+          bool &Success) {
+  size_t Size = Val.bytesToSerialize();
+
+  if (Code.size() + Size > std::numeric_limits<unsigned>::max()) {
+    Success = false;
+    return;
+  }
+
+  // Access must be aligned!
+  size_t ValPos = align(Code.size());
+  Size = align(Size);
+  assert(aligned(ValPos + Size));
+  Code.resize(ValPos + Size);
+
+  Val.serialize(Code.data() + ValPos);
+}
+
 template <typename... Tys>
 bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &SI) {
   bool Success = true;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D155165: [clang][Inter... Timm Bäder via Phabricator via cfe-commits

Reply via email to