From 5b48af38bde9d789cfc9a1db38b6764c17919f02 Mon Sep 17 00:00:00 2001 From: Chen Steenvoorden Date: Wed, 1 May 2024 16:10:43 +0200 Subject: [PATCH] Fix global ::delete on virtual object Using `::delete` would fail because `ItaniumCXXABI::emitVirtualObjectDelete` used the wrong offset (-2) into the vtable to find the complete-object pointer. Example (triggers address sanitizer): ``` struct Base { virtual ~Base() {} }; struct Derived : Base {}; int main() { Derived* derived = ::new Derived(); ::delete derived; } ``` --- clang/lib/CodeGen/ItaniumCXXABI.cpp | 33 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 51b183fb7a81..7e1477e5602b 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1282,16 +1282,35 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // Derive the complete-object pointer, which is what we need // to pass to the deallocation function. - // Grab the vtable pointer as an intptr_t*. auto *ClassDecl = cast(ElementType->castAs()->getDecl()); - llvm::Value *VTable = - CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl); + llvm::Value *Offset; - // Track back to entry -2 and pull out the offset there. - llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( - CGF.IntPtrTy, VTable, -2, "complete-offset.ptr"); - llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr, CGF.getPointerAlign()); + if (!CGM.getTarget().isByteAddressable()) { + bool asmjs = ClassDecl->hasAttr(); + + if (asmjs) { + llvm::Type *VTableType = + CGM.getTypes().GetSecondaryVTableType(ClassDecl); + Address VTable = Address( + CGF.GetVTablePtr(Ptr, VTableType->getPointerTo(), ClassDecl), + VTableType, Ptr.getAlignment()); + Address Tmp = CGF.Builder.CreateStructGEP(VTable, 0); + Offset = CGF.Builder.CreateLoad(Tmp, "complete-offset.ptr"); + } else { + Offset = llvm::ConstantInt::get(CGM.IntPtrTy, 0); + } + } else { + // Grab the vtable pointer as an intptr_t*. + llvm::Value *VTable = + CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl); + + // Track back to entry -2 and pull out the offset there. + llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( + CGF.IntPtrTy, VTable, -2, "complete-offset.ptr"); + Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr, + CGF.getPointerAlign()); + } // Apply the offset. llvm::Value *CompletePtr =