diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -903,6 +903,10 @@ void setTrackAllocationStacks(bool Track) { initThreadMaybe(); + if (getFlags()->allocation_ring_buffer_size == 0) { + DCHECK(!Primary.Options.get(OptionsBit::TrackAllocationStacks)); + return; + } if (Track) Primary.Options.set(OptionBit::TrackAllocationStacks); else @@ -1066,6 +1070,10 @@ // Pointer to memory mapped area starting with AllocationRingBuffer struct, // and immediately followed by Size elements of type Entry. char *RawRingBuffer = {}; + // If we disable allocation tracking, we give a zero-sized + // AllocationRingBuffer to the client code. This is slightly wasteful + // (we use 128 bytes on a 64-bit platform), but simplifies the code. + AllocationRingBuffer PlaceholderRingBuffer = {}; // The following might get optimized out by the compiler. NOINLINE void performSanityChecks() { @@ -1408,8 +1416,8 @@ const char *RingBufferPtr) { auto *RingBuffer = reinterpret_cast(RingBufferPtr); - if (!RingBuffer) - return; // just in case; called before init + if (!RingBuffer || RingBuffer->Size == 0) + return; uptr Pos = atomic_load_relaxed(&RingBuffer->Pos); for (uptr I = Pos - 1; @@ -1495,9 +1503,14 @@ void initRingBuffer() { u32 AllocationRingBufferSize = static_cast(getFlags()->allocation_ring_buffer_size); - // Have at least one entry so we don't need to special case. - if (AllocationRingBufferSize < 1) - AllocationRingBufferSize = 1; + // If allocation_ring_buffer_size is zero we allocate a placeholder as not + // to confuse downstream users of this buffer, but we don't use it because + // we disallow setTrackAllocationStacks. + if (AllocationRingBufferSize < 1) { + DCHECK(PlaceholderRingBuffer->Size == 0); + RawRingBuffer = reinterpret_cast(&PlaceholderRingBuffer); + return; + } MapPlatformData Data = {}; RawRingBuffer = static_cast( map(/*Addr=*/nullptr,