Merge ^/vendor/compiler-rt/dist up to its last change, and resolve conflicts.

This commit is contained in:
Dimitry Andric 2020-01-22 22:01:43 +00:00
commit 68d75eff68
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang1000-import/; revision=356999
374 changed files with 4548 additions and 3046 deletions

View File

@ -13,11 +13,10 @@
#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <initializer_list>
#include <string>
@ -25,8 +24,10 @@
#include <utility>
#include <vector>
// In addition to the comments below, the API is also briefly documented at
// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
class FuzzedDataProvider {
public:
public:
// |data| is an array of length |size| that the FuzzedDataProvider wraps to
// provide more granular access. |data| must outlive the FuzzedDataProvider.
FuzzedDataProvider(const uint8_t *data, size_t size)
@ -143,9 +144,9 @@ class FuzzedDataProvider {
return ConsumeBytes<T>(remaining_bytes_);
}
// Returns a std::string containing all remaining bytes of the input data.
// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
// object.
// Returns a std::vector containing all remaining bytes of the input data.
std::string ConsumeRemainingBytesAsString() {
return ConsumeBytesAsString(remaining_bytes_);
}
@ -161,7 +162,7 @@ class FuzzedDataProvider {
// Reads one byte and returns a bool, or false when no data remains.
bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); }
// Returns a copy of a value selected from a fixed-size |array|.
// Returns a copy of the value selected from the given fixed-size |array|.
template <typename T, size_t size>
T PickValueInArray(const T (&array)[size]) {
static_assert(size > 0, "The array must be non empty.");
@ -170,11 +171,14 @@ class FuzzedDataProvider {
template <typename T>
T PickValueInArray(std::initializer_list<const T> list) {
// static_assert(list.size() > 0, "The array must be non empty.");
// TODO(Dor1s): switch to static_assert once C++14 is allowed.
if (!list.size())
abort();
return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));
}
// Return an enum value. The enum must start at 0 and be contiguous. It must
// Returns an enum value. The enum must start at 0 and be contiguous. It must
// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
template <typename T> T ConsumeEnum() {
@ -183,10 +187,60 @@ class FuzzedDataProvider {
0, static_cast<uint32_t>(T::kMaxValue)));
}
// Returns a floating point number in the range [0.0, 1.0]. If there's no
// input data left, always returns 0.
template <typename T> T ConsumeProbability() {
static_assert(std::is_floating_point<T>::value,
"A floating point type is required.");
// Use different integral types for different floating point types in order
// to provide better density of the resulting values.
using IntegralType =
typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), uint32_t,
uint64_t>::type;
T result = static_cast<T>(ConsumeIntegral<IntegralType>());
result /= static_cast<T>(std::numeric_limits<IntegralType>::max());
return result;
}
// Returns a floating point value in the range [Type's lowest, Type's max] by
// consuming bytes from the input data. If there's no input data left, always
// returns approximately 0.
template <typename T> T ConsumeFloatingPoint() {
return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),
std::numeric_limits<T>::max());
}
// Returns a floating point value in the given range by consuming bytes from
// the input data. If there's no input data left, returns |min|. Note that
// |min| must be less than or equal to |max|.
template <typename T> T ConsumeFloatingPointInRange(T min, T max) {
if (min > max)
abort();
T range = .0;
T result = min;
constexpr T zero(.0);
if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {
// The diff |max - min| would overflow the given floating point type. Use
// the half of the diff as the range and consume a bool to decide whether
// the result is in the first of the second part of the diff.
range = (max / 2.0) - (min / 2.0);
if (ConsumeBool()) {
result += range;
}
} else {
range = max - min;
}
return result + range * ConsumeProbability<T>();
}
// Reports the remaining bytes available for fuzzed input.
size_t remaining_bytes() { return remaining_bytes_; }
private:
private:
FuzzedDataProvider(const FuzzedDataProvider &) = delete;
FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;
@ -230,9 +284,9 @@ class FuzzedDataProvider {
// Avoid using implementation-defined unsigned to signer conversions.
// To learn more, see https://stackoverflow.com/questions/13150449.
if (value <= std::numeric_limits<TS>::max())
if (value <= std::numeric_limits<TS>::max()) {
return static_cast<TS>(value);
else {
} else {
constexpr auto TS_min = std::numeric_limits<TS>::min();
return TS_min + static_cast<char>(value - TS_min);
}

View File

@ -112,7 +112,7 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
} // extern "C"
template <typename T>
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
dfsan_set_label(label, (void *)&data, sizeof(T));
}

View File

@ -17,10 +17,10 @@
extern "C" {
#endif
typedef char __tsan_atomic8;
typedef short __tsan_atomic16; // NOLINT
typedef int __tsan_atomic32;
typedef long __tsan_atomic64; // NOLINT
typedef char __tsan_atomic8;
typedef short __tsan_atomic16;
typedef int __tsan_atomic32;
typedef long __tsan_atomic64;
#if defined(__SIZEOF_INT128__) \
|| (__clang_major__ * 100 + __clang_minor__ >= 302)
__extension__ typedef __int128 __tsan_atomic128;

View File

@ -0,0 +1,32 @@
//===-- sanitizer/ubsan_interface.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 UBSanitizer (UBSan).
//
// Public interface header.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_UBSAN_INTERFACE_H
#define SANITIZER_UBSAN_INTERFACE_H
#ifdef __cplusplus
extern "C" {
#endif
/// User-provided default option settings.
///
/// You can provide your own implementation of this function to return a string
/// containing UBSan runtime options (for example,
/// <c>verbosity=1:halt_on_error=0</c>).
///
/// \returns Default options string.
const char* __ubsan_default_options(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // SANITIZER_UBSAN_INTERFACE_H

View File

@ -1,4 +1,4 @@
//===-- asan_activation.cc --------------------------------------*- C++ -*-===//
//===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_allocator.cc -------------------------------------------------===//
//===-- asan_allocator.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -1075,7 +1075,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
} // namespace __lsan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// ASan allocator doesn't reserve extra bytes, so normally we would
// just return "size". We don't want to expose our redzone sizes, etc here.

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_allocator.cc.
// ASan-private header for asan_allocator.cpp.
//===----------------------------------------------------------------------===//
#ifndef ASAN_ALLOCATOR_H

View File

@ -1,4 +1,4 @@
//===-- asan_debugging.cc -------------------------------------------------===//
//===-- asan_debugging.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -25,7 +25,7 @@ using namespace __asan;
static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
char *name, uptr name_size,
uptr &region_address, uptr &region_size) {
uptr *region_address, uptr *region_size) {
InternalMmapVector<StackVarDescr> vars;
vars.reserve(16);
if (!ParseFrameDescription(frame_descr, &vars)) {
@ -39,8 +39,8 @@ static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
// the whole name and then terminate with '\0'.
internal_strlcpy(name, vars[i].name_pos,
Min(name_size, vars[i].name_len + 1));
region_address = addr - (offset - vars[i].beg);
region_size = vars[i].size;
*region_address = addr - (offset - vars[i].beg);
*region_size = vars[i].size;
return;
}
}
@ -108,7 +108,7 @@ const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
// region_{address,size} are already 0
} else {
FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
name_size, region_address, region_size);
name_size, &region_address, &region_size);
}
} else if (auto global = descr.AsGlobal()) {
region_kind = "global";

View File

@ -1,4 +1,4 @@
//===-- asan_descriptions.cc ------------------------------------*- C++ -*-===//
//===-- asan_descriptions.cpp -----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_descriptions.cc.
// ASan-private header for asan_descriptions.cpp.
// TODO(filcab): Most struct definitions should move to the interface headers.
//===----------------------------------------------------------------------===//
#ifndef ASAN_DESCRIPTIONS_H
@ -203,7 +203,7 @@ class AddressDescription {
AddressDescription() = default;
// shouldLockThreadRegistry allows us to skip locking if we're sure we already
// have done it.
AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
: AddressDescription(addr, 1, shouldLockThreadRegistry) {}
AddressDescription(uptr addr, uptr access_size,
bool shouldLockThreadRegistry = true);

View File

@ -1,4 +1,4 @@
//===-- asan_errors.cc ------------------------------------------*- C++ -*-===//
//===-- asan_errors.cpp -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -35,7 +35,8 @@ static void OnStackUnwind(const SignalContext &sig,
// corresponding code in the sanitizer_common and we use this callback to
// print it.
static_cast<const ScarinessScoreBase *>(callback_context)->Print();
stack->Unwind(sig.pc, sig.bp, sig.context, fast);
stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
fast);
}
void ErrorDeadlySignal::Print() {
@ -244,7 +245,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
"ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
"%zd, alignment must be a power of two and a multiple of sizeof(void*) "
"== %zd (thread %s)\n",
alignment, sizeof(void*), AsanThreadIdAndName(tid).c_str()); // NOLINT
alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
Printf("%s", d.Default());
stack->Print();
PrintHintAllocatorCannotReturnNull();

View File

