Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/report.cpp
35292 views
//===-- report.cpp ----------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "report.h"910#include "atomic_helpers.h"11#include "string_utils.h"1213#include <stdarg.h>1415namespace scudo {1617class ScopedErrorReport {18public:19ScopedErrorReport() : Message() { Message.append("Scudo ERROR: "); }20void append(const char *Format, ...) {21va_list Args;22va_start(Args, Format);23Message.vappend(Format, Args);24va_end(Args);25}26NORETURN ~ScopedErrorReport() { reportRawError(Message.data()); }2728private:29ScopedString Message;30};3132inline void NORETURN trap() { __builtin_trap(); }3334// This could potentially be called recursively if a CHECK fails in the reports.35void NORETURN reportCheckFailed(const char *File, int Line,36const char *Condition, u64 Value1, u64 Value2) {37static atomic_u32 NumberOfCalls;38if (atomic_fetch_add(&NumberOfCalls, 1, memory_order_relaxed) > 2) {39// TODO(kostyak): maybe sleep here?40trap();41}42ScopedErrorReport Report;43Report.append("CHECK failed @ %s:%d %s ((u64)op1=%llu, (u64)op2=%llu)\n",44File, Line, Condition, Value1, Value2);45}4647// Generic string fatal error message.48void NORETURN reportError(const char *Message) {49ScopedErrorReport Report;50Report.append("%s\n", Message);51}5253// Generic fatal error message without ScopedString.54void NORETURN reportRawError(const char *Message) {55outputRaw(Message);56setAbortMessage(Message);57die();58}5960void NORETURN reportInvalidFlag(const char *FlagType, const char *Value) {61ScopedErrorReport Report;62Report.append("invalid value for %s option: '%s'\n", FlagType, Value);63}6465// The checksum of a chunk header is invalid. This could be caused by an66// {over,under}write of the header, a pointer that is not an actual chunk.67void NORETURN reportHeaderCorruption(void *Ptr) {68ScopedErrorReport Report;69Report.append("corrupted chunk header at address %p\n", Ptr);70}7172// The allocator was compiled with parameters that conflict with field size73// requirements.74void NORETURN reportSanityCheckError(const char *Field) {75ScopedErrorReport Report;76Report.append("maximum possible %s doesn't fit in header\n", Field);77}7879// We enforce a maximum alignment, to keep fields smaller and generally prevent80// integer overflows, or unexpected corner cases.81void NORETURN reportAlignmentTooBig(uptr Alignment, uptr MaxAlignment) {82ScopedErrorReport Report;83Report.append("invalid allocation alignment: %zu exceeds maximum supported "84"alignment of %zu\n",85Alignment, MaxAlignment);86}8788// See above, we also enforce a maximum size.89void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,90uptr MaxSize) {91ScopedErrorReport Report;92Report.append("requested allocation size %zu (%zu after adjustments) exceeds "93"maximum supported size of %zu\n",94UserSize, TotalSize, MaxSize);95}9697void NORETURN reportOutOfBatchClass() {98ScopedErrorReport Report;99Report.append("BatchClass region is used up, can't hold any free block\n");100}101102void NORETURN reportOutOfMemory(uptr RequestedSize) {103ScopedErrorReport Report;104Report.append("out of memory trying to allocate %zu bytes\n", RequestedSize);105}106107static const char *stringifyAction(AllocatorAction Action) {108switch (Action) {109case AllocatorAction::Recycling:110return "recycling";111case AllocatorAction::Deallocating:112return "deallocating";113case AllocatorAction::Reallocating:114return "reallocating";115case AllocatorAction::Sizing:116return "sizing";117}118return "<invalid action>";119}120121// The chunk is not in a state congruent with the operation we want to perform.122// This is usually the case with a double-free, a realloc of a freed pointer.123void NORETURN reportInvalidChunkState(AllocatorAction Action, void *Ptr) {124ScopedErrorReport Report;125Report.append("invalid chunk state when %s address %p\n",126stringifyAction(Action), Ptr);127}128129void NORETURN reportMisalignedPointer(AllocatorAction Action, void *Ptr) {130ScopedErrorReport Report;131Report.append("misaligned pointer when %s address %p\n",132stringifyAction(Action), Ptr);133}134135// The deallocation function used is at odds with the one used to allocate the136// chunk (eg: new[]/delete or malloc/delete, and so on).137void NORETURN reportDeallocTypeMismatch(AllocatorAction Action, void *Ptr,138u8 TypeA, u8 TypeB) {139ScopedErrorReport Report;140Report.append("allocation type mismatch when %s address %p (%d vs %d)\n",141stringifyAction(Action), Ptr, TypeA, TypeB);142}143144// The size specified to the delete operator does not match the one that was145// passed to new when allocating the chunk.146void NORETURN reportDeleteSizeMismatch(void *Ptr, uptr Size,147uptr ExpectedSize) {148ScopedErrorReport Report;149Report.append(150"invalid sized delete when deallocating address %p (%zu vs %zu)\n", Ptr,151Size, ExpectedSize);152}153154void NORETURN reportAlignmentNotPowerOfTwo(uptr Alignment) {155ScopedErrorReport Report;156Report.append(157"invalid allocation alignment: %zu, alignment must be a power of two\n",158Alignment);159}160161void NORETURN reportCallocOverflow(uptr Count, uptr Size) {162ScopedErrorReport Report;163Report.append("calloc parameters overflow: count * size (%zu * %zu) cannot "164"be represented with type size_t\n",165Count, Size);166}167168void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment) {169ScopedErrorReport Report;170Report.append(171"invalid alignment requested in posix_memalign: %zu, alignment must be a "172"power of two and a multiple of sizeof(void *) == %zu\n",173Alignment, sizeof(void *));174}175176void NORETURN reportPvallocOverflow(uptr Size) {177ScopedErrorReport Report;178Report.append("pvalloc parameters overflow: size %zu rounded up to system "179"page size %zu cannot be represented in type size_t\n",180Size, getPageSizeCached());181}182183void NORETURN reportInvalidAlignedAllocAlignment(uptr Alignment, uptr Size) {184ScopedErrorReport Report;185Report.append("invalid alignment requested in aligned_alloc: %zu, alignment "186"must be a power of two and the requested size %zu must be a "187"multiple of alignment\n",188Alignment, Size);189}190191} // namespace scudo192193194