Skip to content

Commit 7fc975a

Browse files
authored
Reland "[scudo] Apply filling when realloc shrinks and re-grows a block in-place" (#95838)
Reland of #93212, which had been reverted in commit bddd8ea.
1 parent 519175c commit 7fc975a

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

compiler-rt/lib/scudo/standalone/combined.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,19 @@ class Allocator {
549549
// header to reflect the size change.
550550
if (reinterpret_cast<uptr>(OldTaggedPtr) + NewSize <= BlockEnd) {
551551
if (NewSize > OldSize || (OldSize - NewSize) < getPageSizeCached()) {
552+
// If we have reduced the size, set the extra bytes to the fill value
553+
// so that we are ready to grow it again in the future.
554+
if (NewSize < OldSize) {
555+
const FillContentsMode FillContents =
556+
TSDRegistry.getDisableMemInit() ? NoFill
557+
: Options.getFillContentsMode();
558+
if (FillContents != NoFill) {
559+
memset(reinterpret_cast<char *>(OldTaggedPtr) + NewSize,
560+
FillContents == ZeroFill ? 0 : PatternFillByte,
561+
OldSize - NewSize);
562+
}
563+
}
564+
552565
Header.SizeOrUnusedBytes =
553566
(ClassId ? NewSize
554567
: BlockEnd -

compiler-rt/lib/scudo/standalone/tests/combined_test.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,19 +447,32 @@ SCUDO_TYPED_TEST(ScudoCombinedDeathTest, ReallocateSame) {
447447
// returns the same chunk. This requires that all the sizes we iterate on use
448448
// the same block size, but that should be the case for MaxSize - 64 with our
449449
// default class size maps.
450-
constexpr scudo::uptr ReallocSize =
450+
constexpr scudo::uptr InitialSize =
451451
TypeParam::Primary::SizeClassMap::MaxSize - 64;
452-
void *P = Allocator->allocate(ReallocSize, Origin);
453452
const char Marker = 'A';
454-
memset(P, Marker, ReallocSize);
453+
Allocator->setFillContents(scudo::PatternOrZeroFill);
454+
455+
void *P = Allocator->allocate(InitialSize, Origin);
456+
scudo::uptr CurrentSize = InitialSize;
455457
for (scudo::sptr Delta = -32; Delta < 32; Delta += 8) {
458+
memset(P, Marker, CurrentSize);
456459
const scudo::uptr NewSize =
457-
static_cast<scudo::uptr>(static_cast<scudo::sptr>(ReallocSize) + Delta);
460+
static_cast<scudo::uptr>(static_cast<scudo::sptr>(InitialSize) + Delta);
458461
void *NewP = Allocator->reallocate(P, NewSize);
459462
EXPECT_EQ(NewP, P);
460-
for (scudo::uptr I = 0; I < ReallocSize - 32; I++)
463+
464+
// Verify that existing contents have been preserved.
465+
for (scudo::uptr I = 0; I < scudo::Min(CurrentSize, NewSize); I++)
461466
EXPECT_EQ((reinterpret_cast<char *>(NewP))[I], Marker);
467+
468+
// Verify that new bytes are set according to FillContentsMode.
469+
for (scudo::uptr I = CurrentSize; I < NewSize; I++) {
470+
unsigned char V = (reinterpret_cast<unsigned char *>(NewP))[I];
471+
EXPECT_TRUE(V == scudo::PatternFillByte || V == 0);
472+
}
473+
462474
checkMemoryTaggingMaybe(Allocator, NewP, NewSize, 0);
475+
CurrentSize = NewSize;
463476
}
464477
Allocator->deallocate(P, Origin);
465478
}

0 commit comments

Comments
 (0)