Assertions.cpp (2719B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "mozilla/Assertions.h" 7 #include "mozilla/Atomics.h" 8 #include "mozilla/Sprintf.h" 9 10 #include <stdarg.h> 11 #include <string.h> 12 #include "fmt/format.h" 13 14 MOZ_BEGIN_EXTERN_C 15 16 /* 17 * The crash reason is defined as a global variable here rather than in the 18 * crash reporter itself to make it available to all code, even libraries like 19 * JS that don't link with the crash reporter directly. This value will only 20 * be consumed if the crash reporter is used by the target application. 21 */ 22 MFBT_DATA const char* gMozCrashReason = nullptr; 23 24 static char sPrintfCrashReason[sPrintfCrashReasonSize] = {}; 25 26 // Accesses to this atomic are not included in web replay recordings, so that 27 // if we crash in an area where recorded events are not allowed the true reason 28 // for the crash is not obscured by a record/replay error. 29 static mozilla::Atomic<bool, mozilla::SequentiallyConsistent> sCrashing(false); 30 31 MFBT_API MOZ_COLD MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(1, 2) const 32 char* MOZ_CrashPrintf(const char* aFormat, ...) { 33 if (!sCrashing.compareExchange(false, true)) { 34 // In the unlikely event of a race condition, skip 35 // setting the crash reason and just crash safely. 36 MOZ_RELEASE_ASSERT(false); 37 } 38 va_list aArgs; 39 va_start(aArgs, aFormat); 40 int ret = VsprintfLiteral(sPrintfCrashReason, aFormat, aArgs); 41 va_end(aArgs); 42 MOZ_RELEASE_ASSERT( 43 ret >= 0 && size_t(ret) < sPrintfCrashReasonSize, 44 "Could not write the explanation string to the supplied buffer!"); 45 return sPrintfCrashReason; 46 } 47 48 MOZ_END_EXTERN_C 49 50 #ifdef __cplusplus 51 52 namespace mozilla::detail { 53 54 template <typename... Args> 55 const char* CrashFmtImpl(const char* format, Args&&... args) { 56 if (!sCrashing.compareExchange(false, true)) { 57 // In the unlikely event of a race condition, skip 58 // setting the crash reason and just crash safely. 59 MOZ_RELEASE_ASSERT(false); 60 } 61 62 // This will silently truncate the string if it's too long. 63 auto result = 64 fmt::vformat_to_n(sPrintfCrashReason, sPrintfCrashReasonSize - 1, format, 65 fmt::make_format_args(args...)); 66 sPrintfCrashReason[result.size] = '\0'; 67 68 return sPrintfCrashReason; 69 } 70 71 } // namespace mozilla::detail 72 73 #endif 74 75 [[noreturn]] MFBT_API MOZ_COLD void mozilla::detail::InvalidArrayIndex_CRASH( 76 size_t aIndex, size_t aLength) { 77 MOZ_CRASH_UNSAFE_PRINTF("ElementAt(aIndex = %zu, aLength = %zu)", aIndex, 78 aLength); 79 }