@ -48,7 +48,8 @@ struct ErrorDeadlySignal : ErrorBase {
scariness.Scare(10, "stack-overflow");
} else if (!signal.is_memory_access) {
scariness.Scare(10, "signal");
} else if (signal.addr < GetPageSizeCached()) {
} else if (signal.is_true_faulting_addr &&
signal.addr < GetPageSizeCached()) {
scariness.Scare(10, "null-deref");
} else if (signal.addr == signal.pc) {
scariness.Scare(60, "wild-jump");

View File

@ -1,4 +1,4 @@
//===-- asan_fake_stack.cc ------------------------------------------------===//
//===-- asan_fake_stack.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_fake_stack.cc, implements FakeStack.
// ASan-private header for asan_fake_stack.cpp, implements FakeStack.
//===----------------------------------------------------------------------===//
#ifndef ASAN_FAKE_STACK_H

View File

@ -1,4 +1,4 @@
//===-- asan_flags.cc -------------------------------------------*- C++ -*-===//
//===-- asan_flags.cpp ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -139,10 +139,10 @@ ASAN_FLAG(
"If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
"pairs (e.g. when pointers belong to different objects); "
"If == 1, detect invalid operations only when both pointers are non-null.")
ASAN_FLAG(
bool, detect_container_overflow, true,
"If true, honor the container overflow annotations. See "
"https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow")
ASAN_FLAG(bool, detect_container_overflow, true,
"If true, honor the container overflow annotations. See "
"https://github.com/google/sanitizers/wiki/"
"AddressSanitizerContainerOverflow")
ASAN_FLAG(int, detect_odr_violation, 2,
"If >=2, detect violation of One-Definition-Rule (ODR); "
"If ==1, detect ODR-violation only if the two variables "
@ -158,5 +158,6 @@ ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
ASAN_FLAG(bool, verify_asan_link_order, true,
"Check position of ASan runtime in library list (needs to be disabled"
" when other library has to be preloaded system-wide)")
ASAN_FLAG(bool, windows_hook_rtl_allocators, false,
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
ASAN_FLAG(
bool, windows_hook_rtl_allocators, false,
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")

View File

@ -1,4 +1,4 @@
//===-- asan_fuchsia.cc --------------------------------------------------===//
//===-- asan_fuchsia.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -28,7 +28,7 @@ namespace __asan {
// The system already set up the shadow memory for us.
// __sanitizer::GetMaxUserVirtualAddress has already been called by
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cc).
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
// Just do some additional sanity checks here.
void InitializeShadowMemory() {
if (Verbosity()) PrintAddressSpaceLayout();
@ -172,7 +172,7 @@ static void ThreadCreateHook(void *hook, bool aborted) {
// This is called in the newly-created thread before it runs anything else,
// with the pointer returned by BeforeThreadCreateHook (above).
// cf. asan_interceptors.cc:asan_thread_start
// cf. asan_interceptors.cpp:asan_thread_start
static void ThreadStartHook(void *hook, uptr os_id) {
AsanThread *thread = static_cast<AsanThread *>(hook);
SetCurrentThread(thread);

View File

@ -1,4 +1,4 @@
//===-- asan_globals.cc ---------------------------------------------------===//
//===-- asan_globals.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -227,8 +227,7 @@ static void RegisterGlobal(const Global *g) {
list_of_all_globals = l;
if (g->has_dynamic_init) {
if (!dynamic_init_globals) {
dynamic_init_globals =
new (allocator_for_globals) VectorOfGlobals; // NOLINT
dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
}
DynInitGlobal dyn_global = { *g, false };
@ -315,8 +314,7 @@ void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// Apply __asan_register_globals to all globals found in the same loaded
// executable or shared library as `flag'. The flag tracks whether globals have
@ -364,7 +362,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
BlockingMutexLock lock(&mu_for_globals);
if (!global_registration_site_vector) {
global_registration_site_vector =
new (allocator_for_globals) GlobalRegistrationSiteVector; // NOLINT
new (allocator_for_globals) GlobalRegistrationSiteVector;
global_registration_site_vector->reserve(128);
}
GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};

View File

@ -1,4 +1,4 @@
//===-- asan_globals_win.cc -----------------------------------------------===//
//===-- asan_globals_win.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -15,8 +15,8 @@
namespace __asan {
#pragma section(".ASAN$GA", read, write) // NOLINT
#pragma section(".ASAN$GZ", read, write) // NOLINT
#pragma section(".ASAN$GA", read, write)
#pragma section(".ASAN$GZ", read, write)
extern "C" __declspec(allocate(".ASAN$GA"))
ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {};
extern "C" __declspec(allocate(".ASAN$GZ"))
@ -49,8 +49,8 @@ static void unregister_dso_globals() {
}
// Register globals
#pragma section(".CRT$XCU", long, read) // NOLINT
#pragma section(".CRT$XTX", long, read) // NOLINT
#pragma section(".CRT$XCU", long, read)
#pragma section(".CRT$XTX", long, read)
extern "C" __declspec(allocate(".CRT$XCU"))
void (*const __asan_dso_reg_hook)() = &register_dso_globals;
extern "C" __declspec(allocate(".CRT$XTX"))

View File

@ -1,4 +1,4 @@
//===-- asan_interceptors.cc ----------------------------------------------===//
//===-- asan_interceptors.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -24,7 +24,7 @@
#include "sanitizer_common/sanitizer_libc.h"
// There is no general interception at all on Fuchsia and RTEMS.
// Only the functions in asan_interceptors_memintrinsics.cc are
// Only the functions in asan_interceptors_memintrinsics.cpp are
// really defined to replace libc functions.
#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
@ -79,7 +79,7 @@ int OnExit() {
} // namespace __asan
// ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
@ -164,6 +164,11 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
ASAN_MEMSET_IMPL(ctx, block, c, size); \
} while (false)
#if CAN_SANITIZE_LEAKS
#define COMMON_INTERCEPTOR_STRERROR() \
__lsan::ScopedInterceptorDisabler disabler
#endif
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#include "sanitizer_common/sanitizer_signal_interceptors.inc"
@ -373,26 +378,26 @@ DEFINE_REAL(char*, index, const char *string, int c)
// For both strcat() and strncat() we need to check the validity of |to|
// argument irrespective of the |from| length.
INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
uptr from_length = REAL(strlen)(from);
ASAN_READ_RANGE(ctx, from, from_length + 1);
uptr to_length = REAL(strlen)(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap
// with the resulting string starting at |to|, which has a length of
// to_length + from_length + 1.
if (from_length > 0) {
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
from, from_length + 1);
INTERCEPTOR(char *, strcat, char *to, const char *from) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
uptr from_length = REAL(strlen)(from);
ASAN_READ_RANGE(ctx, from, from_length + 1);
uptr to_length = REAL(strlen)(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap
// with the resulting string starting at |to|, which has a length of
// to_length + from_length + 1.
if (from_length > 0) {
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
from_length + 1);
}
}
return REAL(strcat)(to, from);
}
return REAL(strcat)(to, from); // NOLINT
}
INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
void *ctx;
@ -413,16 +418,17 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
return REAL(strncat)(to, from, size);
}
INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
INTERCEPTOR(char *, strcpy, char *to, const char *from) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
#if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
if (UNLIKELY(!asan_inited))
return REAL(strcpy)(to, from);
#endif
// strcpy is called from malloc_default_purgeable_zone()
// in __asan::ReplaceSystemAlloc() on Mac.
if (asan_init_is_running) {
return REAL(strcpy)(to, from); // NOLINT
return REAL(strcpy)(to, from);
}
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
@ -431,7 +437,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
ASAN_READ_RANGE(ctx, from, from_size);
ASAN_WRITE_RANGE(ctx, to, from_size);
}
return REAL(strcpy)(to, from); // NOLINT
return REAL(strcpy)(to, from);
}
INTERCEPTOR(char*, strdup, const char *s) {
@ -479,8 +485,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
return REAL(strncpy)(to, from, size);
}
INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
char **endptr, int base) {
INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtol);
ENSURE_ASAN_INITED();
@ -488,7 +493,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
return REAL(strtol)(nptr, endptr, base);
}
char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
long result = REAL(strtol)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result;
}
@ -514,7 +519,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
return result;
}
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
INTERCEPTOR(long, atol, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atol);
#if SANITIZER_MAC
@ -525,15 +530,14 @@ INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
return REAL(atol)(nptr);
}
char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
long result = REAL(strtol)(nptr, &real_endptr, 10);
FixRealStrtolEndptr(nptr, &real_endptr);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result;
}
#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
char **endptr, int base) {
INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
ENSURE_ASAN_INITED();
@ -541,12 +545,12 @@ INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
return REAL(strtoll)(nptr, endptr, base);
}
char *real_endptr;
long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
long long result = REAL(strtoll)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result;
}
INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
INTERCEPTOR(long long, atoll, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atoll);
ENSURE_ASAN_INITED();
@ -554,31 +558,66 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
return REAL(atoll)(nptr);
}
char *real_endptr;
long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
long long result = REAL(strtoll)(nptr, &real_endptr, 10);
FixRealStrtolEndptr(nptr, &real_endptr);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result;
}
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
#if ASAN_INTERCEPT___CXA_ATEXIT
#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
static void AtCxaAtexit(void *unused) {
(void)unused;
StopInitOrderChecking();
}
#endif
#if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
#if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
#endif
ENSURE_ASAN_INITED();
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res;
}
#endif // ASAN_INTERCEPT___CXA_ATEXIT
#if ASAN_INTERCEPT_ATEXIT
INTERCEPTOR(int, atexit, void (*func)()) {
ENSURE_ASAN_INITED();
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
// Avoid calling real atexit as it is unrechable on at least on Linux.
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res;
}
#endif
#if ASAN_INTERCEPT_PTHREAD_ATFORK
extern "C" {
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
void (*child)());
};
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
void (*child)()) {
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
// on NetBSD
return _pthread_atfork(prepare, parent, child);
}
#endif
#if ASAN_INTERCEPT_VFORK
DEFINE_REAL(int, vfork)
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
@ -594,8 +633,8 @@ void InitializeAsanInterceptors() {
InitializeSignalInterceptors();
// Intercept str* functions.
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
ASAN_INTERCEPT_FUNC(strcat);
ASAN_INTERCEPT_FUNC(strcpy);
ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup);
@ -661,6 +700,14 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(__cxa_atexit);
#endif
#if ASAN_INTERCEPT_ATEXIT
ASAN_INTERCEPT_FUNC(atexit);
#endif
#if ASAN_INTERCEPT_PTHREAD_ATFORK
ASAN_INTERCEPT_FUNC(pthread_atfork);
#endif
#if ASAN_INTERCEPT_VFORK
ASAN_INTERCEPT_FUNC(vfork);
#endif

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_interceptors.cc
// ASan-private header for asan_interceptors.cpp
//===----------------------------------------------------------------------===//
#ifndef ASAN_INTERCEPTORS_H
#define ASAN_INTERCEPTORS_H
@ -99,6 +99,12 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT___CXA_ATEXIT 0
#endif
#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
#else
# define ASAN_INTERCEPT_ATEXIT 0
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
# define ASAN_INTERCEPT___STRDUP 1
#else
@ -112,6 +118,12 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_VFORK 0
#endif
#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
#else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
#endif
DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
DECLARE_REAL(char*, strchr, const char *str, int c)
DECLARE_REAL(SIZE_T, strlen, const char *s)

View File

