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 @@ -1166,7 +1166,8 @@ void storeEndMarker(uptr End, uptr Size, uptr BlockEnd) { DCHECK_EQ(BlockEnd, untagPointer(BlockEnd)); uptr UntaggedEnd = untagPointer(End); - if (UntaggedEnd != BlockEnd) { + uptr UntaggedBlockEnd = untagPointer(BlockEnd); + if (UntaggedEnd != UntaggedBlockEnd) { storeTag(UntaggedEnd); if (Size == 0) *reinterpret_cast(UntaggedEnd) = extractTag(End); diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -679,3 +679,23 @@ Allocator->setOption(scudo::Option::ThreadDisableMemInit, 0); } + +SCUDO_TYPED_TEST(ScudoCombinedTest, ReallocateInPlaceStress) { + auto *Allocator = this->Allocator.get(); + + // Regression test: make realloc-in-place happen at the very right end of a + // mapped region. + constexpr int nPtrs = 10000; + for (int i = 1; i < 32; ++i) { + scudo::uptr Size = 16 * i - 1; + std::vector Ptrs; + for (int i = 0; i < nPtrs; ++i) { + void *P = Allocator->allocate(Size, Origin); + P = Allocator->reallocate(P, Size + 1); + Ptrs.push_back(P); + } + + for (int i = 0; i < nPtrs; ++i) + Allocator->deallocate(Ptrs[i], Origin); + } +}