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 @@ -694,7 +694,7 @@ // function. This can be called with a null buffer or zero size for buffer // sizing purposes. uptr getStats(char *Buffer, uptr Size) { - ScopedString Str(1024); + ScopedString Str; disable(); const uptr Length = getStats(&Str) + 1; enable(); @@ -708,7 +708,7 @@ } void printStats() { - ScopedString Str(1024); + ScopedString Str; disable(); getStats(&Str); enable(); diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -341,7 +341,7 @@ if (UNLIKELY(RegionBase + MappedUser + MapSize > RegionSize)) { if (!Region->Exhausted) { Region->Exhausted = true; - ScopedString Str(1024); + ScopedString Str; getStats(&Str); Str.append( "Scudo OOM: The process has exhausted %zuM for size class %zu.\n", diff --git a/compiler-rt/lib/scudo/standalone/size_class_map.h b/compiler-rt/lib/scudo/standalone/size_class_map.h --- a/compiler-rt/lib/scudo/standalone/size_class_map.h +++ b/compiler-rt/lib/scudo/standalone/size_class_map.h @@ -309,7 +309,7 @@ typedef FixedSizeClassMap SvelteSizeClassMap; template inline void printMap() { - ScopedString Buffer(1024); + ScopedString Buffer; uptr PrevS = 0; uptr TotalCached = 0; for (uptr I = 0; I < SCMap::NumClasses; I++) { diff --git a/compiler-rt/lib/scudo/standalone/string_utils.h b/compiler-rt/lib/scudo/standalone/string_utils.h --- a/compiler-rt/lib/scudo/standalone/string_utils.h +++ b/compiler-rt/lib/scudo/standalone/string_utils.h @@ -18,7 +18,7 @@ class ScopedString { public: - explicit ScopedString(uptr MaxLength) : String(MaxLength), Length(0) { + explicit ScopedString(uptr InitialSize = 0) : String(InitialSize) { String[0] = '\0'; } uptr length() { return Length; } @@ -33,7 +33,7 @@ private: Vector String; - uptr Length; + uptr Length = 0; }; int formatString(char *Buffer, uptr BufferLength, const char *Format, ...); diff --git a/compiler-rt/lib/scudo/standalone/string_utils.cpp b/compiler-rt/lib/scudo/standalone/string_utils.cpp --- a/compiler-rt/lib/scudo/standalone/string_utils.cpp +++ b/compiler-rt/lib/scudo/standalone/string_utils.cpp @@ -219,7 +219,7 @@ } void ScopedString::append(const char *Format, va_list Args) { - DCHECK_LT(Length, String.size()); + RAW_CHECK(Length <= String.size()); va_list ArgsCopy; va_copy(ArgsCopy, Args); // formatString doesn't currently support a null buffer or zero buffer length, @@ -228,11 +228,13 @@ char C[1]; const uptr AdditionalLength = static_cast(formatString(C, sizeof(C), Format, Args)) + 1; - String.resize(Length + AdditionalLength); - formatString(String.data() + Length, AdditionalLength, Format, ArgsCopy); + // append will silently fail if the underlying Vector can't grow. + if (String.resize(Length + AdditionalLength)) { + formatString(String.data() + Length, AdditionalLength, Format, ArgsCopy); + Length = strlen(String.data()); + RAW_CHECK(Length < String.size()); + } va_end(ArgsCopy); - Length = strlen(String.data()); - CHECK_LT(Length, String.size()); } FORMAT(2, 3) @@ -247,7 +249,7 @@ void Printf(const char *Format, ...) { va_list Args; va_start(Args, Format); - ScopedString Msg(1024); + ScopedString Msg; Msg.append(Format, Args); outputRaw(Msg.data()); va_end(Args); diff --git a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp @@ -132,7 +132,7 @@ } Cache.destroy(nullptr); Allocator->releaseToOS(); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Allocator->getStats(&Str); Str.output(); } @@ -178,7 +178,7 @@ } Cache.destroy(nullptr); Allocator.releaseToOS(); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Allocator.getStats(&Str); Str.output(); EXPECT_EQ(AllocationFailed, true); @@ -216,7 +216,7 @@ } Cache.destroy(nullptr); Allocator->releaseToOS(); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Allocator->getStats(&Str); Str.output(); } @@ -263,7 +263,7 @@ for (auto &T : Threads) T.join(); Allocator->releaseToOS(); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Allocator->getStats(&Str); Str.output(); } diff --git a/compiler-rt/lib/scudo/standalone/tests/quarantine_test.cpp b/compiler-rt/lib/scudo/standalone/tests/quarantine_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/quarantine_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/quarantine_test.cpp @@ -214,7 +214,7 @@ Quarantine.drainAndRecycle(&Cache, Cb); EXPECT_EQ(Cache.getSize(), 0UL); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Quarantine.getStats(&Str); Str.output(); } @@ -246,7 +246,7 @@ for (scudo::uptr I = 0; I < NumberOfThreads; I++) pthread_join(T[I].Thread, 0); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; Quarantine.getStats(&Str); Str.output(); diff --git a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp @@ -64,7 +64,7 @@ L->deallocate(scudo::Options{}, V.back()); V.pop_back(); } - scudo::ScopedString Str(1024); + scudo::ScopedString Str; L->getStats(&Str); Str.output(); L->unmapTestOnly(); @@ -122,7 +122,7 @@ } } } - scudo::ScopedString Str(1024); + scudo::ScopedString Str; L->getStats(&Str); Str.output(); L->unmapTestOnly(); @@ -146,7 +146,7 @@ L->deallocate(scudo::Options{}, V.back()); V.pop_back(); } - scudo::ScopedString Str(1024); + scudo::ScopedString Str; L->getStats(&Str); Str.output(); L->unmapTestOnly(); @@ -217,7 +217,7 @@ } for (auto &T : Threads) T.join(); - scudo::ScopedString Str(1024); + scudo::ScopedString Str; L->getStats(&Str); Str.output(); L->unmapTestOnly(); diff --git a/compiler-rt/lib/scudo/standalone/vector.h b/compiler-rt/lib/scudo/standalone/vector.h --- a/compiler-rt/lib/scudo/standalone/vector.h +++ b/compiler-rt/lib/scudo/standalone/vector.h @@ -17,16 +17,15 @@ // A low-level vector based on map. May incur a significant memory overhead for // small vectors. The current implementation supports only POD types. -template class VectorNoCtor { +template class VectorNoCtor { public: - void init(uptr InitialCapacity) { - CapacityBytes = 0; - Size = 0; - Data = nullptr; + void init(uptr InitialCapacity = 0) { + Data = reinterpret_cast(&LocalData[0]); + CapacityBytes = sizeof(LocalData); reserve(InitialCapacity); } void destroy() { - if (Data) + if (Data != reinterpret_cast(&LocalData[0])) unmap(Data, CapacityBytes); } T &operator[](uptr I) { @@ -40,6 +39,9 @@ void push_back(const T &Element) { DCHECK_LE(Size, capacity()); if (Size == capacity()) { + // For now, push_back will silently fail if the Vector can't grow. + if (!CanGrow) + return; const uptr NewCapacity = roundUpToPowerOfTwo(Size + 1); reallocate(NewCapacity); } @@ -57,17 +59,23 @@ const T *data() const { return Data; } T *data() { return Data; } uptr capacity() const { return CapacityBytes / sizeof(T); } - void reserve(uptr NewSize) { + bool reserve(uptr NewSize) { // Never downsize internal buffer. - if (NewSize > capacity()) + if (NewSize > capacity()) { + if (!CanGrow) + return false; reallocate(NewSize); + } + return true; } - void resize(uptr NewSize) { + bool resize(uptr NewSize) { if (NewSize > Size) { - reserve(NewSize); + if (!reserve(NewSize)) + return false; memset(&Data[Size], 0, sizeof(T) * (NewSize - Size)); } Size = NewSize; + return true; } void clear() { Size = 0; } @@ -82,26 +90,25 @@ void reallocate(uptr NewCapacity) { DCHECK_GT(NewCapacity, 0); DCHECK_LE(Size, NewCapacity); - const uptr NewCapacityBytes = - roundUpTo(NewCapacity * sizeof(T), getPageSizeCached()); + NewCapacity = roundUpTo(NewCapacity * sizeof(T), getPageSizeCached()); T *NewData = - reinterpret_cast(map(nullptr, NewCapacityBytes, "scudo:vector")); - if (Data) { - memcpy(NewData, Data, Size * sizeof(T)); + reinterpret_cast(map(nullptr, NewCapacity, "scudo:vector")); + memcpy(NewData, Data, Size * sizeof(T)); + if (Data != reinterpret_cast(&LocalData[0])) unmap(Data, CapacityBytes); - } Data = NewData; - CapacityBytes = NewCapacityBytes; + CapacityBytes = NewCapacity; } - T *Data; - uptr CapacityBytes; - uptr Size; + T *Data = nullptr; + u8 LocalData[256] = {}; + uptr CapacityBytes = 0; + uptr Size = 0; }; template class Vector : public VectorNoCtor { public: - Vector() { VectorNoCtor::init(1); } + Vector() { VectorNoCtor::init(); } explicit Vector(uptr Count) { VectorNoCtor::init(Count); this->resize(Count);