@ -1,4 +1,4 @@
//===-- asan_interceptors_memintrinsics.cc --------------------------------===//
//===-- asan_interceptors_memintrinsics.cpp -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -16,7 +16,7 @@
#include "asan_stack.h"
#include "asan_suppressions.h"
using namespace __asan; // NOLINT
using namespace __asan;
void *__asan_memcpy(void *to, const void *from, uptr size) {
ASAN_MEMCPY_IMPL(nullptr, to, from, size);

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_memintrin.cc
// ASan-private header for asan_interceptors_memintrinsics.cpp
//===---------------------------------------------------------------------===//
#ifndef ASAN_MEMINTRIN_H
#define ASAN_MEMINTRIN_H

View File

@ -61,29 +61,29 @@ using __sanitizer::StackTrace;
void AsanInitFromRtl();
// asan_win.cc
// asan_win.cpp
void InitializePlatformExceptionHandlers();
// Returns whether an address is a valid allocated system heap block.
// 'addr' must point to the beginning of the block.
bool IsSystemHeapAddress(uptr addr);
// asan_rtl.cc
// asan_rtl.cpp
void PrintAddressSpaceLayout();
void NORETURN ShowStatsAndAbort();
// asan_shadow_setup.cc
// asan_shadow_setup.cpp
void InitializeShadowMemory();
// asan_malloc_linux.cc / asan_malloc_mac.cc
// asan_malloc_linux.cpp / asan_malloc_mac.cpp
void ReplaceSystemMalloc();
// asan_linux.cc / asan_mac.cc / asan_rtems.cc / asan_win.cc
// asan_linux.cpp / asan_mac.cpp / asan_rtems.cpp / asan_win.cpp
uptr FindDynamicShadowStart();
void *AsanDoesNotSupportStaticLinkage();
void AsanCheckDynamicRTPrereqs();
void AsanCheckIncompatibleRT();
// asan_thread.cc
// asan_thread.cpp
AsanThread *CreateMainThread();
// Support function for __asan_(un)register_image_globals. Searches for the

View File

@ -1,4 +1,4 @@
//===-- asan_linux.cc -----------------------------------------------------===//
//===-- asan_linux.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_mac.cc -------------------------------------------------------===//
//===-- asan_mac.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -205,7 +205,7 @@ void asan_dispatch_call_block_and_release(void *block) {
} // namespace __asan
using namespace __asan; // NOLINT
using namespace __asan;
// Wrap |ctxt| and |func| into an asan_block_context_t.
// The caller retains control of the allocated context.

View File

@ -1,4 +1,4 @@
//===-- asan_malloc_linux.cc ----------------------------------------------===//
//===-- asan_malloc_linux.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -27,7 +27,7 @@
#include "asan_stack.h"
// ---------------------- Replacement functions ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
static uptr allocated_for_dlsym;
static uptr last_dlsym_alloc_size_in_words;

View File

@ -1,4 +1,4 @@
//===-- asan_malloc_mac.cc ------------------------------------------------===//
//===-- asan_malloc_mac.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_malloc_win.cc ------------------------------------------------===//
//===-- asan_malloc_win.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -54,7 +54,7 @@ size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
}
using namespace __asan; // NOLINT
using namespace __asan;
// MT: Simply defining functions with the same signature in *.obj
// files overrides the standard functions in the CRT.
@ -528,10 +528,11 @@ void ReplaceSystemMalloc() {
(uptr)WRAP(RtlAllocateHeap),
(uptr *)&REAL(RtlAllocateHeap));
} else {
#define INTERCEPT_UCRT_FUNCTION(func) \
if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll", \
"api-ms-win-core-heap-l1-1-0.dll", func)) \
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func);
#define INTERCEPT_UCRT_FUNCTION(func) \
if (!INTERCEPT_FUNCTION_DLLIMPORT( \
"ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) { \
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
}
INTERCEPT_UCRT_FUNCTION(HeapAlloc);
INTERCEPT_UCRT_FUNCTION(HeapFree);
INTERCEPT_UCRT_FUNCTION(HeapReAlloc);

View File

@ -1,4 +1,4 @@
//===-- asan_memory_profile.cc.cc -----------------------------------------===//
//===-- asan_memory_profile.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_interceptors.cc ----------------------------------------------===//
//===-- asan_interceptors.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -48,7 +48,7 @@ COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
#endif
using namespace __asan; // NOLINT
using namespace __asan;
// FreeBSD prior v9.2 have wrong definition of 'size_t'.
// http://svnweb.freebsd.org/base?view=revision&revision=232261

View File

@ -1,4 +1,4 @@
//===-- asan_poisoning.cc -------------------------------------------------===//
//===-- asan_poisoning.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -92,7 +92,7 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// Current implementation of __asan_(un)poison_memory_region doesn't check
// that user program (un)poisons the memory it owns. It poisons memory

View File

@ -1,4 +1,4 @@
//===-- asan_posix.cc -----------------------------------------------------===//
//===-- asan_posix.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_preinit.cc ---------------------------------------------------===//
//===-- asan_preinit.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_premap_shadow.cc ---------------------------------------------===//
//===-- asan_premap_shadow.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- asan_report.cc ----------------------------------------------------===//
//===-- asan_report.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -410,8 +410,12 @@ static bool IsInvalidPointerPair(uptr a1, uptr a2) {
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
switch (flags()->detect_invalid_pointer_pairs) {
case 0 : return;
case 1 : if (p1 == nullptr || p2 == nullptr) return; break;
case 0:
return;
case 1:
if (p1 == nullptr || p2 == nullptr)
return;
break;
}
uptr a1 = reinterpret_cast<uptr>(p1);
@ -472,7 +476,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
} // namespace __asan
// --------------------------- Interface --------------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
uptr access_size, u32 exp) {

View File

@ -1,4 +1,4 @@
//===-- asan_rtems.cc -----------------------------------------------------===//
//===-- asan_rtems.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -181,11 +181,11 @@ static void ThreadStartHook(void *hook, uptr os_id) {
asanThreadRegistry().GetThreadLocked(thread->tid())->status;
DCHECK(status == ThreadStatusCreated || status == ThreadStatusRunning);
// Determine whether we are starting or restarting the thread.
if (status == ThreadStatusCreated)
if (status == ThreadStatusCreated) {
// In lieu of AsanThread::ThreadStart.
asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
nullptr);
else {
} else {
// In a thread restart, a thread may resume execution at an
// arbitrary function entry point, with its stack and TLS state
// reset. We unpoison the stack in that case.

View File

@ -1,4 +1,4 @@
//===-- asan_rtl.cc -------------------------------------------------------===//
//===-- asan_rtl.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -542,7 +542,7 @@ void AsanInitFromRtl() {
// (and thus normal initializers from .preinit_array or modules haven't run).
class AsanInitializer {
public: // NOLINT
public:
AsanInitializer() {
AsanInitFromRtl();
}
@ -554,7 +554,7 @@ static AsanInitializer asan_initializer;
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
void NOINLINE __asan_handle_no_return() {
if (asan_init_is_running)

View File

@ -43,7 +43,7 @@ struct ScarinessScoreBase {
internal_strlcat(descr, "-", sizeof(descr));
internal_strlcat(descr, reason, sizeof(descr));
score += add_to_score;
};
}
int GetScore() const { return score; }
const char *GetDescription() const { return descr; }
void Print() const {

View File

@ -1,4 +1,4 @@
//===-- asan_shadow_setup.cc ----------------------------------------------===//
//===-- asan_shadow_setup.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -13,7 +13,7 @@
#include "sanitizer_common/sanitizer_platform.h"
// asan_fuchsia.cc and asan_rtems.cc have their own
// asan_fuchsia.cpp and asan_rtems.cpp have their own
// InitializeShadowMemory implementation.
#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
@ -30,14 +30,13 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
uptr size = end - beg + 1;
DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
if (!MmapFixedNoReserve(beg, size, name)) {
if (!MmapFixedSuperNoReserve(beg, size, name)) {
Report(
"ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
"Perhaps you're using ulimit -v\n",
size);
Abort();
}
if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size);
if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
}

View File

@ -1,4 +1,4 @@
//===-- asan_stack.cc -----------------------------------------------------===//
//===-- asan_stack.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_stack.cc.
// ASan-private header for asan_stack.cpp.
//===----------------------------------------------------------------------===//
#ifndef ASAN_STACK_H

View File

@ -1,4 +1,4 @@
//===-- asan_stats.cc -----------------------------------------------------===//
//===-- asan_stats.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -133,7 +133,7 @@ static void PrintAccumulatedStats() {
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
uptr __sanitizer_get_current_allocated_bytes() {
AsanStats stats;

View File

@ -1,4 +1,4 @@
//===-- asan_suppressions.cc ----------------------------------------------===//
//===-- asan_suppressions.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -36,7 +36,7 @@ SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx);
suppression_ctx = new (suppression_placeholder) // NOLINT
suppression_ctx = new (suppression_placeholder)
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__asan_default_suppressions)

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_suppressions.cc.
// ASan-private header for asan_suppressions.cpp.
//===----------------------------------------------------------------------===//
#ifndef ASAN_SUPPRESSIONS_H
#define ASAN_SUPPRESSIONS_H

View File

@ -1,4 +1,4 @@
//===-- asan_thread.cc ----------------------------------------------------===//
//===-- asan_thread.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -367,8 +367,9 @@ uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
} else if (has_fake_stack()) {
bottom = fake_stack()->AddrIsInFakeStack(addr);
CHECK(bottom);
} else
} else {
return 0;
}
uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
@ -505,7 +506,7 @@ void EnsureMainThreadIDIsCorrect() {
} // namespace __lsan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE

View File

@ -8,7 +8,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// ASan-private header for asan_thread.cc.
// ASan-private header for asan_thread.cpp.
//===----------------------------------------------------------------------===//
#ifndef ASAN_THREAD_H

View File

@ -1,4 +1,4 @@
//===-- asan_win.cc -------------------------------------------------------===//
//===-- asan_win.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -29,7 +29,7 @@
#include "sanitizer_common/sanitizer_win.h"
#include "sanitizer_common/sanitizer_win_defs.h"
using namespace __asan; // NOLINT
using namespace __asan;
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
@ -106,7 +106,7 @@ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler,
_EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
_DISPATCHER_CONTEXT *d) { // NOLINT
_DISPATCHER_CONTEXT *d) {
CHECK(REAL(__C_specific_handler));
__asan_handle_no_return();
return REAL(__C_specific_handler)(a, b, c, d);
@ -362,7 +362,7 @@ bool HandleDlopenInit() {
// beginning of C++ initialization. We set our priority to XCAB to run
// immediately after the CRT runs. This way, our exception filter is called
// first and we can delegate to their filter if appropriate.
#pragma section(".CRT$XCAB", long, read) // NOLINT
#pragma section(".CRT$XCAB", long, read)
__declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
__asan_set_seh_filter;
@ -375,7 +375,7 @@ static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
__asan_init();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
void *, unsigned long, void *) = asan_thread_init;
#endif
@ -389,7 +389,7 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
}
}
#pragma section(".CRT$XLY", long, read) // NOLINT
#pragma section(".CRT$XLY", long, read)
__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
void *, unsigned long, void *) = asan_thread_exit;

