Index: include/llvm/Support/Allocator.h =================================================================== --- include/llvm/Support/Allocator.h +++ include/llvm/Support/Allocator.h @@ -156,7 +156,7 @@ BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), - BytesAllocated(Old.BytesAllocated), + BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize), Allocator(std::move(Old.Allocator)) { Old.CurPtr = Old.End = nullptr; Old.BytesAllocated = 0; @@ -176,6 +176,7 @@ CurPtr = RHS.CurPtr; End = RHS.End; BytesAllocated = RHS.BytesAllocated; + RedZoneSize = RHS.RedZoneSize; Slabs = std::move(RHS.Slabs); CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); Allocator = std::move(RHS.Allocator); @@ -218,10 +219,16 @@ size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); + size_t SizeToAllocate = Size; +#if LLVM_ADDRESS_SANITIZER_BUILD + // Add a trailing byte as a "red zone" under ASan. + SizeToAllocate += RedZoneSize; +#endif + // Check if we have enough space. - if (Adjustment + Size <= size_t(End - CurPtr)) { + if (Adjustment + SizeToAllocate <= size_t(End - CurPtr)) { char *AlignedPtr = CurPtr + Adjustment; - CurPtr = AlignedPtr + Size; + CurPtr = AlignedPtr + SizeToAllocate; // Update the allocation point of this memory block in MemorySanitizer. // Without this, MemorySanitizer messages for values originated from here // will point to the allocation of the entire slab. @@ -232,7 +239,7 @@ } // If Size is really big, allocate a separate slab for it. - size_t PaddedSize = Size + Alignment - 1; + size_t PaddedSize = SizeToAllocate + Alignment - 1; if (PaddedSize > SizeThreshold) { void *NewSlab = Allocator.Allocate(PaddedSize, 0); // We own the new slab and don't want anyone reading anyting other than @@ -251,10 +258,10 @@ // Otherwise, start a new slab and try again. StartNewSlab(); uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); - assert(AlignedAddr + Size <= (uintptr_t)End && + assert(AlignedAddr + SizeToAllocate <= (uintptr_t)End && "Unable to allocate memory!"); char *AlignedPtr = (char*)AlignedAddr; - CurPtr = AlignedPtr + Size; + CurPtr = AlignedPtr + SizeToAllocate; __msan_allocated_memory(AlignedPtr, Size); __asan_unpoison_memory_region(AlignedPtr, Size); return AlignedPtr; @@ -283,6 +290,10 @@ size_t getBytesAllocated() const { return BytesAllocated; } + void setRedZoneSize(size_t NewSize) { + RedZoneSize = NewSize; + } + void PrintStats() const { detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, getTotalMemory()); @@ -308,6 +319,10 @@ /// Used so that we can compute how much space was wasted. size_t BytesAllocated; + /// \brief The number of bytes to put between allocations when running under + /// a sanitizer. + size_t RedZoneSize = 1; + /// \brief The allocator instance we use to get slabs of memory. AllocatorT Allocator; @@ -369,7 +384,11 @@ BumpPtrAllocator Allocator; public: - SpecificBumpPtrAllocator() = default; + SpecificBumpPtrAllocator() { + // Because SpecificBumpPtrAllocator walks the memory to call destructors, + // it can't have red zones between allocations. + Allocator.setRedZoneSize(0); + } SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) : Allocator(std::move(Old.Allocator)) {} ~SpecificBumpPtrAllocator() { DestroyAll(); }