diff --git a/xpcom/threads/ThreadStackHelper.cpp b/xpcom/threads/ThreadStackHelper.cpp index cf4e7843ef59..ddc0afd43d43 100644 --- a/xpcom/threads/ThreadStackHelper.cpp +++ b/xpcom/threads/ThreadStackHelper.cpp @@ -138,7 +138,8 @@ ThreadStackHelper::GetStacksInternal(Stack* aStack, ScopedSetPtr nativeStackPtr(mNativeStackToFill, aNativeStack); #endif - char nameBuffer[1000] = {0}; + Array runnableName; + runnableName[0] = '\0'; auto callback = [&, this] (void** aPCs, size_t aCount, bool aIsMainThread) { // NOTE: We cannot allocate any memory in this callback, as the target // thread is suspended, so we first copy it into a stack-allocated buffer, @@ -148,10 +149,8 @@ ThreadStackHelper::GetStacksInternal(Stack* aStack, // Currently we only store the names of runnables which are running on the // main thread, so we only want to read sMainThreadRunnableName and copy its // value in the case that we are currently suspending the main thread. - if (aIsMainThread && nsThread::sMainThreadRunnableName) { - strncpy(nameBuffer, nsThread::sMainThreadRunnableName, sizeof(nameBuffer)); - // Make sure the string is null-terminated. - nameBuffer[sizeof(nameBuffer) - 1] = '\0'; + if (aIsMainThread) { + runnableName = nsThread::sMainThreadRunnableName; } #ifdef MOZ_THREADSTACKHELPER_PSEUDO @@ -176,10 +175,11 @@ ThreadStackHelper::GetStacksInternal(Stack* aStack, /* aSampleNative = */ !!aNativeStack); } - // Copy the name buffer allocation into the output string. - if (nameBuffer[0] != 0) { - aRunnableName = nameBuffer; - } + // Copy the name buffer allocation into the output string. We explicitly set + // the last byte to null in case we read in some corrupted data without a null + // terminator. + runnableName[nsThread::kRunnableNameBufSize - 1] = '\0'; + aRunnableName.AssignASCII(runnableName.cbegin()); #endif } diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index 202025c5ca35..0f07a2c6047d 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -99,7 +99,7 @@ static LazyLogModule sThreadLog("nsThread"); NS_DECL_CI_INTERFACE_GETTER(nsThread) -const char* nsThread::sMainThreadRunnableName = nullptr; +Array nsThread::sMainThreadRunnableName; //----------------------------------------------------------------------------- // Because we do not have our own nsIFactory, we have to implement nsIClassInfo @@ -1422,15 +1422,24 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult) // If we're on the main thread, we want to record our current runnable's // name in a static so that BHR can record it. - const char* restoreRunnableName = nullptr; + Array restoreRunnableName; + restoreRunnableName[0] = '\0'; auto clear = MakeScopeExit([&] { if (MAIN_THREAD == mIsMainThread) { + MOZ_ASSERT(NS_IsMainThread()); sMainThreadRunnableName = restoreRunnableName; } }); if (MAIN_THREAD == mIsMainThread) { + MOZ_ASSERT(NS_IsMainThread()); restoreRunnableName = sMainThreadRunnableName; - sMainThreadRunnableName = name.get(); + + // Copy the name into sMainThreadRunnableName's buffer, and append a + // terminating null. + uint32_t length = std::min((uint32_t) kRunnableNameBufSize - 1, + (uint32_t) name.Length()); + memcpy(sMainThreadRunnableName.begin(), name.BeginReading(), length); + sMainThreadRunnableName[length] = '\0'; } #endif diff --git a/xpcom/threads/nsThread.h b/xpcom/threads/nsThread.h index 5bbe8d8d78a7..9330df346bb5 100644 --- a/xpcom/threads/nsThread.h +++ b/xpcom/threads/nsThread.h @@ -21,6 +21,7 @@ #include "nsAutoPtr.h" #include "mozilla/AlreadyAddRefed.h" #include "mozilla/UniquePtr.h" +#include "mozilla/Array.h" namespace mozilla { class CycleCollectedJSContext; @@ -93,7 +94,8 @@ public: static bool SaveMemoryReportNearOOM(ShouldSaveMemoryReport aShouldSave); #endif - static const char* sMainThreadRunnableName; + static const uint32_t kRunnableNameBufSize = 1000; + static mozilla::Array sMainThreadRunnableName; private: void DoMainThreadSpecificProcessing(bool aReallyWait);