View File

@ -1,4 +1,4 @@
//===-- asan_win_dll_thunk.cc ---------------------------------------------===//
//===-- asan_win_dll_thunk.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -54,7 +54,7 @@ INTERCEPT_WRAP_W_W(_expand_dbg)
// TODO(timurrrr): Might want to add support for _aligned_* allocation
// functions to detect a bit more bugs. Those functions seem to wrap malloc().
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
INTERCEPT_LIBRARY_FUNCTION(atoi);
INTERCEPT_LIBRARY_FUNCTION(atol);
@ -67,10 +67,10 @@ INTERCEPT_LIBRARY_FUNCTION(memcmp);
INTERCEPT_LIBRARY_FUNCTION(memcpy);
INTERCEPT_LIBRARY_FUNCTION(memmove);
INTERCEPT_LIBRARY_FUNCTION(memset);
INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT
INTERCEPT_LIBRARY_FUNCTION(strcat);
INTERCEPT_LIBRARY_FUNCTION(strchr);
INTERCEPT_LIBRARY_FUNCTION(strcmp);
INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT
INTERCEPT_LIBRARY_FUNCTION(strcpy);
INTERCEPT_LIBRARY_FUNCTION(strcspn);
INTERCEPT_LIBRARY_FUNCTION(strdup);
INTERCEPT_LIBRARY_FUNCTION(strlen);
@ -135,7 +135,7 @@ static int asan_dll_thunk_init() {
return 0;
}
#pragma section(".CRT$XIB", long, read) // NOLINT
#pragma section(".CRT$XIB", long, read)
__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
static void WINAPI asan_thread_init(void *mod, unsigned long reason,
@ -143,7 +143,7 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init;

View File

@ -1,4 +1,4 @@
//===-- asan_win_dynamic_runtime_thunk.cc ---------------------------------===//
//===-- asan_win_dynamic_runtime_thunk.cpp --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -32,12 +32,12 @@
#include "asan_interface.inc"
// First, declare CRT sections we'll be using in this file
#pragma section(".CRT$XIB", long, read) // NOLINT
#pragma section(".CRT$XID", long, read) // NOLINT
#pragma section(".CRT$XCAB", long, read) // NOLINT
#pragma section(".CRT$XTW", long, read) // NOLINT
#pragma section(".CRT$XTY", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XIB", long, read)
#pragma section(".CRT$XID", long, read)
#pragma section(".CRT$XCAB", long, read)
#pragma section(".CRT$XTW", long, read)
#pragma section(".CRT$XTY", long, read)
#pragma section(".CRT$XLAB", long, read)
////////////////////////////////////////////////////////////////////////////////
// Define a copy of __asan_option_detect_stack_use_after_return that should be
@ -114,7 +114,7 @@ int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
////////////////////////////////////////////////////////////////////////////////
// ASan SEH handling.
// We need to set the ASan-specific SEH handler at the end of CRT initialization
// of each module (see also asan_win.cc).
// of each module (see also asan_win.cpp).
extern "C" {
__declspec(dllimport) int __asan_set_seh_filter();
static int SetSEHFilter() { return __asan_set_seh_filter(); }

View File

@ -1,4 +1,4 @@
//===-- asan_win_weak_interception.cc -------------------------------------===//
//===-- asan_win_weak_interception.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -0,0 +1,59 @@
//===----- lib/aarch64/fp_mode.c - Floaing-point mode utilities ---*- 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
//
//===----------------------------------------------------------------------===//
#include <stdint.h>
#include "../fp_mode.h"
#define AARCH64_TONEAREST 0x0
#define AARCH64_UPWARD 0x1
#define AARCH64_DOWNWARD 0x2
#define AARCH64_TOWARDZERO 0x3
#define AARCH64_RMODE_MASK (AARCH64_TONEAREST | AARCH64_UPWARD | \
AARCH64_DOWNWARD | AARCH64_TOWARDZERO)
#define AARCH64_RMODE_SHIFT 22
#define AARCH64_INEXACT 0x10
#ifndef __ARM_FP
// For soft float targets, allow changing rounding mode by overriding the weak
// __aarch64_fe_default_rmode symbol.
FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode = FE_TONEAREST;
#endif
FE_ROUND_MODE __fe_getround() {
#ifdef __ARM_FP
uint64_t fpcr;
__asm__ __volatile__("mrs %0, fpcr" : "=r" (fpcr));
fpcr = fpcr >> AARCH64_RMODE_SHIFT & AARCH64_RMODE_MASK;
switch (fpcr) {
case AARCH64_UPWARD:
return FE_UPWARD;
case AARCH64_DOWNWARD:
return FE_DOWNWARD;
case AARCH64_TOWARDZERO:
return FE_TOWARDZERO;
case AARCH64_TONEAREST:
default:
return FE_TONEAREST;
}
#else
return __aarch64_fe_default_rmode;
#endif
}
int __fe_raise_inexact() {
#ifdef __ARM_FP
uint64_t fpsr;
__asm__ __volatile__("mrs %0, fpsr" : "=r" (fpsr));
__asm__ __volatile__("msr fpsr, %0" : : "ri" (fpsr | AARCH64_INEXACT));
return 0;
#else
return 0;
#endif
}

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements double-precision soft-float addition with the IEEE-754
// default rounding (to nearest, ties to even).
// This file implements double-precision soft-float addition.
//
//===----------------------------------------------------------------------===//

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float addition with the IEEE-754
// default rounding (to nearest, ties to even).
// This file implements single-precision soft-float addition.
//
//===----------------------------------------------------------------------===//

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements quad-precision soft-float addition with the IEEE-754
// default rounding (to nearest, ties to even).
// This file implements quad-precision soft-float addition.
//
//===----------------------------------------------------------------------===//
@ -17,7 +16,7 @@
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
#include "fp_add_impl.inc"
COMPILER_RT_ABI long double __addtf3(long double a, long double b) {
COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b) {
return __addXf3__(a, b);
}

View File

@ -0,0 +1,59 @@
//===----- lib/arm/fp_mode.c - Floaing-point mode utilities -------*- 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
//
//===----------------------------------------------------------------------===//
#include <stdint.h>
#include "../fp_mode.h"
#define ARM_TONEAREST 0x0
#define ARM_UPWARD 0x1
#define ARM_DOWNWARD 0x2
#define ARM_TOWARDZERO 0x3
#define ARM_RMODE_MASK (ARM_TONEAREST | ARM_UPWARD | \
ARM_DOWNWARD | ARM_TOWARDZERO)
#define ARM_RMODE_SHIFT 22
#define ARM_INEXACT 0x1000
#ifndef __ARM_FP
// For soft float targets, allow changing rounding mode by overriding the weak
// __arm_fe_default_rmode symbol.
FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode = FE_TONEAREST;
#endif
FE_ROUND_MODE __fe_getround() {
#ifdef __ARM_FP
uint32_t fpscr;
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
fpscr = fpscr >> ARM_RMODE_SHIFT & ARM_RMODE_MASK;
switch (fpscr) {
case ARM_UPWARD:
return FE_UPWARD;
case ARM_DOWNWARD:
return FE_DOWNWARD;
case ARM_TOWARDZERO:
return FE_TOWARDZERO;
case ARM_TONEAREST:
default:
return FE_TONEAREST;
}
#else
return __arm_fe_default_rmode;
#endif
}
int __fe_raise_inexact() {
#ifdef __ARM_FP
uint32_t fpscr;
__asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr));
__asm__ __volatile__("vmsr fpscr, %0" : : "ri" (fpscr | ARM_INEXACT));
return 0;
#else
return 0;
#endif
}

View File

@ -51,9 +51,11 @@ static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;
////////////////////////////////////////////////////////////////////////////////
#ifdef __FreeBSD__
#include <errno.h>
// clang-format off
#include <sys/types.h>
#include <machine/atomic.h>
#include <sys/umtx.h>
// clang-format on
typedef struct _usem Lock;
__inline static void unlock(Lock *l) {
__c11_atomic_store((_Atomic(uint32_t) *)&l->_count, 1, __ATOMIC_RELEASE);

View File

@ -23,8 +23,10 @@ uintptr_t GetCurrentProcess(void);
#endif
#if defined(__FreeBSD__) && defined(__arm__)
#include <machine/sysarch.h>
// clang-format off
#include <sys/types.h>
#include <machine/sysarch.h>
// clang-format on
#endif
#if defined(__NetBSD__) && defined(__arm__)
@ -32,54 +34,16 @@ uintptr_t GetCurrentProcess(void);
#endif
#if defined(__OpenBSD__) && defined(__mips__)
#include <machine/sysarch.h>
// clang-format off
#include <sys/types.h>
#include <machine/sysarch.h>
// clang-format on
#endif
#if defined(__linux__) && defined(__mips__)
#include <sys/cachectl.h>
#include <sys/syscall.h>
#include <unistd.h>
#if defined(__ANDROID__) && defined(__LP64__)
// clear_mips_cache - Invalidates instruction cache for Mips.
static void clear_mips_cache(const void *Addr, size_t Size) {
__asm__ volatile(
".set push\n"
".set noreorder\n"
".set noat\n"
"beq %[Size], $zero, 20f\n" // If size == 0, branch around.
"nop\n"
"daddu %[Size], %[Addr], %[Size]\n" // Calculate end address + 1
"rdhwr $v0, $1\n" // Get step size for SYNCI.
// $1 is $HW_SYNCI_Step
"beq $v0, $zero, 20f\n" // If no caches require
// synchronization, branch
// around.
"nop\n"
"10:\n"
"synci 0(%[Addr])\n" // Synchronize all caches around
// address.
"daddu %[Addr], %[Addr], $v0\n" // Add step size.
"sltu $at, %[Addr], %[Size]\n" // Compare current with end
// address.
"bne $at, $zero, 10b\n" // Branch if more to do.
"nop\n"
"sync\n" // Clear memory hazards.
"20:\n"
"bal 30f\n"
"nop\n"
"30:\n"
"daddiu $ra, $ra, 12\n" // $ra has a value of $pc here.
// Add offset of 12 to point to the
// instruction after the last nop.
//
"jr.hb $ra\n" // Return, clearing instruction
// hazards.
"nop\n"
".set pop\n"
: [ Addr ] "+r"(Addr), [ Size ] "+r"(Size)::"at", "ra", "v0", "memory");
}
#endif
#endif
// The compiler generates calls to __clear_cache() when creating
@ -123,17 +87,7 @@ void __clear_cache(void *start, void *end) {
#elif defined(__linux__) && defined(__mips__)
const uintptr_t start_int = (uintptr_t)start;
const uintptr_t end_int = (uintptr_t)end;
#if defined(__ANDROID__) && defined(__LP64__)
// Call synci implementation for short address range.
const uintptr_t address_range_limit = 256;
if ((end_int - start_int) <= address_range_limit) {
clear_mips_cache(start, (end_int - start_int));
} else {
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
}
#else
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
#endif
#elif defined(__mips__) && defined(__OpenBSD__)
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
#elif defined(__aarch64__) && !defined(__APPLE__)
@ -173,6 +127,16 @@ void __clear_cache(void *start, void *end) {
for (uintptr_t line = start_line; line < end_line; line += line_size)
__asm__ volatile("icbi 0, %0" : : "r"(line));
__asm__ volatile("isync");
#elif defined(__sparc__)
const size_t dword_size = 8;
const size_t len = (uintptr_t)end - (uintptr_t)start;
const uintptr_t mask = ~(dword_size - 1);
const uintptr_t start_dword = ((uintptr_t)start) & mask;
const uintptr_t end_dword = ((uintptr_t)start + len + dword_size - 1) & mask;
for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size)
__asm__ volatile("flush %0" : : "r"(dword));
#else
#if __APPLE__
// On Darwin, sys_icache_invalidate() provides this functionality

View File

@ -121,7 +121,8 @@ enum ProcessorFeatures {
FEATURE_GFNI,
FEATURE_VPCLMULQDQ,
FEATURE_AVX512VNNI,
FEATURE_AVX512BITALG
FEATURE_AVX512BITALG,
FEATURE_AVX512BF16
};
// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
@ -415,8 +416,8 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
default: // Unknown family 6 CPU.
break;
break;
}
break;
default:
break; // Unknown.
}
@ -582,6 +583,11 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX5124FMAPS);
bool HasLeaf7Subleaf1 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512BF16);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);

