Index: include/sanitizer/asan_interface.h =================================================================== --- include/sanitizer/asan_interface.h +++ include/sanitizer/asan_interface.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file is a part of AddressSanitizer. +// This file is a part of AddressSanitizer (ASan). // // Public interface header. //===----------------------------------------------------------------------===// @@ -18,28 +18,54 @@ #ifdef __cplusplus extern "C" { #endif - // Marks memory region [addr, addr+size) as unaddressable. - // This memory must be previously allocated by the user program. Accessing - // addresses in this region from instrumented code is forbidden until - // this region is unpoisoned. This function is not guaranteed to poison - // the whole region - it may poison only subregion of [addr, addr+size) due - // to ASan alignment restrictions. - // Method is NOT thread-safe in the sense that no two threads can - // (un)poison memory in the same memory region simultaneously. - void __asan_poison_memory_region(void const volatile *addr, size_t size); - // Marks memory region [addr, addr+size) as addressable. - // This memory must be previously allocated by the user program. Accessing - // addresses in this region is allowed until this region is poisoned again. - // This function may unpoison a superregion of [addr, addr+size) due to - // ASan alignment restrictions. - // Method is NOT thread-safe in the sense that no two threads can - // (un)poison memory in the same memory region simultaneously. - void __asan_unpoison_memory_region(void const volatile *addr, size_t size); - -// User code should use macros instead of functions. +/// Marks a memory region ([addr, addr+size)) as unaddressable. +/// +/// This memory must be previously allocated by your program. Instrumented +/// code is forbidden from accessing addresses in this region until it is +/// unpoisoned. This function is not guaranteed to poison the entire region - +/// it could poison only a subregion of [addr, addr+size) due to ASan +/// alignment restrictions. +/// +/// @note This function is not thread-safe because no two threads can poison or +/// unpoison memory in the same memory region simultaneously. +/// +/// @param addr Start of memory region. +/// @param size Size of memory region. +void __asan_poison_memory_region(void const volatile *addr, size_t size); + +/// Marks a memory region ([addr, addr+size)) as addressable. +/// +/// This memory must be previously allocated by your program. Accessing +/// addresses in this region is allowed until this region is poisoned again. +/// This function could unpoison a super-region of [addr, addr+size) due +/// to ASan alignment restrictions. +/// +/// @note This function is not thread-safe because no two threads can +/// poison or unpoison memory in the same memory region simultaneously. +/// +/// @param addr Start of memory region. +/// @param size Size of memory region. +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); + +// Macros provided for convenience. #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +/// Marks a memory region as unaddressable. +/// +/// @note Macro provided for convenience; defined as a no-op if ASan is not +/// enabled. +/// +/// @param addr Start of memory region. +/// @param size Size of memory region. #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) + +/// Marks a memory region as addressable. +/// +/// @note Macro provided for convenience; defined as a no-op if ASan is not +/// enabled. +/// +/// @param addr Start of memory region. +/// @param size Size of memory region. #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ __asan_unpoison_memory_region((addr), (size)) #else @@ -49,103 +75,245 @@ ((void)(addr), (void)(size)) #endif - // Returns 1 if addr is poisoned (i.e. 1-byte read/write access to this - // address will result in error report from AddressSanitizer). - // Otherwise returns 0. - int __asan_address_is_poisoned(void const volatile *addr); - - // If at least one byte in [beg, beg+size) is poisoned, return the address - // of the first such byte. Otherwise return 0. - void *__asan_region_is_poisoned(void *beg, size_t size); - - // Print the description of addr (useful when debugging in gdb). - void __asan_describe_address(void *addr); - - // Useful for calling from a debugger to get information about an ASan error. - // Returns 1 if an error has been (or is being) reported, otherwise returns 0. - int __asan_report_present(void); - - // Useful for calling from a debugger to get information about an ASan error. - // If an error has been (or is being) reported, the following functions return - // the pc, bp, sp, address, access type (0 = read, 1 = write), access size and - // bug description (e.g. "heap-use-after-free"). Otherwise they return 0. - void *__asan_get_report_pc(void); - void *__asan_get_report_bp(void); - void *__asan_get_report_sp(void); - void *__asan_get_report_address(void); - int __asan_get_report_access_type(void); - size_t __asan_get_report_access_size(void); - const char *__asan_get_report_description(void); - - // Useful for calling from the debugger to get information about a pointer. - // Returns the category of the given pointer as a constant string. - // Possible return values are "global", "stack", "stack-fake", "heap", - // "heap-invalid", "shadow-low", "shadow-gap", "shadow-high", "unknown". - // If global or stack, tries to also return the variable name, address and - // size. If heap, tries to return the chunk address and size. 'name' should - // point to an allocated buffer of size 'name_size'. - const char *__asan_locate_address(void *addr, char *name, size_t name_size, - void **region_address, size_t *region_size); - - // Useful for calling from the debugger to get the allocation stack trace - // and thread ID for a heap address. Stores up to 'size' frames into 'trace', - // returns the number of stored frames or 0 on error. - size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, - int *thread_id); - - // Useful for calling from the debugger to get the free stack trace - // and thread ID for a heap address. Stores up to 'size' frames into 'trace', - // returns the number of stored frames or 0 on error. - size_t __asan_get_free_stack(void *addr, void **trace, size_t size, - int *thread_id); - - // Useful for calling from the debugger to get the current shadow memory - // mapping. - void __asan_get_shadow_mapping(size_t *shadow_scale, size_t *shadow_offset); - - // This is an internal function that is called to report an error. - // However it is still a part of the interface because users may want to - // set a breakpoint on this function in a debugger. - void __asan_report_error(void *pc, void *bp, void *sp, - void *addr, int is_write, size_t access_size); - - // Deprecated. Call __sanitizer_set_death_callback instead. - void __asan_set_death_callback(void (*callback)(void)); - - void __asan_set_error_report_callback(void (*callback)(const char*)); - - // User may provide function that would be called right when ASan detects - // an error. This can be used to notice cases when ASan detects an error, but - // the program crashes before ASan report is printed. +/// Checks if an address is poisoned. +/// +/// Returns 1 if addr is poisoned (that is, 1-byte read/write +/// access to this address would result in an error report from ASan). +/// Otherwise returns 0. +/// +/// @param addr Address to check. +/// +/// @retval 1 Address is poisoned. +/// @retval 0 Address is not poisoned. +int __asan_address_is_poisoned(void const volatile *addr); + +/// Checks if a region is poisoned. +/// +/// If at least one byte in [beg, beg+size) is poisoned, returns the +/// address of the first such byte. Otherwise returns 0. +/// +/// @param beg Start of memory region. +/// @param size Start of memory region. +/// @returns Address of first poisoned byte. +void *__asan_region_is_poisoned(void *beg, size_t size); + +/// Describes an address (useful for calling from the debugger). +/// +/// Prints the description of addr. +/// +/// @param addr Address to describe. +void __asan_describe_address(void *addr); + +/// Checks if an error has been or is being reported (useful for calling from +/// the debugger to get information about an ASan error). +/// +/// Returns 1 if an error has been (or is being) reported. Otherwise returns 0. +/// +/// @returns 1 if an error has been (or is being) reported. Otherwise returns +/// 0. +int __asan_report_present(void); + +/// Gets the PC (program counter) register value of an ASan error (useful for +/// calling from the debugger). +/// +/// Returns PC if an error has been (or is being) reported. +/// Otherwise returns 0. +/// +/// @returns PC value. +void *__asan_get_report_pc(void); + +/// Gets the BP (base pointer) register value of an ASan error (useful for +/// calling from the debugger). +/// +/// Returns BP if an error has been (or is being) reported. +/// Otherwise returns 0. +/// +/// @returns BP value. +void *__asan_get_report_bp(void); + +/// Gets the SP (stack pointer) register value of an ASan error (useful for +/// calling from the debugger). +/// +/// If an error has been (or is being) reported, returns SP. +/// Otherwise returns 0. +/// +/// @returns SP value. +void *__asan_get_report_sp(void); + +/// Gets the address of the report buffer of an ASan error (useful for calling +/// from the debugger). +/// +/// Returns the address of the report buffer if an error has been (or is being) +/// reported. Otherwise returns 0. +/// +/// @returns Address of report buffer. +void *__asan_get_report_address(void); + +/// Gets access type of an ASan error (useful for calling from the debugger). +/// +/// Returns access type (read or write) if an error has been (or is being) +/// reported. Otherwise returns 0. +/// +/// @returns Access type (0 = read, 1 = write). +int __asan_get_report_access_type(void); + +/// Gets access size of an ASan error (useful for calling from the debugger). +/// +/// Returns access size if an error has been (or is being) reported. Otherwise +/// returns 0. +/// +/// @returns Access size in bytes. +size_t __asan_get_report_access_size(void); + +/// Gets the bug description of an ASan error (useful for calling from a +/// debugger). +/// +/// @returns Returns a bug description if an error has been (or is being) +/// reported - for example, "heap-use-after-free". Otherwise returns an empty +/// string. +const char *__asan_get_report_description(void); + +/// Gets information about a pointer (useful for calling from the debugger). +/// +/// Returns the category of the given pointer as a constant string. +/// Possible return values are global, stack, stack-fake, +/// heap, heap-invalid, shadow-low, shadow-gap, +/// shadow-high, and unknown. +/// +/// If the return value is global or stack, tries to also return +/// the variable name, address, and size. If the return value is heap, +/// tries to return the chunk address and size. name should point +/// to an allocated buffer of size name_size. +/// +/// @param addr Address to locate. +/// @param name Buffer to store the variable's name. +/// @param name_size Size in bytes of the variable's name buffer. +/// @param region_address [out] Address of the region. +/// @param region_size [out] Size of the region in bytes. +/// +/// @returns Returns the category of the given pointer as a constant string. +const char *__asan_locate_address(void *addr, char *name, size_t name_size, + void **region_address, size_t *region_size); + +/// Gets the allocation stack trace and thread ID for a heap address (useful +/// for calling from the debugger). +/// +/// Stores up to size frames in trace. Returns +/// the number of stored frames or 0 on error. +/// +/// @param addr A heap address. +/// @param trace A buffer to store the stack trace. +/// @param size Size in bytes of the trace buffer. +/// @param thread_id [out] The thread ID of the address. +/// +/// @returns Returns the number of stored frames or 0 on error. +size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, + int *thread_id); + +/// Gets the free stack trace and thread ID for a heap address (useful for +/// calling from the debugger). +/// +/// Stores up to size frames in trace. Returns +/// the number of stored frames or 0 on error. +/// +/// @param addr A heap address. +/// @param trace A buffer to store the stack trace. +/// @param size Size in bytes of the trace buffer. +/// @param thread_id [out] The thread ID of the address. +/// +/// @returns Returns the number of stored frames or 0 on error. +size_t __asan_get_free_stack(void *addr, void **trace, size_t size, + int *thread_id); + +/// Gets the current shadow memory mapping (useful for calling from the +/// debugger). +/// +/// @param shadow_scale [out] Shadow scale value. +/// @param shadow_offset [out] Offset value. +void __asan_get_shadow_mapping(size_t *shadow_scale, size_t *shadow_offset); + +/// This is an internal function that is called to report an error. However, +/// it is still a part of the interface because you might want to set a +/// breakpoint on this function in the debugger. +/// +/// @param pc pc value of the ASan error. +/// @param bp bp value of the ASan error. +/// @param sp sp value of the ASan error. +/// @param addr Address of the ASan error. +/// @param is_write True if the error is a write error; false otherwise. +/// @param access_size Size of the memory access of the ASan error. +void __asan_report_error(void *pc, void *bp, void *sp, + void *addr, int is_write, size_t access_size); + +// Deprecated. Call __sanitizer_set_death_callback instead. +void __asan_set_death_callback(void (*callback)(void)); + +/// Sets the callback function to be called during ASan error reporting. +/// +/// The callback provides a string pointer to the report. +/// +/// @param callback User-provided function. +void __asan_set_error_report_callback(void (*callback)(const char *)); + +/// User-provided callback on ASan errors. +/// +/// You can provide a function that would be called immediately when ASan +/// detects an error. This is useful in cases when ASan detects an error but +/// your program crashes before the ASan report is printed. void __asan_on_error(void); - // Prints accumulated stats to stderr. Used for debugging. - void __asan_print_accumulated_stats(void); - - // This function may be optionally provided by user and should return - // a string containing ASan runtime options. See asan_flags.h for details. - const char* __asan_default_options(void); - - // The following 2 functions facilitate garbage collection in presence of - // asan's fake stack. - - // Returns an opaque handler to be used later in __asan_addr_is_in_fake_stack. - // Returns NULL if the current thread does not have a fake stack. - void *__asan_get_current_fake_stack(void); - - // If fake_stack is non-NULL and addr belongs to a fake frame in - // fake_stack, returns the address on real stack that corresponds to - // the fake frame and sets beg/end to the boundaries of this fake frame. - // Otherwise returns NULL and does not touch beg/end. - // If beg/end are NULL, they are not touched. - // This function may be called from a thread other than the owner of - // fake_stack, but the owner thread need to be alive. - void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, - void **end); - - // Performs cleanup before a [[noreturn]] function. Must be called - // before things like _exit and execl to avoid false positives on stack. - void __asan_handle_no_return(void); +/// Prints accumulated statistics to stderr (useful for calling from the +/// debugger). +void __asan_print_accumulated_stats(void); + +/// User-provided default option settings. +/// +/// You can provide your own implementation of this function to return a string +/// containing ASan runtime options (for example, +/// verbosity=1:halt_on_error=0). +/// +/// @returns Default options string. +const char* __asan_default_options(void); + +// The following two functions facilitate garbage collection in presence of +// ASan's fake stack. + +/// Gets an opaque handler to the current thread's fake stack. +/// +/// Returns an opaque handler to be used by +/// __asan_addr_is_in_fake_stack(). Returns NULL if the current thread +/// does not have a fake stack. +/// +/// @returns An opaque handler to the fake stack or NULL. +void *__asan_get_current_fake_stack(void); + +/// Checks if an address belongs to a given fake stack. +/// +/// If fake_stack is non-NULL and addr belongs to a +/// fake frame in fake_stack, returns the address of the real +/// stack that corresponds to the fake frame and sets beg and +/// end to the boundaries of this fake frame. Otherwise returns +/// NULL and does not touch beg and end. +/// +/// If beg or end are NULL, they are not touched. +/// +/// @note This function can be called from a thread other than the owner of +/// fake_stack, but the owner thread needs to be alive. +/// +/// @param fake_stack An opaque handler to a fake stack. +/// @param addr Address to test. +/// @param beg [out] Beginning of fake frame. +/// @param end [out] End of fake frame. +/// @returns Stack address or NULL. +void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, + void **end); + +/// Performs shadow memory cleanup of the current thread's stack before a +/// function marked with the [[noreturn]] attribute is called. +/// +/// To avoid false positives on the stack, must be called before no-return +/// functions like _exit() and execl(). +void __asan_handle_no_return(void); #ifdef __cplusplus } // extern "C" Index: include/sanitizer/common_interface_defs.h =================================================================== --- include/sanitizer/common_interface_defs.h +++ include/sanitizer/common_interface_defs.h @@ -17,189 +17,334 @@ // GCC does not understand __has_feature. #if !defined(__has_feature) -# define __has_feature(x) 0 +#define __has_feature(x) 0 #endif #ifdef __cplusplus extern "C" { #endif - // Arguments for __sanitizer_sandbox_on_notify() below. - typedef struct { - // Enable sandbox support in sanitizer coverage. - int coverage_sandboxed; - // File descriptor to write coverage data to. If -1 is passed, a file will - // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no - // effect if coverage_sandboxed == 0. - intptr_t coverage_fd; - // If non-zero, split the coverage data into well-formed blocks. This is - // useful when coverage_fd is a socket descriptor. Each block will contain - // a header, allowing data from multiple processes to be sent over the same - // socket. - unsigned int coverage_max_block_size; - } __sanitizer_sandbox_arguments; - - // Tell the tools to write their reports to "path." instead of stderr. - void __sanitizer_set_report_path(const char *path); - // Tell the tools to write their reports to the provided file descriptor - // (casted to void *). - void __sanitizer_set_report_fd(void *fd); - - // Notify the tools that the sandbox is going to be turned on. The reserved - // parameter will be used in the future to hold a structure with functions - // that the tools may call to bypass the sandbox. - void __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args); - - // This function is called by the tool when it has just finished reporting - // an error. 'error_summary' is a one-line string that summarizes - // the error message. This function can be overridden by the client. - void __sanitizer_report_error_summary(const char *error_summary); - - // Some of the sanitizers (e.g. asan/tsan) may miss bugs that happen - // in unaligned loads/stores. In order to find such bugs reliably one needs - // to replace plain unaligned loads/stores with these calls. - uint16_t __sanitizer_unaligned_load16(const void *p); - uint32_t __sanitizer_unaligned_load32(const void *p); - uint64_t __sanitizer_unaligned_load64(const void *p); - void __sanitizer_unaligned_store16(void *p, uint16_t x); - void __sanitizer_unaligned_store32(void *p, uint32_t x); - void __sanitizer_unaligned_store64(void *p, uint64_t x); - - // Returns 1 on the first call, then returns 0 thereafter. Called by the tool - // to ensure only one report is printed when multiple errors occur - // simultaneously. - int __sanitizer_acquire_crash_state(); - - // Annotate the current state of a contiguous container, such as - // std::vector, std::string or similar. - // A contiguous container is a container that keeps all of its elements - // in a contiguous region of memory. The container owns the region of memory - // [beg, end); the memory [beg, mid) is used to store the current elements - // and the memory [mid, end) is reserved for future elements; - // beg <= mid <= end. For example, in "std::vector<> v" - // beg = &v[0]; - // end = beg + v.capacity() * sizeof(v[0]); - // mid = beg + v.size() * sizeof(v[0]); - // - // This annotation tells the Sanitizer tool about the current state of the - // container so that the tool can report errors when memory from [mid, end) - // is accessed. Insert this annotation into methods like push_back/pop_back. - // Supply the old and the new values of mid (old_mid/new_mid). - // In the initial state mid == end and so should be the final - // state when the container is destroyed or when it reallocates the storage. - // - // Use with caution and don't use for anything other than vector-like classes. - // - // For AddressSanitizer, 'beg' should be 8-aligned and 'end' should - // be either 8-aligned or it should point to the end of a separate heap-, - // stack-, or global- allocated buffer. I.e. the following will not work: - // int64_t x[2]; // 16 bytes, 8-aligned. - // char *beg = (char *)&x[0]; - // char *end = beg + 12; // Not 8 aligned, not the end of the buffer. - // This however will work fine: - // int32_t x[3]; // 12 bytes, but 8-aligned under AddressSanitizer. - // char *beg = (char*)&x[0]; - // char *end = beg + 12; // Not 8-aligned, but is the end of the buffer. - void __sanitizer_annotate_contiguous_container(const void *beg, - const void *end, - const void *old_mid, - const void *new_mid); - // Returns true if the contiguous container [beg, end) is properly poisoned - // (e.g. with __sanitizer_annotate_contiguous_container), i.e. if - // - [beg, mid) is addressable, - // - [mid, end) is unaddressable. - // Full verification requires O(end-beg) time; this function tries to avoid - // such complexity by touching only parts of the container around beg/mid/end. - int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, - const void *end); - - // Similar to __sanitizer_verify_contiguous_container but returns the address - // of the first improperly poisoned byte otherwise. Returns null if the area - // is poisoned properly. - const void *__sanitizer_contiguous_container_find_bad_address( - const void *beg, const void *mid, const void *end); - - // Print the stack trace leading to this call. Useful for debugging user code. - void __sanitizer_print_stack_trace(void); - - // Symbolizes the supplied 'pc' using the format string 'fmt'. - // Outputs at most 'out_buf_size' bytes into 'out_buf'. - // If 'out_buf' is not empty then output is zero or more non empty C strings - // followed by single empty C string. Multiple strings can be returned if PC - // corresponds to inlined function. Inlined frames are printed in the order - // from "most-inlined" to the "least-inlined", so the last frame should be the - // not inlined function. - // Inlined frames can be removed with 'symbolize_inline_frames=0'. - // The format syntax is described in - // lib/sanitizer_common/sanitizer_stacktrace_printer.h. - void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf, - size_t out_buf_size); - // Same as __sanitizer_symbolize_pc, but for data section (i.e. globals). - void __sanitizer_symbolize_global(void *data_ptr, const char *fmt, - char *out_buf, size_t out_buf_size); - - // Sets the callback to be called right before death on error. - // Passing 0 will unset the callback. - void __sanitizer_set_death_callback(void (*callback)(void)); - - // Interceptor hooks. - // Whenever a libc function interceptor is called it checks if the - // corresponding weak hook is defined, and it so -- calls it. - // The primary use case is data-flow-guided fuzzing, where the fuzzer needs - // to know what is being passed to libc functions, e.g. memcmp. - // FIXME: implement more hooks. - void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1, - const void *s2, size_t n, int result); - void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, - const char *s2, size_t n, int result); - void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, - const char *s2, size_t n, int result); - void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1, - const char *s2, int result); - void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, - const char *s2, int result); - void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, - const char *s2, char *result); +// Arguments for __sanitizer_sandbox_on_notify() below. +typedef struct { + // Enable sandbox support in sanitizer coverage. + int coverage_sandboxed; + // File descriptor to write coverage data to. If -1 is passed, a file will + // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no + // effect if coverage_sandboxed == 0. + intptr_t coverage_fd; + // If non-zero, split the coverage data into well-formed blocks. This is + // useful when coverage_fd is a socket descriptor. Each block will contain + // a header, allowing data from multiple processes to be sent over the same + // socket. + unsigned int coverage_max_block_size; +} __sanitizer_sandbox_arguments; + +// Tell the tools to write their reports to "path." instead of stderr. +void __sanitizer_set_report_path(const char *path); +// Tell the tools to write their reports to the provided file descriptor +// (casted to void *). +void __sanitizer_set_report_fd(void *fd); + +// Notify the tools that the sandbox is going to be turned on. The reserved +// parameter will be used in the future to hold a structure with functions +// that the tools may call to bypass the sandbox. +void __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args); + +// This function is called by the tool when it has just finished reporting +// an error. 'error_summary' is a one-line string that summarizes +// the error message. This function can be overridden by the client. +void __sanitizer_report_error_summary(const char *error_summary); + +// Some of the sanitizers (for example ASan/TSan) could miss bugs that happen +// in unaligned loads/stores. To find such bugs reliably, you need to replace +// plain unaligned loads/stores with these calls. + +/// Loads a 16-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// +/// @returns Loaded value. +uint16_t __sanitizer_unaligned_load16(const void *p); + +/// Loads a 32-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// +/// @returns Loaded value. +uint32_t __sanitizer_unaligned_load32(const void *p); + +/// Loads a 64-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// +/// @returns Loaded value. +uint64_t __sanitizer_unaligned_load64(const void *p); + +/// Stores a 16-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// @param x 16-bit value to store. +void __sanitizer_unaligned_store16(void *p, uint16_t x); + +/// Stores a 32-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// @param x 32-bit value to store. +void __sanitizer_unaligned_store32(void *p, uint32_t x); + +/// Stores a 64-bit unaligned value. +/// +/// @param p Pointer to unaligned memory. +/// @param x 64-bit value to store. +void __sanitizer_unaligned_store64(void *p, uint64_t x); + +// Returns 1 on the first call, then returns 0 thereafter. Called by the tool +// to ensure only one report is printed when multiple errors occur +// simultaneously. +int __sanitizer_acquire_crash_state(); + +/// Annotates the current state of a contiguous container, such as +/// std::vector, std::string, or similar. +/// +/// A contiguous container is a container that keeps all of its elements +/// in a contiguous region of memory. The container owns the region of memory +/// [beg, end); the memory [beg, mid) is used to store the +/// current elements, and the memory [mid, end) is reserved for future +/// elements (beg <= mid <= end). For example, in +/// std::vector<> v: +/// +/// @code +/// beg = &v[0]; +/// end = beg + v.capacity() * sizeof(v[0]); +/// mid = beg + v.size() * sizeof(v[0]); +/// @endcode +/// +/// This annotation tells the Sanitizer tool about the current state of the +/// container so that the tool can report errors when memory from +/// [mid, end) is accessed. Insert this annotation into methods like +/// push_back() or pop_back(). Supply the old and new values of +/// mid(old_mid and new_mid). In the initial +/// state mid == end, so that should be the final state when the +/// container is destroyed or when the container reallocates the storage. +/// +/// For ASan, beg should be 8-aligned and end +/// should be either 8-aligned or it should point to the end of a separate +/// heap-, stack-, or global-allocated buffer. So the following example will +/// not work: +/// +/// @code +/// int64_t x[2]; // 16 bytes, 8-aligned +/// char *beg = (char *)&x[0]; +/// char *end = beg + 12; // Not 8-aligned, not the end of the buffer +/// @endcode +/// +/// The following, however, will work: +/// @code +/// int32_t x[3]; // 12 bytes, but 8-aligned under ASan. +/// char *beg = (char*)&x[0]; +/// char *end = beg + 12; // Not 8-aligned, but is the end of the buffer +/// @endcode +/// +/// @note Use this function with caution and do not use for anything other +/// than vector-like classes. +/// +/// @param beg Beginning of memory region. +/// @param end End of memory region. +/// @param old_mid Old middle of memory region. +/// @param new_mid New middle of memory region. +void __sanitizer_annotate_contiguous_container(const void *beg, + const void *end, + const void *old_mid, + const void *new_mid); + +/// Returns true if the contiguous container [beg, end) is properly +/// poisoned. +/// +/// Proper poisoning could occur, for example, with +/// __sanitizer_annotate_contiguous_container), that is, if +/// [beg, mid) is addressable and [mid, end) is unaddressable. +/// Full verification requires O (end - beg) time; this function tries +/// to avoid such complexity by touching only parts of the container around +/// beg, mid, and end. +/// +/// @param beg Beginning of memory region. +/// @param mid Middle of memory region. +/// @param end Old end of memory region. +/// +/// @returns True if the contiguous container [beg, end) is properly +/// poisoned. +int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, + const void *end); + +/// Similar to __sanitizer_verify_contiguous_container() but also +/// returns the address of the first improperly poisoned byte. +/// +/// Returns NULL if the area is poisoned properly. +/// +/// @param beg Beginning of memory region. +/// @param mid Middle of memory region. +/// @param end Old end of memory region. +/// +/// @returns The bad address or NULL. +const void *__sanitizer_contiguous_container_find_bad_address(const void *beg, + const void *mid, + const void *end); + +/// Prints the stack trace leading to this call (useful for calling from the +/// debugger). +void __sanitizer_print_stack_trace(void); + +// Symbolizes the supplied 'pc' using the format string 'fmt'. +// Outputs at most 'out_buf_size' bytes into 'out_buf'. +// If 'out_buf' is not empty then output is zero or more non empty C strings +// followed by single empty C string. Multiple strings can be returned if PC +// corresponds to inlined function. Inlined frames are printed in the order +// from "most-inlined" to the "least-inlined", so the last frame should be the +// not inlined function. +// Inlined frames can be removed with 'symbolize_inline_frames=0'. +// The format syntax is described in +// lib/sanitizer_common/sanitizer_stacktrace_printer.h. +void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf, + size_t out_buf_size); +// Same as __sanitizer_symbolize_pc, but for data section (i.e. globals). +void __sanitizer_symbolize_global(void *data_ptr, const char *fmt, + char *out_buf, size_t out_buf_size); + +/// Sets the callback to be called immediately before death on error. +/// +/// Passing 0 will unset the callback. +/// +/// @param callback User-provided callback. +void __sanitizer_set_death_callback(void (*callback)(void)); + + +// Interceptor hooks. +// Whenever a libc function interceptor is called, it checks if the +// corresponding weak hook is defined, and calls it if it is indeed defined. +// The primary use-case is data-flow-guided fuzzing, where the fuzzer needs +// to know what is being passed to libc functions (for example memcmp). +// FIXME: implement more hooks. + +/// Interceptor hook for memcmp(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param n Number of bytes to compare. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1, + const void *s2, size_t n, int result); + +/// Interceptor hook for strncmp(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param n Number of bytes to compare. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result); + +/// Interceptor hook for strncasecmp(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param n Number of bytes to compare. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result); + +/// Interceptor hook for strcmp(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1, + const char *s2, int result); + +/// Interceptor hook for strcasecmp(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, + const char *s2, int result); + +/// Interceptor hook for strstr(). +/// +/// @param called_pc PC (program counter) address of the original call. +/// @param s1 Pointer to block of memory. +/// @param s2 Pointer to block of memory. +/// @param result Value returned by the intercepted function. +void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result); + void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, const char *s2, char *result); void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, const void *s2, size_t len2, void *result); - // Prints stack traces for all live heap allocations ordered by total - // allocation size until `top_percent` of total live heap is shown. - // `top_percent` should be between 1 and 100. - // At most `max_number_of_contexts` contexts (stack traces) is printed. - // Experimental feature currently available only with asan on Linux/x86_64. - void __sanitizer_print_memory_profile(size_t top_percent, - size_t max_number_of_contexts); - - // Fiber annotation interface. - // Before switching to a different stack, one must call - // __sanitizer_start_switch_fiber with a pointer to the bottom of the - // destination stack and its size. When code starts running on the new stack, - // it must call __sanitizer_finish_switch_fiber to finalize the switch. - // The start_switch function takes a void** to store the current fake stack if - // there is one (it is needed when detect_stack_use_after_return is enabled). - // When restoring a stack, this pointer must be given to the finish_switch - // function. In most cases, this void* can be stored on the stack just before - // switching. When leaving a fiber definitely, null must be passed as first - // argument to the start_switch function so that the fake stack is destroyed. - // If you do not want support for stack use-after-return detection, you can - // always pass null to these two functions. - // Note that the fake stack mechanism is disabled during fiber switch, so if a - // signal callback runs during the switch, it will not benefit from the stack - // use-after-return detection. - void __sanitizer_start_switch_fiber(void **fake_stack_save, - const void *bottom, size_t size); - void __sanitizer_finish_switch_fiber(void *fake_stack_save, - const void **bottom_old, - size_t *size_old); - - // Get full module name and calculate pc offset within it. - // Returns 1 if pc belongs to some module, 0 if module was not found. - int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path, - size_t module_path_len, - void **pc_offset); +// Prints stack traces for all live heap allocations ordered by total +// allocation size until top_percent of total live heap is shown. top_percent +// should be between 1 and 100. At most max_number_of_contexts contexts +// (stack traces) are printed. +// Experimental feature currently available only with ASan on Linux/x86_64. +void __sanitizer_print_memory_profile(size_t top_percent, + size_t max_number_of_contexts); + +/// Notify ASan that a fiber switch has started (required only if implementing +/// your own fiber library). +/// +/// Before switching to a different stack, you must call +/// __sanitizer_start_switch_fiber() with a pointer to the bottom of the +/// destination stack and with its size. When code starts running on the new +/// stack, it must call __sanitizer_finish_switch_fiber() to finalize +/// the switch. The __sanitizer_start_switch_fiber() function takes a +/// void** pointer argument to store the current fake stack if there is +/// one (it is necessary when the runtime option +/// detect_stack_use_after_return is enabled). +/// +/// When restoring a stack, this void** pointer must be given to the +/// __sanitizer_finish_switch_fiber() function. In most cases, this +/// pointer can be stored on the stack immediately before switching. When +/// leaving a fiber definitely, NULL must be passed as the first argument to +/// the __sanitizer_start_switch_fiber() function so that the fake stack +/// is destroyed. If your program does not need stack use-after-return +/// detection, you can always pass NULL to these two functions. +/// +/// @note The fake stack mechanism is disabled during fiber switch, so if a +/// signal callback runs during the switch, it will not benefit from stack +/// use-after-return detection. +/// +/// @param fake_stack_save [out] Fake stack save location. +/// @param bottom Bottom address of stack. +/// @param size Size of stack in bytes. +void __sanitizer_start_switch_fiber(void **fake_stack_save, + const void *bottom, size_t size); + +/// Notify ASan that a fiber switch has completed (required only if +/// implementing your own fiber library). +/// +/// When code starts running on the new stack, it must call +/// __sanitizer_finish_switch_fiber() to finalize +/// the switch. For usage details, see the description of +/// __sanitizer_start_switch_fiber(). +/// +/// @param fake_stack_save Fake stack save location. +/// @param bottom_old [out] Bottom address of old stack. +/// @param size_old [out] Size of old stack in bytes. +void __sanitizer_finish_switch_fiber(void *fake_stack_save, + const void **bottom_old, + size_t *size_old); + +// Get full module name and calculate pc offset within it. +// Returns 1 if pc belongs to some module, 0 if module was not found. +int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path, + size_t module_path_len, + void **pc_offset); #ifdef __cplusplus } // extern "C"