diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 15a199ae0349b..9283e11aa3b7f 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -565,6 +565,20 @@ class Allocator { storeSecondaryAllocationStackMaybe(Options, OldPtr, NewSize); } } + + // If we have reduced the size, set the extra bytes to the fill value + // so that we are ready to grow it again in the future. + if (NewSize < OldSize) { + const FillContentsMode FillContents = + TSDRegistry.getDisableMemInit() ? NoFill + : Options.getFillContentsMode(); + if (FillContents != NoFill) { + memset(reinterpret_cast(OldTaggedPtr) + NewSize, + FillContents == ZeroFill ? 0 : PatternFillByte, + OldSize - NewSize); + } + } + return OldTaggedPtr; } } diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp index 1a36155bcd423..655dc87cbac64 100644 --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -447,19 +447,32 @@ SCUDO_TYPED_TEST(ScudoCombinedDeathTest, ReallocateSame) { // returns the same chunk. This requires that all the sizes we iterate on use // the same block size, but that should be the case for MaxSize - 64 with our // default class size maps. - constexpr scudo::uptr ReallocSize = + constexpr scudo::uptr InitialSize = TypeParam::Primary::SizeClassMap::MaxSize - 64; - void *P = Allocator->allocate(ReallocSize, Origin); const char Marker = 'A'; - memset(P, Marker, ReallocSize); + Allocator->setFillContents(scudo::PatternOrZeroFill); + + void *P = Allocator->allocate(InitialSize, Origin); + scudo::uptr CurrentSize = InitialSize; for (scudo::sptr Delta = -32; Delta < 32; Delta += 8) { + memset(P, Marker, CurrentSize); const scudo::uptr NewSize = - static_cast(static_cast(ReallocSize) + Delta); + static_cast(static_cast(InitialSize) + Delta); void *NewP = Allocator->reallocate(P, NewSize); EXPECT_EQ(NewP, P); - for (scudo::uptr I = 0; I < ReallocSize - 32; I++) + + // Verify that existing contents have been preserved. + for (scudo::uptr I = 0; I < scudo::Min(CurrentSize, NewSize); I++) EXPECT_EQ((reinterpret_cast(NewP))[I], Marker); + + // Verify that new bytes are set according to FillContentsMode. + for (scudo::uptr I = CurrentSize; I < NewSize; I++) { + EXPECT_EQ((reinterpret_cast(NewP))[I], + scudo::PatternFillByte); + } + checkMemoryTaggingMaybe(Allocator, NewP, NewSize, 0); + CurrentSize = NewSize; } Allocator->deallocate(P, Origin); }