View File

@ -213,7 +213,7 @@ COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) {
// Round.
absResult += round;
// Insert the sign and return.
const long double result = fromRep(absResult | quotientSign);
const fp_t result = fromRep(absResult | quotientSign);
return result;
}
}

View File

@ -26,12 +26,23 @@
#define EMUTLS_SKIP_DESTRUCTOR_ROUNDS 0
#endif
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC raises a warning about a nonstandard extension being used for the 0
// sized element in this array. Disable this for warn-as-error builds.
#pragma warning(push)
#pragma warning(disable : 4206)
#endif
typedef struct emutls_address_array {
uintptr_t skip_destructor_rounds;
uintptr_t size; // number of elements in the 'data' array
void *data[];
} emutls_address_array;
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif
static void emutls_shutdown(emutls_address_array *array);
#ifndef _WIN32

View File

@ -14,7 +14,7 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI long double __extenddftf2(double a) {
COMPILER_RT_ABI fp_t __extenddftf2(double a) {
return __extendXfYf2__(a);
}

View File

@ -14,7 +14,7 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI long double __extendsftf2(float a) {
COMPILER_RT_ABI fp_t __extendsftf2(float a) {
return __extendXfYf2__(a);
}

View File

@ -25,6 +25,13 @@
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
// mmmm mmmm mmmm
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC throws a warning about 'unitialized variable use' here,
// disable it for builds that warn-as-error
#pragma warning(push)
#pragma warning(disable : 4700)
#endif
COMPILER_RT_ABI du_int __fixunsxfdi(long double a) {
long_double_bits fb;
fb.f = a;
@ -36,4 +43,8 @@ COMPILER_RT_ABI du_int __fixunsxfdi(long double a) {
return fb.u.low.all >> (63 - e);
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif
#endif //!_ARCH_PPC

View File

@ -25,6 +25,13 @@
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
// mmmm mmmm mmmm
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC throws a warning about 'unitialized variable use' here,
// disable it for builds that warn-as-error
#pragma warning(push)
#pragma warning(disable : 4700)
#endif
COMPILER_RT_ABI su_int __fixunsxfsi(long double a) {
long_double_bits fb;
fb.f = a;
@ -36,4 +43,8 @@ COMPILER_RT_ABI su_int __fixunsxfsi(long double a) {
return fb.u.low.s.high >> (31 - e);
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif
#endif // !_ARCH_PPC

View File

@ -24,6 +24,13 @@
// eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
// mmmm mmmm mmmm
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC throws a warning about 'unitialized variable use' here,
// disable it for builds that warn-as-error
#pragma warning(push)
#pragma warning(disable : 4700)
#endif
COMPILER_RT_ABI di_int __fixxfdi(long double a) {
const di_int di_max = (di_int)((~(du_int)0) / 2);
const di_int di_min = -di_max - 1;
@ -40,4 +47,8 @@ COMPILER_RT_ABI di_int __fixxfdi(long double a) {
return (r ^ s) - s;
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif
#endif // !_ARCH_PPC

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "fp_lib.h"
#include "fp_mode.h"
static __inline fp_t __addXf3__(fp_t a, fp_t b) {
rep_t aRep = toRep(a);
@ -93,7 +94,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
const unsigned int align = aExponent - bExponent;
if (align) {
if (align < typeWidth) {
const bool sticky = bSignificand << (typeWidth - align);
const bool sticky = (bSignificand << (typeWidth - align)) != 0;
bSignificand = bSignificand >> align | sticky;
} else {
bSignificand = 1; // Set the sticky bit. b is known to be non-zero.
@ -132,7 +133,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
// The result is denormal before rounding. The exponent is zero and we
// need to shift the significand.
const int shift = 1 - aExponent;
const bool sticky = aSignificand << (typeWidth - shift);
const bool sticky = (aSignificand << (typeWidth - shift)) != 0;
aSignificand = aSignificand >> shift | sticky;
aExponent = 0;
}
@ -149,9 +150,23 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
// Perform the final rounding. The result may overflow to infinity, but
// that is the correct result in that case.
if (roundGuardSticky > 0x4)
result++;
if (roundGuardSticky == 0x4)
result += result & 1;
switch (__fe_getround()) {
case FE_TONEAREST:
if (roundGuardSticky > 0x4)
result++;
if (roundGuardSticky == 0x4)
result += result & 1;
break;
case FE_DOWNWARD:
if (resultSign && roundGuardSticky) result++;
break;
case FE_UPWARD:
if (!resultSign && roundGuardSticky) result++;
break;
case FE_TOWARDZERO:
break;
}
if (roundGuardSticky)
__fe_raise_inexact();
return fromRep(result);
}

View File

@ -245,7 +245,7 @@ static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo,
unsigned int count) {
if (count < typeWidth) {
const bool sticky = *lo << (typeWidth - count);
const bool sticky = (*lo << (typeWidth - count)) != 0;
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
*hi = *hi >> count;
} else if (count < 2 * typeWidth) {

View File

@ -0,0 +1,24 @@
//===----- lib/fp_mode.c - Floaing-point environment mode utilities --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 provides a default implementation of fp_mode.h for architectures
// that does not support or does not have an implementation of floating point
// environment mode.
//
//===----------------------------------------------------------------------===//
#include "fp_mode.h"
// IEEE-754 default rounding (to nearest, ties to even).
FE_ROUND_MODE __fe_getround() {
return FE_TONEAREST;
}
int __fe_raise_inexact() {
return 0;
}

View File

@ -0,0 +1,29 @@
//===----- lib/fp_mode.h - Floaing-point environment mode utilities --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 not part of the interface of this library.
//
// This file defines an interface for accessing hardware floating point
// environment mode.
//
//===----------------------------------------------------------------------===//
#ifndef FP_MODE
#define FP_MODE
typedef enum {
FE_TONEAREST,
FE_DOWNWARD,
FE_UPWARD,
FE_TOWARDZERO
} FE_ROUND_MODE;
FE_ROUND_MODE __fe_getround();
int __fe_raise_inexact();
#endif // FP_MODE_H

View File

@ -113,7 +113,7 @@ static __inline dst_t __truncXfYf2__(src_t a) {
if (shift > srcSigBits) {
absResult = 0;
} else {
const bool sticky = significand << (srcBits - shift);
const bool sticky = (significand << (srcBits - shift)) != 0;
src_rep_t denormalizedSignificand = significand >> shift | sticky;
absResult = denormalizedSignificand >> (srcSigBits - dstSigBits);
const src_rep_t roundBits = denormalizedSignificand & roundMask;

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements double-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
// This file implements double-precision soft-float subtraction.
//
//===----------------------------------------------------------------------===//

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
// This file implements single-precision soft-float subtraction.
//
//===----------------------------------------------------------------------===//

View File

@ -6,8 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements quad-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
// This file implements quad-precision soft-float subtraction.
//
//===----------------------------------------------------------------------===//

View File

@ -17,6 +17,13 @@
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC throws a warning about mod 0 here, disable it for builds that
// warn-as-error
#pragma warning(push)
#pragma warning(disable : 4724)
#endif
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
@ -187,3 +194,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
*rem = r.all;
return q.all;
}
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(pop)
#endif

View File

@ -1,4 +1,4 @@
//===-- dfsan.cc ----------------------------------------------------------===//
//===-- dfsan.cpp ---------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -1,4 +1,4 @@
//===-- dfsan.cc ----------------------------------------------------------===//
//===-- dfsan.cpp ---------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -505,7 +505,7 @@ int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
SANITIZER_INTERFACE_ATTRIBUTE
char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
dfsan_label src_label, dfsan_label *ret_label) {
char *ret = strcpy(dest, src);
char *ret = strcpy(dest, src); // NOLINT
if (ret) {
internal_memcpy(shadow_for(dest), shadow_for(src),
sizeof(dfsan_label) * (strlen(src) + 1));

View File

@ -1,4 +1,4 @@
//===-- dfsan_interceptors.cc ---------------------------------------------===//
//===-- dfsan_interceptors.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View File

@ -15,9 +15,6 @@
#include "FuzzerDefs.h"
#if LIBFUZZER_MSVC
#if !defined(_M_ARM) && !defined(_M_X64)
#error "_BitScanReverse64 unavailable on this platform so MSVC is unsupported."
#endif
#include <intrin.h>
#include <cstdint>
#include <cstdlib>
@ -40,7 +37,18 @@ inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); }
// outside of Windows.
inline uint32_t Clzll(uint64_t X) {
unsigned long LeadZeroIdx = 0;
#if !defined(_M_ARM) && !defined(_M_X64)
// Scan the high 32 bits.
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X >> 32)))
return static_cast<int>(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB.
// Scan the low 32 bits.
if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X)))
return static_cast<int>(63 - LeadZeroIdx);
#else
if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
#endif
return 64;
}
@ -50,7 +58,13 @@ inline uint32_t Clz(uint32_t X) {
return 32;
}
inline int Popcountll(unsigned long long X) { return __popcnt64(X); }
inline int Popcountll(unsigned long long X) {
#if !defined(_M_ARM) && !defined(_M_X64)
return __popcnt(X) + __popcnt(X >> 32);
#else
return __popcnt64(X);
#endif
}
} // namespace fuzzer

View File

@ -15,10 +15,11 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <set>
#include <memory>
// Platform detection.
#ifdef __linux__

View File

@ -708,7 +708,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.FeaturesDir = Flags.features_dir;
if (Flags.collect_data_flow)
Options.CollectDataFlow = Flags.collect_data_flow;
Options.LazyCounters = Flags.lazy_counters;
if (Flags.stop_file)
Options.StopFile = Flags.stop_file;

View File

@ -16,12 +16,12 @@
// Optional user functions
EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);
EXT_FUNC(LLVMFuzzerCustomMutator, size_t,
(uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),
(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed),
false);
EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
(const uint8_t * Data1, size_t Size1,
const uint8_t * Data2, size_t Size2,
uint8_t * Out, size_t MaxOutSize, unsigned int Seed),
(const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize, unsigned int Seed),
false);
// Sanitizer functions
@ -33,8 +33,9 @@ EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
(void (*malloc_hook)(const volatile void *, size_t),
void (*free_hook)(const volatile void *)),
false);
EXT_FUNC(__sanitizer_log_write, void, (const char *buf, size_t len), false);
EXT_FUNC(__sanitizer_purge_allocator, void, (), false);
EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t, size_t), false);
EXT_FUNC(__sanitizer_print_memory_profile, void, (size_t, size_t), false);
EXT_FUNC(__sanitizer_print_stack_trace, void, (), true);
EXT_FUNC(__sanitizer_symbolize_pc, void,
(void *, const char *fmt, char *out_buf, size_t out_buf_size), false);

