mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-06 09:28:50 +00:00

This revision is a part of a series of patches extending AddressSanitizer C++ container overflow detection capabilities by adding annotations, similar to those existing in std::vector, to std::string and std::deque collections. These changes allow ASan to detect cases when the instrumented program accesses memory which is internally allocated by the collection but is still not in-use (accesses before or after the stored elements for std::deque, or between the size and capacity bounds for std::string). The motivation for the research and those changes was a bug, found by Trail of Bits, in a real code where an out-of-bounds read could happen as two strings were compared via a std::equals function that took iter1_begin, iter1_end, iter2_begin iterators (with a custom comparison function). When object iter1 was longer than iter2, read out-of-bounds on iter2 could happen. Container sanitization would detect it. This revision adds a new compiler-rt ASan sanitization API function sanitizer_annotate_double_ended_contiguous_container necessary to sanitize/annotate double ended contiguous containers. Note that that function annotates a single contiguous memory buffer (for example the std::deque's internal chunk). Such containers have the beginning of allocated memory block, beginning of the container in-use data, end of the container's in-use data and the end of the allocated memory block. This also adds a new API function to verify if a double ended contiguous container is correctly annotated (__sanitizer_verify_double_ended_contiguous_container). Since we do not modify the ASan's shadow memory encoding values, the capability of sanitizing/annotating a prefix of the internal contiguous memory buffer is limited – up to SHADOW_GRANULARITY-1 bytes may not be poisoned before the container's in-use data. This can cause false negatives (situations when ASan will not detect memory corruption in those areas). On the other hand, API function interfaces are designed to work even if this caveat would not exist. Therefore implementations using those functions will poison every byte correctly, if only ASan (and compiler-rt) is extended to support it. In other words, if ASan was modified to support annotating/poisoning of objects lying on addresses unaligned to SHADOW_GRANULARITY (so e.g. prefixes of those blocks), which would require changing its shadow memory encoding, this would not require any changes in the libcxx std::string/deque code which is added in further commits of this patch series. If you have any questions, please email: advenam.tacet@trailofbits.com disconnect3d@trailofbits.com Differential Revision: https://reviews.llvm.org/D132090
104 lines
4.8 KiB
C++
104 lines
4.8 KiB
C++
//===-- asan_report.h -------------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
|
//
|
|
// ASan-private header for error reporting functions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef ASAN_REPORT_H
|
|
#define ASAN_REPORT_H
|
|
|
|
#include "asan_allocator.h"
|
|
#include "asan_internal.h"
|
|
#include "asan_thread.h"
|
|
|
|
namespace __asan {
|
|
|
|
struct StackVarDescr {
|
|
uptr beg;
|
|
uptr size;
|
|
const char *name_pos;
|
|
uptr name_len;
|
|
uptr line;
|
|
};
|
|
|
|
// Returns the number of globals close to the provided address and copies
|
|
// them to "globals" array.
|
|
int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
|
|
int max_globals);
|
|
|
|
const char *MaybeDemangleGlobalName(const char *name);
|
|
void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g);
|
|
void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g);
|
|
|
|
void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
|
|
bool in_shadow, const char *after = "\n");
|
|
|
|
// The following functions prints address description depending
|
|
// on the memory type (shadow/heap/stack/global).
|
|
bool ParseFrameDescription(const char *frame_descr,
|
|
InternalMmapVector<StackVarDescr> *vars);
|
|
|
|
// Different kinds of error reports.
|
|
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
|
uptr access_size, u32 exp, bool fatal);
|
|
void ReportDeadlySignal(const SignalContext &sig);
|
|
void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
|
|
uptr delete_alignment,
|
|
BufferedStackTrace *free_stack);
|
|
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
|
|
void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
|
|
void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
|
AllocType alloc_type,
|
|
AllocType dealloc_type);
|
|
void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
|
|
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
|
BufferedStackTrace *stack);
|
|
void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
|
|
void ReportReallocArrayOverflow(uptr count, uptr size,
|
|
BufferedStackTrace *stack);
|
|
void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
|
|
void ReportInvalidAllocationAlignment(uptr alignment,
|
|
BufferedStackTrace *stack);
|
|
void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
|
|
BufferedStackTrace *stack);
|
|
void ReportInvalidPosixMemalignAlignment(uptr alignment,
|
|
BufferedStackTrace *stack);
|
|
void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
|
|
BufferedStackTrace *stack);
|
|
void ReportRssLimitExceeded(BufferedStackTrace *stack);
|
|
void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack);
|
|
void ReportStringFunctionMemoryRangesOverlap(const char *function,
|
|
const char *offset1, uptr length1,
|
|
const char *offset2, uptr length2,
|
|
BufferedStackTrace *stack);
|
|
void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
|
BufferedStackTrace *stack);
|
|
void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
|
uptr old_mid, uptr new_mid,
|
|
BufferedStackTrace *stack);
|
|
void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
|
|
uptr storage_beg, uptr storage_end, uptr old_container_beg,
|
|
uptr old_container_end, uptr new_container_beg, uptr new_container_end,
|
|
BufferedStackTrace *stack);
|
|
|
|
void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
|
const __asan_global *g2, u32 stack_id2);
|
|
|
|
// Mac-specific errors and warnings.
|
|
void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
|
|
const char *zone_name,
|
|
BufferedStackTrace *stack);
|
|
void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
|
|
const char *zone_name,
|
|
BufferedStackTrace *stack);
|
|
|
|
} // namespace __asan
|
|
#endif // ASAN_REPORT_H
|