View File

@ -123,9 +123,6 @@ FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.")
FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.")
FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.")
FUZZER_FLAG_INT(lazy_counters, 0, "If 1, a performance optimization is"
"enabled for the 8bit inline counters. "
"Requires that libFuzzer successfully installs its SEGV handler")
FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
"if 2, close stderr; if 3, close both. "
"Be careful, this will also close e.g. stderr of asan.")

View File

@ -98,7 +98,8 @@ class Fuzzer {
void ReportNewCoverage(InputInfo *II, const Unit &U);
void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);
void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0,
size_t Features = 0);
void PrintStatusForNewUnit(const Unit &U, const char *Text);
void CheckExitOnSrcPosOrItem();

View File

@ -273,9 +273,9 @@ void Fuzzer::InterruptCallback() {
NO_SANITIZE_MEMORY
void Fuzzer::AlarmCallback() {
assert(Options.UnitTimeoutSec > 0);
// In Windows Alarm callback is executed by a different thread.
// In Windows and Fuchsia, Alarm callback is executed by a different thread.
// NetBSD's current behavior needs this change too.
#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA
if (!InFuzzingThread())
return;
#endif
@ -319,14 +319,15 @@ void Fuzzer::RssLimitCallback() {
_Exit(Options.OOMExitCode); // Stop right now.
}
void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units,
size_t Features) {
size_t ExecPerSec = execPerSec();
if (!Options.Verbosity)
return;
Printf("#%zd\t%s", TotalNumberOfRuns, Where);
if (size_t N = TPC.GetTotalPCCoverage())
Printf(" cov: %zd", N);
if (size_t N = Corpus.NumFeatures())
if (size_t N = Features ? Features : Corpus.NumFeatures())
Printf(" ft: %zd", N);
if (!Corpus.empty()) {
Printf(" corp: %zd", Corpus.NumActiveUnits());
@ -512,10 +513,12 @@ size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
}
void Fuzzer::CrashOnOverwrittenData() {
Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
Printf("==%d== ERROR: libFuzzer: fuzz target overwrites its const input\n",
GetPid());
PrintStackTrace();
Printf("SUMMARY: libFuzzer: overwrites-const-input\n");
DumpCurrentUnit("crash-");
Printf("SUMMARY: libFuzzer: out-of-memory\n");
PrintFinalStats();
_Exit(Options.ErrorExitCode); // Stop right now.
}
@ -739,10 +742,6 @@ void Fuzzer::ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles) {
uint8_t dummy = 0;
ExecuteCallback(&dummy, 0);
// Protect lazy counters here, after the once-init code has been executed.
if (Options.LazyCounters)
TPC.ProtectLazyCounters();
if (CorporaFiles.empty()) {
Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
Unit U({'\n'}); // Valid ASCII input.

View File

@ -19,6 +19,7 @@
#include <iterator>
#include <set>
#include <sstream>
#include <unordered_set>
namespace fuzzer {
@ -210,6 +211,9 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
Set<size_t> AllFeatures;
auto PrintStatsWrapper = [this, &AllFeatures](const char* Where) {
this->PrintStats(Where, "\n", 0, AllFeatures.size());
};
Set<const TracePC::PCTableEntry *> AllPCs;
for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
Fuzzer::MaybeExitGracefully();
@ -218,7 +222,7 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
U.resize(MaxInputLen);
U.shrink_to_fit();
}
std::ostringstream StartedLine;
// Write the pre-run marker.
OF << "STARTED " << i << " " << U.size() << "\n";
OF.flush(); // Flush is important since Command::Execute may crash.
@ -238,7 +242,9 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
TPC.UpdateObservedPCs();
// Show stats.
if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)))
PrintStats("pulse ");
PrintStatsWrapper("pulse ");
if (TotalNumberOfRuns == M.NumFilesInFirstCorpus)
PrintStatsWrapper("LOADED");
// Write the post-run marker and the coverage.
OF << "FT " << i;
for (size_t F : UniqFeatures)
@ -252,25 +258,42 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
OF << "\n";
OF.flush();
}
PrintStats("DONE ");
PrintStatsWrapper("DONE ");
}
static void WriteNewControlFile(const std::string &CFPath,
const Vector<SizedFile> &OldCorpus,
const Vector<SizedFile> &NewCorpus) {
static size_t WriteNewControlFile(const std::string &CFPath,
const Vector<SizedFile> &OldCorpus,
const Vector<SizedFile> &NewCorpus,
const Vector<MergeFileInfo> &KnownFiles) {
std::unordered_set<std::string> FilesToSkip;
for (auto &SF: KnownFiles)
FilesToSkip.insert(SF.Name);
Vector<std::string> FilesToUse;
auto MaybeUseFile = [=, &FilesToUse](std::string Name) {
if (FilesToSkip.find(Name) == FilesToSkip.end())
FilesToUse.push_back(Name);
};
for (auto &SF: OldCorpus)
MaybeUseFile(SF.File);
auto FilesToUseFromOldCorpus = FilesToUse.size();
for (auto &SF: NewCorpus)
MaybeUseFile(SF.File);
RemoveFile(CFPath);
std::ofstream ControlFile(CFPath);
ControlFile << (OldCorpus.size() + NewCorpus.size()) << "\n";
ControlFile << OldCorpus.size() << "\n";
for (auto &SF: OldCorpus)
ControlFile << SF.File << "\n";
for (auto &SF: NewCorpus)
ControlFile << SF.File << "\n";
ControlFile << FilesToUse.size() << "\n";
ControlFile << FilesToUseFromOldCorpus << "\n";
for (auto &FN: FilesToUse)
ControlFile << FN << "\n";
if (!ControlFile) {
Printf("MERGE-OUTER: failed to write to the control file: %s\n",
CFPath.c_str());
exit(1);
}
return FilesToUse.size();
}
// Outer process. Does not call the target code and thus should not fail.
@ -286,12 +309,13 @@ void CrashResistantMerge(const Vector<std::string> &Args,
bool V /*Verbose*/) {
if (NewCorpus.empty() && OldCorpus.empty()) return; // Nothing to merge.
size_t NumAttempts = 0;
Vector<MergeFileInfo> KnownFiles;
if (FileSize(CFPath)) {
VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n",
CFPath.c_str());
Merger M;
std::ifstream IF(CFPath);
if (M.Parse(IF, /*ParseCoverage=*/false)) {
if (M.Parse(IF, /*ParseCoverage=*/true)) {
VPrintf(V, "MERGE-OUTER: control file ok, %zd files total,"
" first not processed file %zd\n",
M.Files.size(), M.FirstNotProcessedFile);
@ -300,12 +324,25 @@ void CrashResistantMerge(const Vector<std::string> &Args,
"(merge has stumbled on it the last time)\n",
M.LastFailure.c_str());
if (M.FirstNotProcessedFile >= M.Files.size()) {
VPrintf(
V, "MERGE-OUTER: nothing to do, merge has been completed before\n");
exit(0);
}
// Merge has already been completed with the given merge control file.
if (M.Files.size() == OldCorpus.size() + NewCorpus.size()) {
VPrintf(
V,
"MERGE-OUTER: nothing to do, merge has been completed before\n");
exit(0);
}
NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
// Number of input files likely changed, start merge from scratch, but
// reuse coverage information from the given merge control file.
VPrintf(
V,
"MERGE-OUTER: starting merge from scratch, but reusing coverage "
"information from the given control file\n");
KnownFiles = M.Files;
} else {
// There is a merge in progress, continue.
NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
}
} else {
VPrintf(V, "MERGE-OUTER: bad control file, will overwrite it\n");
}
@ -313,10 +350,11 @@ void CrashResistantMerge(const Vector<std::string> &Args,
if (!NumAttempts) {
// The supplied control file is empty or bad, create a fresh one.
NumAttempts = OldCorpus.size() + NewCorpus.size();
VPrintf(V, "MERGE-OUTER: %zd files, %zd in the initial corpus\n",
NumAttempts, OldCorpus.size());
WriteNewControlFile(CFPath, OldCorpus, NewCorpus);
VPrintf(V, "MERGE-OUTER: "
"%zd files, %zd in the initial corpus, %zd processed earlier\n",
OldCorpus.size() + NewCorpus.size(), OldCorpus.size(),
KnownFiles.size());
NumAttempts = WriteNewControlFile(CFPath, OldCorpus, NewCorpus, KnownFiles);
}
// Execute the inner process until it passes.
@ -353,6 +391,8 @@ void CrashResistantMerge(const Vector<std::string> &Args,
VPrintf(V,
"MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n",
M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb());
M.Files.insert(M.Files.end(), KnownFiles.begin(), KnownFiles.end());
M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles);
VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added; "
"%zd new coverage edges\n",

View File

@ -75,7 +75,6 @@ struct FuzzingOptions {
bool HandleXfsz = false;
bool HandleUsr1 = false;
bool HandleUsr2 = false;
bool LazyCounters = false;
};
} // namespace fuzzer

View File

@ -67,45 +67,6 @@ void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
NumInline8bitCounters += M.Size();
}
// Mark all full page counter regions as PROT_NONE and set Enabled=false.
// The first time the instrumented code hits such a protected/disabled
// counter region we should catch a SEGV and call UnprotectLazyCounters,
// which will mark the page as PROT_READ|PROT_WRITE and set Enabled=true.
//
// Whenever other functions iterate over the counters they should ignore
// regions with Enabled=false.
void TracePC::ProtectLazyCounters() {
size_t NumPagesProtected = 0;
IterateCounterRegions([&](Module::Region &R) {
if (!R.OneFullPage) return;
if (Mprotect(R.Start, R.Stop - R.Start, false)) {
R.Enabled = false;
NumPagesProtected++;
}
});
if (NumPagesProtected)
Printf("INFO: %zd pages of counters where protected;"
" libFuzzer's SEGV handler must be installed\n",
NumPagesProtected);
}
bool TracePC::UnprotectLazyCounters(void *CounterPtr) {
// Printf("UnprotectLazyCounters: %p\n", CounterPtr);
if (!CounterPtr)
return false;
bool Done = false;
uint8_t *Addr = reinterpret_cast<uint8_t *>(CounterPtr);
IterateCounterRegions([&](Module::Region &R) {
if (!R.OneFullPage || R.Enabled || Done) return;
if (Addr >= R.Start && Addr < R.Stop)
if (Mprotect(R.Start, R.Stop - R.Start, true)) {
R.Enabled = true;
Done = true;
}
});
return Done;
}
void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start);
const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop);
@ -173,7 +134,7 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
}
/// \return the address of the next instruction.
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc`
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cpp`
ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) {
#if defined(__mips__)
return PC + 8;

View File

@ -119,9 +119,6 @@ class TracePC {
void SetFocusFunction(const std::string &FuncName);
bool ObservedFocusFunction();
void ProtectLazyCounters();
bool UnprotectLazyCounters(void *CounterPtr);
struct PCTableEntry {
uintptr_t PC, PCFlags;
};

View File

@ -52,8 +52,6 @@ void SetSignalHandler(const FuzzingOptions& Options);
void SleepSeconds(int Seconds);
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite);
unsigned long GetPid();
size_t GetPeakRSSMb();

View File

@ -305,12 +305,19 @@ void CrashHandler(zx_handle_t *Event) {
} // namespace
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
return false; // UNIMPLEMENTED
}
// Platform specific functions.
void SetSignalHandler(const FuzzingOptions &Options) {
// Make sure information from libFuzzer and the sanitizers are easy to
// reassemble. `__sanitizer_log_write` has the added benefit of ensuring the
// DSO map is always available for the symbolizer.
// A uint64_t fits in 20 chars, so 64 is plenty.
char Buf[64];
memset(Buf, 0, sizeof(Buf));
snprintf(Buf, sizeof(Buf), "==%lu== INFO: libFuzzer starting.\n", GetPid());
if (EF->__sanitizer_log_write)
__sanitizer_log_write(Buf, sizeof(Buf));
Printf("%s", Buf);
// Set up alarm handler if needed.
if (Options.UnitTimeoutSec > 0) {
std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1);
@ -400,13 +407,14 @@ int ExecuteCommand(const Command &Cmd) {
// that lacks a mutable working directory. Fortunately, when this is the case
// a mutable output directory must be specified using "-artifact_prefix=...",
// so write the log file(s) there.
// However, we don't want to apply this logic for absolute paths.
int FdOut = STDOUT_FILENO;
if (Cmd.hasOutputFile()) {
std::string Path;
if (Cmd.hasFlag("artifact_prefix"))
Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile();
else
Path = Cmd.getOutputFile();
std::string Path = Cmd.getOutputFile();
bool IsAbsolutePath = Path.length() > 1 && Path[0] == '/';
if (!IsAbsolutePath && Cmd.hasFlag("artifact_prefix"))
Path = Cmd.getFlagValue("artifact_prefix") + "/" + Path;
FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
if (FdOut == -1) {
Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),

View File

@ -37,7 +37,6 @@ static void (*upstream_segv_handler)(int, siginfo_t *, void *);
static void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
assert(si->si_signo == SIGSEGV);
if (TPC.UnprotectLazyCounters(si->si_addr)) return;
if (upstream_segv_handler)
return upstream_segv_handler(sig, si, ucontext);
Fuzzer::StaticCrashSignalCallback();
@ -98,11 +97,6 @@ void SetTimer(int Seconds) {
SetSigaction(SIGALRM, AlarmHandler);
}
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
return 0 == mprotect(Ptr, Size,
AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE);
}
void SetSignalHandler(const FuzzingOptions& Options) {
if (Options.UnitTimeoutSec > 0)
SetTimer(Options.UnitTimeoutSec / 2 + 1);

View File

@ -111,10 +111,6 @@ static TimerQ Timer;
static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
return false; // UNIMPLEMENTED
}
void SetSignalHandler(const FuzzingOptions& Options) {
HandlerOpt = &Options;

View File

@ -13,7 +13,7 @@
// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
// macro is defined before including <inttypes.h>.
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#define __STDC_FORMAT_MACROS 1
#endif
#include <assert.h>
@ -44,11 +44,12 @@ class ScopedBoolean {
bool &Bool;
};
void defaultPrintStackTrace(uintptr_t *Trace, options::Printf_t Printf) {
if (Trace[0] == 0)
void defaultPrintStackTrace(uintptr_t *Trace, size_t TraceLength,
options::Printf_t Printf) {
if (TraceLength == 0)
Printf(" <unknown (does your allocator support backtracing?)>\n");
for (size_t i = 0; Trace[i] != 0; ++i) {
for (size_t i = 0; i < TraceLength; ++i) {
Printf(" #%zu 0x%zx in <unknown>\n", i, Trace[i]);
}
Printf("\n");
@ -68,12 +69,18 @@ void GuardedPoolAllocator::AllocationMetadata::RecordAllocation(
// TODO(hctim): Ask the caller to provide the thread ID, so we don't waste
// other thread's time getting the thread ID under lock.
AllocationTrace.ThreadID = getThreadID();
AllocationTrace.TraceSize = 0;
DeallocationTrace.TraceSize = 0;
DeallocationTrace.ThreadID = kInvalidThreadID;
if (Backtrace)
Backtrace(AllocationTrace.Trace, kMaximumStackFrames);
else
AllocationTrace.Trace[0] = 0;
DeallocationTrace.Trace[0] = 0;
if (Backtrace) {
uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
size_t BacktraceLength =
Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
AllocationTrace.TraceSize = compression::pack(
UncompressedBuffer, BacktraceLength, AllocationTrace.CompressedTrace,
kStackFrameStorageBytes);
}
}
void GuardedPoolAllocator::AllocationMetadata::RecordDeallocation(
@ -81,11 +88,16 @@ void GuardedPoolAllocator::AllocationMetadata::RecordDeallocation(
IsDeallocated = true;
// Ensure that the unwinder is not called if the recursive flag is set,
// otherwise non-reentrant unwinders may deadlock.
DeallocationTrace.TraceSize = 0;
if (Backtrace && !ThreadLocals.RecursiveGuard) {
ScopedBoolean B(ThreadLocals.RecursiveGuard);
Backtrace(DeallocationTrace.Trace, kMaximumStackFrames);
} else {
DeallocationTrace.Trace[0] = 0;
uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
size_t BacktraceLength =
Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
DeallocationTrace.TraceSize = compression::pack(
UncompressedBuffer, BacktraceLength, DeallocationTrace.CompressedTrace,
kStackFrameStorageBytes);
}
DeallocationTrace.ThreadID = getThreadID();
}
@ -161,7 +173,7 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
// Ensure that signal handlers are installed as late as possible, as the class
// is not thread-safe until init() is finished, and thus a SIGSEGV may cause a
// race to members if recieved during init().
// race to members if received during init().
if (Opts.InstallSignalHandlers)
installSignalHandlers();
}
@ -373,7 +385,7 @@ void printErrorType(Error E, uintptr_t AccessPtr, AllocationMetadata *Meta,
case Error::UNKNOWN:
ErrorString = "GWP-ASan couldn't automatically determine the source of "
"the memory error. It was likely caused by a wild memory "
"access into the GWP-ASan pool. The error occured";
"access into the GWP-ASan pool. The error occurred";
break;
case Error::USE_AFTER_FREE:
ErrorString = "Use after free";
@ -442,7 +454,13 @@ void printAllocDeallocTraces(uintptr_t AccessPtr, AllocationMetadata *Meta,
Printf("0x%zx was deallocated by thread %zu here:\n", AccessPtr,
Meta->DeallocationTrace.ThreadID);
PrintBacktrace(Meta->DeallocationTrace.Trace, Printf);
uintptr_t UncompressedTrace[AllocationMetadata::kMaxTraceLengthToCollect];
size_t UncompressedLength = compression::unpack(
Meta->DeallocationTrace.CompressedTrace,
Meta->DeallocationTrace.TraceSize, UncompressedTrace,
AllocationMetadata::kMaxTraceLengthToCollect);
PrintBacktrace(UncompressedTrace, UncompressedLength, Printf);
}
if (Meta->AllocationTrace.ThreadID == GuardedPoolAllocator::kInvalidThreadID)
@ -451,7 +469,12 @@ void printAllocDeallocTraces(uintptr_t AccessPtr, AllocationMetadata *Meta,
Printf("0x%zx was allocated by thread %zu here:\n", Meta->Addr,
Meta->AllocationTrace.ThreadID);
PrintBacktrace(Meta->AllocationTrace.Trace, Printf);
uintptr_t UncompressedTrace[AllocationMetadata::kMaxTraceLengthToCollect];
size_t UncompressedLength = compression::unpack(
Meta->AllocationTrace.CompressedTrace, Meta->AllocationTrace.TraceSize,
UncompressedTrace, AllocationMetadata::kMaxTraceLengthToCollect);
PrintBacktrace(UncompressedTrace, UncompressedLength, Printf);
}
struct ScopedEndOfReportDecorator {
@ -491,11 +514,11 @@ void GuardedPoolAllocator::reportErrorInternal(uintptr_t AccessPtr, Error E) {
uint64_t ThreadID = getThreadID();
printErrorType(E, AccessPtr, Meta, Printf, ThreadID);
if (Backtrace) {
static constexpr unsigned kMaximumStackFramesForCrashTrace = 128;
static constexpr unsigned kMaximumStackFramesForCrashTrace = 512;
uintptr_t Trace[kMaximumStackFramesForCrashTrace];
Backtrace(Trace, kMaximumStackFramesForCrashTrace);
size_t TraceLength = Backtrace(Trace, kMaximumStackFramesForCrashTrace);
PrintBacktrace(Trace, Printf);
PrintBacktrace(Trace, TraceLength, Printf);
} else {
Printf(" <unknown (does your allocator support backtracing?)>\n\n");
}

View File

@ -13,6 +13,7 @@
#include "gwp_asan/mutex.h"
#include "gwp_asan/options.h"
#include "gwp_asan/random.h"
#include "gwp_asan/stack_trace_compressor.h"
#include <stddef.h>
#include <stdint.h>
@ -39,9 +40,15 @@ class GuardedPoolAllocator {
};
struct AllocationMetadata {
// Maximum number of stack trace frames to collect for allocations + frees.
// TODO(hctim): Implement stack frame compression, a-la Chromium.
static constexpr size_t kMaximumStackFrames = 64;
// The number of bytes used to store a compressed stack frame. On 64-bit
// platforms, assuming a compression ratio of 50%, this should allow us to
// store ~64 frames per trace.
static constexpr size_t kStackFrameStorageBytes = 256;
// Maximum number of stack frames to collect on allocation/deallocation. The
// actual number of collected frames may be less than this as the stack
// frames are compressed into a fixed memory range.
static constexpr size_t kMaxTraceLengthToCollect = 128;
// Records the given allocation metadata into this struct.
void RecordAllocation(uintptr_t Addr, size_t Size,
@ -51,11 +58,13 @@ class GuardedPoolAllocator {
void RecordDeallocation(options::Backtrace_t Backtrace);
struct CallSiteInfo {
// The backtrace to the allocation/deallocation. If the first value is
// zero, we did not collect a trace.
uintptr_t Trace[kMaximumStackFrames] = {};
// The compressed backtrace to the allocation/deallocation.
uint8_t CompressedTrace[kStackFrameStorageBytes];
// The thread ID for this trace, or kInvalidThreadID if not available.
uint64_t ThreadID = kInvalidThreadID;
// The size of the compressed trace (in bytes). Zero indicates that no
// trace was collected.
size_t TraceSize = 0;
};
// The address of this allocation.

View File

@ -14,7 +14,12 @@
namespace gwp_asan {
namespace options {
// Functions to get the platform-specific and implementation-specific backtrace
// and backtrace printing functions.
// and backtrace printing functions when RTGwpAsanBacktraceLibc or
// RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
// backtrace function for populating the Options::Backtrace and
// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
// note any thread-safety descriptions for the implementation of these functions
// that you use.
Backtrace_t getBacktraceFunction();
PrintBacktrace_t getPrintBacktraceFunction();
} // namespace options

View File

@ -17,33 +17,23 @@
#include "gwp_asan/options.h"
namespace {
void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
// Grab (what seems to be) one more trace than we need. TraceBuffer needs to
// be null-terminated, but we wish to remove the frame of this function call.
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
int NumTraces =
backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
// Now shift the entire trace one place to the left and null-terminate.
memmove(TraceBuffer, TraceBuffer + 1, NumTraces * sizeof(void *));
TraceBuffer[NumTraces - 1] = 0;
return backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
}
static void PrintBacktrace(uintptr_t *Trace,
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
gwp_asan::options::Printf_t Printf) {
size_t NumTraces = 0;
for (; Trace[NumTraces] != 0; ++NumTraces) {
}
if (NumTraces == 0) {
if (TraceLength == 0) {
Printf(" <not found (does your allocator support backtracing?)>\n\n");
return;
}
char **BacktraceSymbols =
backtrace_symbols(reinterpret_cast<void **>(Trace), NumTraces);
backtrace_symbols(reinterpret_cast<void **>(Trace), TraceLength);
for (size_t i = 0; i < NumTraces; ++i) {
for (size_t i = 0; i < TraceLength; ++i) {
if (!BacktraceSymbols)
Printf(" #%zu %p\n", i, Trace[i]);
else

View File

@ -13,6 +13,9 @@
#include "gwp_asan/optional/backtrace.h"
#include "gwp_asan/options.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
@ -26,7 +29,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
}
namespace {
void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
__sanitizer::BufferedStackTrace Trace;
Trace.Reset();
if (Size > __sanitizer::kStackTraceMax)
@ -38,19 +41,14 @@ void Backtrace(uintptr_t *TraceBuffer, size_t Size) {
/* fast unwind */ true, Size - 1);
memcpy(TraceBuffer, Trace.trace, Trace.size * sizeof(uintptr_t));
TraceBuffer[Trace.size] = 0;
return Trace.size;
}
static void PrintBacktrace(uintptr_t *Trace,
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
gwp_asan::options::Printf_t Printf) {
__sanitizer::StackTrace StackTrace;
StackTrace.trace = reinterpret_cast<__sanitizer::uptr *>(Trace);
for (StackTrace.size = 0; StackTrace.size < __sanitizer::kStackTraceMax;
++StackTrace.size) {
if (Trace[StackTrace.size] == 0)
break;
}
StackTrace.size = TraceLength;
if (StackTrace.size == 0) {
Printf(" <unknown (does your allocator support backtracing?)>\n\n");
@ -63,7 +61,18 @@ static void PrintBacktrace(uintptr_t *Trace,
namespace gwp_asan {
namespace options {
Backtrace_t getBacktraceFunction() { return Backtrace; }
// This function is thread-compatible. It must be synchronised in respect to any
// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
// and calls to either of the functions that they return. Furthermore, this may
// require synchronisation with any calls to sanitizer_common that use flags.
// Generally, this function will be called during the initialisation of the
// allocator, which is done in a thread-compatible manner.
Backtrace_t getBacktraceFunction() {
// The unwinder requires the default flags to be set.
__sanitizer::SetCommonFlagsDefaults();
__sanitizer::InitializeCommonFlags();
return Backtrace;
}
PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
} // namespace options
} // namespace gwp_asan

View File

@ -14,22 +14,63 @@
namespace gwp_asan {
namespace options {
// The function pointer type for printf(). Follows the standard format from the
// sanitizers library. If the supported allocator exposes printing via a
// different function signature, please provide a wrapper which has this
// printf() signature, and pass the wrapper instead.
// ================================ Requirements ===============================
// This function is required to be implemented by the supporting allocator. The
// sanitizer::Printf() function can be simply used here.
// ================================ Description ================================
// This function shall produce output according to a strict subset of the C
// standard library's printf() family. This function must support printing the
// following formats:
// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
// 2. pointers: "%p"
// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
// 4. chars: "%c"
// This function must be implemented in a signal-safe manner.
// =================================== Notes ===================================
// This function has a slightly different signature than the C standard
// library's printf(). Notably, it returns 'void' rather than 'int'.
typedef void (*Printf_t)(const char *Format, ...);
// The function pointer type for backtrace information. Required to be
// implemented by the supporting allocator. The callee should elide itself and
// all frames below itself from TraceBuffer, i.e. the caller's frame should be
// in TraceBuffer[0], and subsequent frames 1..n into TraceBuffer[1..n], where a
// maximum of `MaximumDepth - 1` frames are stored. TraceBuffer should be
// nullptr-terminated (i.e. if there are 5 frames; TraceBuffer[5] == nullptr).
// If the allocator cannot supply backtrace information, it should set
// TraceBuffer[0] == nullptr.
typedef void (*Backtrace_t)(uintptr_t *TraceBuffer, size_t Size);
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, Printf_t Print);
// ================================ Requirements ===============================
// This function is required to be either implemented by the supporting
// allocator, or one of the two provided implementations may be used
// (RTGwpAsanBacktraceLibc or RTGwpAsanBacktraceSanitizerCommon).
// ================================ Description ================================
// This function shall collect the backtrace for the calling thread and place
// the result in `TraceBuffer`. This function should elide itself and all frames
// below itself from `TraceBuffer`, i.e. the caller's frame should be in
// TraceBuffer[0], and subsequent frames 1..n into TraceBuffer[1..n], where a
// maximum of `Size` frames are stored. Returns the number of frames stored into
// `TraceBuffer`, and zero on failure. If the return value of this function is
// equal to `Size`, it may indicate that the backtrace is truncated.
// =================================== Notes ===================================
// This function may directly or indirectly call malloc(), as the
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
// recursion. Any allocation made inside this function will be served by the
// supporting allocator, and will not have GWP-ASan protections.
typedef size_t (*Backtrace_t)(uintptr_t *TraceBuffer, size_t Size);
// ================================ Requirements ===============================
// This function is optional for the supporting allocator, but one of the two
// provided implementations may be used (RTGwpAsanBacktraceLibc or
// RTGwpAsanBacktraceSanitizerCommon). If not provided, a default implementation
// is used which prints the raw pointers only.
// ================================ Description ================================
// This function shall take the backtrace provided in `TraceBuffer`, and print
// it in a human-readable format using `Print`. Generally, this function shall
// resolve raw pointers to section offsets and print them with the following
// sanitizer-common format:
// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
// This format allows the backtrace to be symbolized offline successfully using
// llvm-symbolizer.
// =================================== Notes ===================================
// This function may directly or indirectly call malloc(), as the
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
// recursion. Any allocation made inside this function will be served by the
// supporting allocator, and will not have GWP-ASan protections.
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
Printf_t Print);
struct Options {
Printf_t Printf = nullptr;

View File

@ -21,9 +21,9 @@ GWP_ASAN_OPTION(
"byte buffer-overflows for multibyte allocations at the cost of "
"performance, and may be incompatible with some architectures.")
GWP_ASAN_OPTION(
int, MaxSimultaneousAllocations, 16,
"Number of usable guarded slots in the allocation pool. Defaults to 16.")
GWP_ASAN_OPTION(int, MaxSimultaneousAllocations, 16,
"Number of simultaneously-guarded allocations available in the "
"pool. Defaults to 16.")
GWP_ASAN_OPTION(int, SampleRate, 5000,
"The probability (1 / SampleRate) that an allocation is "

Some files were not shown because too many files have changed in this diff Show More