diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-01-18 19:46:00 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-01-18 19:46:00 +0000 |
commit | 05342ccc9cff16425c0a831fddd510879544a0bf (patch) | |
tree | d86b2dfee6aa9d3a54d6d21aabb6bd7462b6669b | |
parent | 6fc0ad0a5de45f80140620e2dd606f65d547362a (diff) | |
parent | b15181368831966c0ec1824617a4c95853fd1b92 (diff) | |
download | compiler-rt-05342ccc9cff16425c0a831fddd510879544a0bf.tar.gz |
Creating branches/google/stable and tags/google/stable/2019-01-18 from r351319
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/branches/google/stable@351578 91177308-0d34-0410-b5e6-96231b3b80d8
219 files changed, 4515 insertions, 1072 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4697dba62..aa360a3ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,7 @@ set(CXXABIS none default libstdc++ libc++) set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) if (SANITIZER_CXX_ABI STREQUAL "default") - if (APPLE) + if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(SANITIZER_CXX_ABI_LIBNAME "libc++") set(SANITIZER_CXX_ABI_SYSTEM 1) elseif (FUCHSIA) @@ -428,15 +428,19 @@ endif() add_subdirectory(include) -foreach(path IN ITEMS ${LLVM_MAIN_SRC_DIR}/projects/libcxx - ${LLVM_MAIN_SRC_DIR}/runtimes/libcxx - ${LLVM_MAIN_SRC_DIR}/../libcxx - ${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR}) - if(IS_DIRECTORY ${path}) - set(COMPILER_RT_LIBCXX_PATH ${path}) - break() - endif() -endforeach() +option(COMPILER_RT_USE_LIBCXX + "Enable compiler-rt to use libc++ from the source tree" ON) +if(COMPILER_RT_USE_LIBCXX) + foreach(path IN ITEMS ${LLVM_MAIN_SRC_DIR}/projects/libcxx + ${LLVM_MAIN_SRC_DIR}/runtimes/libcxx + ${LLVM_MAIN_SRC_DIR}/../libcxx + ${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR}) + if(IS_DIRECTORY ${path}) + set(COMPILER_RT_LIBCXX_PATH ${path}) + break() + endif() + endforeach() +endif() set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/tools/lld) if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD) diff --git a/LICENSE.TXT b/LICENSE.TXT index 0134694e4..1c94ad5d8 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -14,7 +14,7 @@ Full text of the relevant licenses is included below. University of Illinois/NCSA Open Source License -Copyright (c) 2009-2018 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT All rights reserved. diff --git a/cmake/Modules/CompilerRTUtils.cmake b/cmake/Modules/CompilerRTUtils.cmake index c4500328e..5348f2064 100644 --- a/cmake/Modules/CompilerRTUtils.cmake +++ b/cmake/Modules/CompilerRTUtils.cmake @@ -58,14 +58,6 @@ macro(append_rtti_flag polarity list) endif() endmacro() -macro(append_have_file_definition filename varname list) - check_include_file("${filename}" "${varname}") - if (NOT ${varname}) - set("${varname}" 0) - endif() - list(APPEND ${list} "${varname}=${${varname}}") -endmacro() - macro(list_intersect output input1 input2) set(${output}) foreach(it ${${input1}}) @@ -239,7 +231,7 @@ macro(load_llvm_config) # Detect if we have the LLVMXRay and TestingSupport library installed and # available from llvm-config. execute_process( - COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray" "testingsupport" + COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray" RESULT_VARIABLE HAD_ERROR OUTPUT_VARIABLE CONFIG_OUTPUT) if (HAD_ERROR) @@ -254,6 +246,26 @@ macro(load_llvm_config) set(COMPILER_RT_HAS_LLVMXRAY TRUE) endif() + set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE) + execute_process( + COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "testingsupport" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT) + if (HAD_ERROR) + message(WARNING "llvm-config finding testingsupport failed with status ${HAD_ERROR}") + else() + string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) + list(GET CONFIG_OUTPUT 0 LDFLAGS) + list(GET CONFIG_OUTPUT 1 LIBLIST) + if (LIBLIST STREQUAL "") + message(WARNING "testingsupport library not installed, some tests will be skipped") + else() + set(LLVM_TESTINGSUPPORT_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMTestingSupport library") + set(LLVM_TESTINGSUPPORT_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMTestingSupport") + set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE) + endif() + endif() + # Make use of LLVM CMake modules. # --cmakedir is supported since llvm r291218 (4.0 release) execute_process( diff --git a/cmake/Modules/SanitizerUtils.cmake b/cmake/Modules/SanitizerUtils.cmake index 8fe4baae4..64d3ed92c 100644 --- a/cmake/Modules/SanitizerUtils.cmake +++ b/cmake/Modules/SanitizerUtils.cmake @@ -30,7 +30,7 @@ macro(add_sanitizer_rt_symbols name) add_custom_command(OUTPUT ${stamp} COMMAND ${PYTHON_EXECUTABLE} ${SANITIZER_GEN_DYNAMIC_LIST} ${extra_args} $<TARGET_FILE:${target_name}> - > $<TARGET_FILE:${target_name}>.syms + -o $<TARGET_FILE:${target_name}>.syms COMMAND ${CMAKE_COMMAND} -E touch ${stamp} DEPENDS ${target_name} ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -80,7 +80,7 @@ macro(add_sanitizer_rt_version_list name) add_custom_command(OUTPUT ${vers} COMMAND ${PYTHON_EXECUTABLE} ${SANITIZER_GEN_DYNAMIC_LIST} --version-list ${args} - > ${vers} + -o ${vers} DEPENDS ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA} ${ARG_LIBS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating version list for ${name}" diff --git a/cmake/base-config-ix.cmake b/cmake/base-config-ix.cmake index 2a44d830b..6684d7371 100644 --- a/cmake/base-config-ix.cmake +++ b/cmake/base-config-ix.cmake @@ -8,6 +8,12 @@ include(CheckCXXSourceCompiles) check_include_file(unwind.h HAVE_UNWIND_H) +# Used by sanitizer_common and tests. +check_include_file(rpc/xdr.h HAVE_RPC_XDR_H) +if (NOT HAVE_RPC_XDR_H) + set(HAVE_RPC_XDR_H 0) +endif() + # Top level target used to build all compiler-rt libraries. add_custom_target(compiler-rt ALL) add_custom_target(install-compiler-rt) diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 7e9ad6355..db5c4645d 100644 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -586,7 +586,7 @@ else() endif() if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD") set(COMPILER_RT_HAS_PROFILE TRUE) else() set(COMPILER_RT_HAS_PROFILE FALSE) diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index 51fba254a..c9b37dc7a 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -148,6 +148,7 @@ const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. typedef DefaultSizeClassMap SizeClassMap; # endif +template <typename AddressSpaceViewTy> struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -155,9 +156,12 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name. typedef __asan::SizeClassMap SizeClassMap; typedef AsanMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; -typedef SizeClassAllocator64<AP64> PrimaryAllocator; +template <typename AddressSpaceView> +using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; +using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; #else // Fallback to SizeClassAllocator32. static const uptr kRegionSizeLog = 20; static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; @@ -188,11 +192,21 @@ using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; #endif // SANITIZER_CAN_USE_ALLOCATOR64 static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; -typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; -typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator; -typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, - SecondaryAllocator> AsanAllocator; +template <typename AddressSpaceView> +using AllocatorCacheASVT = + SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>; +using AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>; +template <typename AddressSpaceView> +using SecondaryAllocatorASVT = + LargeMmapAllocator<AsanMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray, + AddressSpaceView>; +template <typename AddressSpaceView> +using AsanAllocatorASVT = + CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>, + AllocatorCacheASVT<AddressSpaceView>, + SecondaryAllocatorASVT<AddressSpaceView>>; +using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>; struct AsanThreadLocalMallocStorage { uptr quarantine_cache[16]; diff --git a/lib/asan/asan_errors.cc b/lib/asan/asan_errors.cc index 33d0613f7..0ecd30dca 100644 --- a/lib/asan/asan_errors.cc +++ b/lib/asan/asan_errors.cc @@ -125,9 +125,8 @@ void ErrorAllocTypeMismatch::Print() { Decorator d; Printf("%s", d.Error()); Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n", - scariness.GetDescription(), - alloc_names[alloc_type], dealloc_names[dealloc_type], - addr_description.addr); + scariness.GetDescription(), alloc_names[alloc_type], + dealloc_names[dealloc_type], addr_description.Address()); Printf("%s", d.Default()); CHECK_GT(dealloc_stack->size, 0); scariness.Print(); diff --git a/lib/asan/asan_errors.h b/lib/asan/asan_errors.h index 574197ebf..7ddd7e94e 100644 --- a/lib/asan/asan_errors.h +++ b/lib/asan/asan_errors.h @@ -110,8 +110,8 @@ struct ErrorFreeNotMalloced : ErrorBase { struct ErrorAllocTypeMismatch : ErrorBase { const BufferedStackTrace *dealloc_stack; - HeapAddressDescription addr_description; AllocType alloc_type, dealloc_type; + AddressDescription addr_description; ErrorAllocTypeMismatch() = default; // (*) ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr, @@ -119,9 +119,8 @@ struct ErrorAllocTypeMismatch : ErrorBase { : ErrorBase(tid, 10, "alloc-dealloc-mismatch"), dealloc_stack(stack), alloc_type(alloc_type_), - dealloc_type(dealloc_type_) { - GetHeapAddressInformation(addr, 1, &addr_description); - }; + dealloc_type(dealloc_type_), + addr_description(addr, 1, false) {} void Print(); }; diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index 17c28b0ae..ca99c04b3 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -40,6 +40,51 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { // ---------------------- TSD ---------------- {{{1 +#if SANITIZER_NETBSD || SANITIZER_FREEBSD +// Thread Static Data cannot be used in early init on NetBSD and FreeBSD. +// Reuse the Asan TSD API for compatibility with existing code +// with an alternative implementation. + +static void (*tsd_destructor)(void *tsd) = nullptr; + +struct tsd_key { + tsd_key() : key(nullptr) {} + ~tsd_key() { + CHECK(tsd_destructor); + if (key) + (*tsd_destructor)(key); + } + void *key; +}; + +static thread_local struct tsd_key key; + +void AsanTSDInit(void (*destructor)(void *tsd)) { + CHECK(!tsd_destructor); + tsd_destructor = destructor; +} + +void *AsanTSDGet() { + CHECK(tsd_destructor); + return key.key; +} + +void AsanTSDSet(void *tsd) { + CHECK(tsd_destructor); + CHECK(tsd); + CHECK(!key.key); + key.key = tsd; +} + +void PlatformTSDDtor(void *tsd) { + CHECK(tsd_destructor); + CHECK_EQ(key.key, tsd); + key.key = nullptr; + // Make sure that signal handler can not see a stale current thread pointer. + atomic_signal_fence(memory_order_seq_cst); + AsanThread::TSDDtor(tsd); +} +#else static pthread_key_t tsd_key; static bool tsd_key_inited = false; void AsanTSDInit(void (*destructor)(void *tsd)) { @@ -67,6 +112,7 @@ void PlatformTSDDtor(void *tsd) { } AsanThread::TSDDtor(tsd); } +#endif } // namespace __asan #endif // SANITIZER_POSIX diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 0ecbcd594..13344f3b8 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -383,6 +383,19 @@ void PrintAddressSpaceLayout() { kHighShadowBeg > kMidMemEnd); } +#if defined(__thumb__) && defined(__linux__) +#define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL +#endif + +#ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL +static bool UNUSED __local_asan_dyninit = [] { + MaybeStartBackgroudThread(); + SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); + + return false; +}(); +#endif + static void AsanInitInternal() { if (LIKELY(asan_inited)) return; SanitizerToolName = "AddressSanitizer"; @@ -457,8 +470,10 @@ static void AsanInitInternal() { allocator_options.SetFrom(flags(), common_flags()); InitializeAllocator(allocator_options); +#ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL MaybeStartBackgroudThread(); SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); +#endif // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // should be set to 1 prior to initializing the threads. diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc index faf423d30..0895e4ce0 100644 --- a/lib/asan/asan_thread.cc +++ b/lib/asan/asan_thread.cc @@ -223,9 +223,11 @@ void AsanThread::Init(const InitOptions *options) { atomic_store(&stack_switching_, false, memory_order_release); CHECK_EQ(this->stack_size(), 0U); SetThreadStackAndTls(options); - CHECK_GT(this->stack_size(), 0U); - CHECK(AddrIsInMem(stack_bottom_)); - CHECK(AddrIsInMem(stack_top_ - 1)); + if (stack_top_ != stack_bottom_) { + CHECK_GT(this->stack_size(), 0U); + CHECK(AddrIsInMem(stack_bottom_)); + CHECK(AddrIsInMem(stack_top_ - 1)); + } ClearShadowForThreadStackAndTLS(); fake_stack_ = nullptr; if (__asan_option_detect_stack_use_after_return) @@ -289,20 +291,23 @@ void AsanThread::SetThreadStackAndTls(const InitOptions *options) { DCHECK_EQ(options, nullptr); uptr tls_size = 0; uptr stack_size = 0; - GetThreadStackAndTls(tid() == 0, const_cast<uptr *>(&stack_bottom_), - const_cast<uptr *>(&stack_size), &tls_begin_, &tls_size); + GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size, &tls_begin_, + &tls_size); stack_top_ = stack_bottom_ + stack_size; tls_end_ = tls_begin_ + tls_size; dtls_ = DTLS_Get(); - int local; - CHECK(AddrIsInStack((uptr)&local)); + if (stack_top_ != stack_bottom_) { + int local; + CHECK(AddrIsInStack((uptr)&local)); + } } #endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS void AsanThread::ClearShadowForThreadStackAndTLS() { - PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); + if (stack_top_ != stack_bottom_) + PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); if (tls_begin_ != tls_end_) { uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY); uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY); @@ -314,6 +319,9 @@ void AsanThread::ClearShadowForThreadStackAndTLS() { bool AsanThread::GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access) { + if (stack_top_ == stack_bottom_) + return false; + uptr bottom = 0; if (AddrIsInStack(addr)) { bottom = stack_bottom(); diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index 82332967b..77947417b 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -505,7 +505,9 @@ set(mips64el_SOURCES ${GENERIC_TF_SOURCES} set(powerpc64_SOURCES ppc/divtc3.c ppc/fixtfdi.c + ppc/fixunstfti.c ppc/fixunstfdi.c + ppc/floattitf.c ppc/floatditf.c ppc/floatunditf.c ppc/gcc_qadd.c diff --git a/lib/builtins/ppc/fixunstfti.c b/lib/builtins/ppc/fixunstfti.c new file mode 100644 index 000000000..fa21084cb --- /dev/null +++ b/lib/builtins/ppc/fixunstfti.c @@ -0,0 +1,106 @@ +//===-- lib/builtins/ppc/fixunstfti.c - Convert long double->int128 *-C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements converting the 128bit IBM/PowerPC long double (double- +// double) data type to an unsigned 128 bit integer. +// +//===----------------------------------------------------------------------===// + +#include "../int_math.h" +#define BIAS 1023 + +/* Convert long double into an unsigned 128-bit integer. */ +__uint128_t __fixunstfti(long double input) { + + /* If we are trying to convert a NaN, return the NaN bit pattern. */ + if (crt_isnan(input)) { + return ((__uint128_t)0x7FF8000000000000ll) << 64 | + (__uint128_t)0x0000000000000000ll; + } + + __uint128_t result, hiResult, loResult; + int hiExponent, loExponent, shift; + /* The long double representation, with the high and low portions of + * the long double, and the corresponding bit patterns of each double. */ + union { + long double ld; + double d[2]; /* [0] is the high double, [1] is the low double. */ + unsigned long long ull[2]; /* High and low doubles as 64-bit integers. */ + } ldUnion; + + /* If the long double is less than 1.0 or negative, + * return 0.0. */ + if (input < 1.0) + return 0.0; + + /* Retrieve the 64-bit patterns of high and low doubles. + * Compute the unbiased exponent of both high and low doubles by + * removing the signs, isolating the exponent, and subtracting + * the bias from it. */ + ldUnion.ld = input; + hiExponent = ((ldUnion.ull[0] & 0x7FFFFFFFFFFFFFFFll) >> 52) - BIAS; + loExponent = ((ldUnion.ull[1] & 0x7FFFFFFFFFFFFFFFll) >> 52) - BIAS; + + /* Convert each double into int64; they will be added to the int128 result. + * CASE 1: High or low double fits in int64 + * - Convert the each double normally into int64. + * + * CASE 2: High or low double does not fit in int64 + * - Scale the double to fit within a 64-bit integer + * - Calculate the shift (amount to scale the double by in the int128) + * - Clear all the bits of the exponent (with 0x800FFFFFFFFFFFFF) + * - Add BIAS+53 (0x4350000000000000) to exponent to correct the value + * - Scale (move) the double to the correct place in the int128 + * (Move it by 2^53 places) + * + * Note: If the high double is assumed to be positive, an unsigned conversion + * from long double to 64-bit integer is needed. The low double can be either + * positive or negative, so a signed conversion is needed to retain the result + * of the low double and to ensure it does not simply get converted to 0. */ + + /* CASE 1 - High double fits in int64. */ + if (hiExponent < 63) { + hiResult = (unsigned long long)ldUnion.d[0]; + } else if (hiExponent < 128) { + /* CASE 2 - High double does not fit in int64, scale and convert it. */ + shift = hiExponent - 54; + ldUnion.ull[0] &= 0x800FFFFFFFFFFFFFll; + ldUnion.ull[0] |= 0x4350000000000000ll; + hiResult = (unsigned long long)ldUnion.d[0]; + hiResult <<= shift; + } else { + /* Detect cases for overflow. When the exponent of the high + * double is greater than 128 bits and when the long double + * input is positive, return the max 128-bit integer. + * For negative inputs with exponents > 128, return 1, like gcc. */ + if (ldUnion.d[0] > 0) { + return ((__uint128_t)0xFFFFFFFFFFFFFFFFll) << 64 | + (__uint128_t)0xFFFFFFFFFFFFFFFFll; + } else { + return ((__uint128_t)0x0000000000000000ll) << 64 | + (__uint128_t)0x0000000000000001ll; + } + } + + /* CASE 1 - Low double fits in int64. */ + if (loExponent < 63) { + loResult = (long long)ldUnion.d[1]; + } else { + /* CASE 2 - Low double does not fit in int64, scale and convert it. */ + shift = loExponent - 54; + ldUnion.ull[1] &= 0x800FFFFFFFFFFFFFll; + ldUnion.ull[1] |= 0x4350000000000000ll; + loResult = (long long)ldUnion.d[1]; + loResult <<= shift; + } + + /* Add the high and low doublewords together to form a 128 bit integer. */ + result = loResult + hiResult; + return result; +} diff --git a/lib/builtins/ppc/floattitf.c b/lib/builtins/ppc/floattitf.c new file mode 100644 index 000000000..b8e297b6b --- /dev/null +++ b/lib/builtins/ppc/floattitf.c @@ -0,0 +1,48 @@ +//===-- lib/builtins/ppc/floattitf.c - Convert int128->long double -*-C -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements converting a signed 128 bit integer to a 128bit IBM / +// PowerPC long double (double-double) value. +// +//===----------------------------------------------------------------------===// + +#include <stdint.h> + +/* Conversions from signed and unsigned 64-bit int to long double. */ +long double __floatditf(int64_t); +long double __floatunditf(uint64_t); + +/* Convert a signed 128-bit integer to long double. + * This uses the following property: Let hi and lo be 64-bits each, + * and let signed_val_k() and unsigned_val_k() be the value of the + * argument interpreted as a signed or unsigned k-bit integer. Then, + * + * signed_val_128(hi,lo) = signed_val_64(hi) * 2^64 + unsigned_val_64(lo) + * = (long double)hi * 2^64 + (long double)lo, + * + * where (long double)hi and (long double)lo are signed and + * unsigned 64-bit integer to long double conversions, respectively. + */ +long double __floattitf(__int128_t arg) { + /* Split the int128 argument into 64-bit high and low int64 parts. */ + int64_t ArgHiPart = (int64_t)(arg >> 64); + uint64_t ArgLoPart = (uint64_t)arg; + + /* Convert each 64-bit part into long double. The high part + * must be a signed conversion and the low part an unsigned conversion + * to ensure the correct result. */ + long double ConvertedHiPart = __floatditf(ArgHiPart); + long double ConvertedLoPart = __floatunditf(ArgLoPart); + + /* The low bit of ArgHiPart corresponds to the 2^64 bit in arg. + * Multiply the high part by 2^64 to undo the right shift by 64-bits + * done in the splitting. Then, add to the low part to obtain the + * final result. */ + return ((ConvertedHiPart * 0x1.0p64) + ConvertedLoPart); +} diff --git a/lib/fuzzer/CMakeLists.txt b/lib/fuzzer/CMakeLists.txt index 8ba3f8a5a..caea9734f 100644 --- a/lib/fuzzer/CMakeLists.txt +++ b/lib/fuzzer/CMakeLists.txt @@ -3,8 +3,8 @@ set(LIBFUZZER_SOURCES FuzzerDataFlowTrace.cpp FuzzerDriver.cpp FuzzerExtFunctionsDlsym.cpp - FuzzerExtFunctionsWeakAlias.cpp FuzzerExtFunctionsWeak.cpp + FuzzerExtFunctionsWindows.cpp FuzzerExtraCounters.cpp FuzzerIO.cpp FuzzerIOPosix.cpp @@ -25,6 +25,8 @@ set(LIBFUZZER_SOURCES FuzzerUtilWindows.cpp) set(LIBFUZZER_HEADERS + FuzzerBuiltins.h + FuzzerBuiltinsMsvc.h FuzzerCommand.h FuzzerCorpus.h FuzzerDataFlowTrace.h diff --git a/lib/fuzzer/FuzzerBuiltins.h b/lib/fuzzer/FuzzerBuiltins.h new file mode 100644 index 000000000..a80938d9a --- /dev/null +++ b/lib/fuzzer/FuzzerBuiltins.h @@ -0,0 +1,36 @@ +//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Wrapper functions and marcos around builtin functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_BUILTINS_H +#define LLVM_FUZZER_BUILTINS_H + +#include "FuzzerDefs.h" + +#if !LIBFUZZER_MSVC +#include <cstdint> + +#define GET_CALLER_PC() __builtin_return_address(0) + +namespace fuzzer { + +inline uint8_t Bswap(uint8_t x) { return x; } +inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } +inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } +inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } + +inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); } +inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); } +inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); } + +} // namespace fuzzer + +#endif // !LIBFUZZER_MSVC +#endif // LLVM_FUZZER_BUILTINS_H diff --git a/lib/fuzzer/FuzzerBuiltinsMsvc.h b/lib/fuzzer/FuzzerBuiltinsMsvc.h new file mode 100644 index 000000000..67dd57ff9 --- /dev/null +++ b/lib/fuzzer/FuzzerBuiltinsMsvc.h @@ -0,0 +1,59 @@ +//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Wrapper functions and marcos that use intrinsics instead of builtin functions +// which cannot be compiled by MSVC. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_BUILTINS_MSVC_H +#define LLVM_FUZZER_BUILTINS_MSVC_H + +#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> + +// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent +// from <intrin.h> +#define GET_CALLER_PC() reinterpret_cast<uintptr_t>(_ReturnAddress()) + +namespace fuzzer { + +inline uint8_t Bswap(uint8_t x) { return x; } +// Use alternatives to __builtin functions from <stdlib.h> and <intrin.h> on +// Windows since the builtins are not supported by MSVC. +inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } +inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } +inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } + +// The functions below were mostly copied from +// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used +// outside of Windows. +inline uint32_t Clzll(uint64_t X) { + unsigned long LeadZeroIdx = 0; + if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; + return 64; +} + +inline uint32_t Clz(uint32_t X) { + unsigned long LeadZeroIdx = 0; + if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx; + return 32; +} + +inline int Popcountll(unsigned long long X) { return __popcnt64(X); } + +} // namespace fuzzer + +#endif // LIBFUZER_MSVC +#endif // LLVM_FUZZER_BUILTINS_MSVC_H diff --git a/lib/fuzzer/FuzzerCorpus.h b/lib/fuzzer/FuzzerCorpus.h index 8ad14656c..f844c07c7 100644 --- a/lib/fuzzer/FuzzerCorpus.h +++ b/lib/fuzzer/FuzzerCorpus.h @@ -238,12 +238,6 @@ class InputCorpus { return false; } - bool IsFeatureNew(size_t Idx, uint32_t NewSize, bool Shrink) { - assert(NewSize); - uint32_t OldSize = GetFeature(Idx % kFeatureSetSize); - return OldSize == 0 || (Shrink && OldSize > NewSize); - } - size_t NumFeatures() const { return NumAddedFeatures; } size_t NumFeatureUpdates() const { return NumUpdatedFeatures; } diff --git a/lib/fuzzer/FuzzerDefs.h b/lib/fuzzer/FuzzerDefs.h index 31655d562..c3dccbcd8 100644 --- a/lib/fuzzer/FuzzerDefs.h +++ b/lib/fuzzer/FuzzerDefs.h @@ -82,6 +82,13 @@ #error "Support for your platform has not been implemented" #endif +#if defined(_MSC_VER) && !defined(__clang__) +// MSVC compiler is being used. +#define LIBFUZZER_MSVC 1 +#else +#define LIBFUZZER_MSVC 0 +#endif + #ifndef __has_attribute # define __has_attribute(x) 0 #endif @@ -183,11 +190,6 @@ typedef int (*UserCallback)(const uint8_t *Data, size_t Size); int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); -inline uint8_t Bswap(uint8_t x) { return x; } -inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } -inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } -inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } - uint8_t *ExtraCountersBegin(); uint8_t *ExtraCountersEnd(); void ClearExtraCounters(); diff --git a/lib/fuzzer/FuzzerDriver.cpp b/lib/fuzzer/FuzzerDriver.cpp index 918a972ff..ff2a639ac 100644 --- a/lib/fuzzer/FuzzerDriver.cpp +++ b/lib/fuzzer/FuzzerDriver.cpp @@ -617,10 +617,6 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Options.PrintFinalStats = Flags.print_final_stats; Options.PrintCorpusStats = Flags.print_corpus_stats; Options.PrintCoverage = Flags.print_coverage; - Options.PrintUnstableStats = Flags.print_unstable_stats; - if (Flags.handle_unstable == TracePC::MinUnstable || - Flags.handle_unstable == TracePC::ZeroUnstable) - Options.HandleUnstable = Flags.handle_unstable; Options.DumpCoverage = Flags.dump_coverage; if (Flags.exit_on_src_pos) Options.ExitOnSrcPos = Flags.exit_on_src_pos; diff --git a/lib/fuzzer/FuzzerExtFunctionsWeakAlias.cpp b/lib/fuzzer/FuzzerExtFunctionsWeakAlias.cpp deleted file mode 100644 index e10f7b4dc..000000000 --- a/lib/fuzzer/FuzzerExtFunctionsWeakAlias.cpp +++ /dev/null @@ -1,56 +0,0 @@ -//===- FuzzerExtFunctionsWeakAlias.cpp - Interface to external functions --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Implementation using weak aliases. Works for Windows. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_WINDOWS - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" - -using namespace fuzzer; - -extern "C" { -// Declare these symbols as weak to allow them to be optionally defined. -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - RETURN_TYPE NAME##Def FUNC_SIG { \ - Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ - exit(1); \ - } \ - RETURN_TYPE NAME FUNC_SIG __attribute__((weak, alias(#NAME "Def"))); - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -template <typename T> -static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { - if (Fun == FunDef) { - if (WarnIfMissing) - Printf("WARNING: Failed to find function \"%s\".\n", FnName); - return nullptr; - } - return Fun; -} - -namespace fuzzer { - -ExternalFunctions::ExternalFunctions() { -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN); - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/lib/fuzzer/FuzzerExtFunctionsWindows.cpp b/lib/fuzzer/FuzzerExtFunctionsWindows.cpp new file mode 100644 index 000000000..b01871439 --- /dev/null +++ b/lib/fuzzer/FuzzerExtFunctionsWindows.cpp @@ -0,0 +1,83 @@ +//=== FuzzerExtWindows.cpp - Interface to external functions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when +// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately +// the method each compiler supports is not supported by the other. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" + +using namespace fuzzer; + +// Intermediate macro to ensure the parameter is expanded before stringified. +#define STRINGIFY_(A) #A +#define STRINGIFY(A) STRINGIFY_(A) + +#if LIBFUZZER_MSVC +// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h +#if defined(_M_IX86) || defined(__i386__) +#define WIN_SYM_PREFIX "_" +#else +#define WIN_SYM_PREFIX +#endif + +// Declare external functions as having alternativenames, so that we can +// determine if they are not defined. +#define EXTERNAL_FUNC(Name, Default) \ + __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ + Name) "=" WIN_SYM_PREFIX STRINGIFY(Default))) +#else +// Declare external functions as weak to allow them to default to a specified +// function if not defined explicitly. We must use weak symbols because clang's +// support for alternatename is not 100%, see +// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details. +#define EXTERNAL_FUNC(Name, Default) \ + __attribute__((weak, alias(STRINGIFY(Default)))) +#endif // LIBFUZZER_MSVC + +extern "C" { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE NAME##Def FUNC_SIG { \ + Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ + exit(1); \ + } \ + EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG; + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +template <typename T> +static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { + if (Fun == FunDef) { + if (WarnIfMissing) + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + return nullptr; + } + return Fun; +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff --git a/lib/fuzzer/FuzzerFlags.def b/lib/fuzzer/FuzzerFlags.def index 0417dda5b..91281c979 100644 --- a/lib/fuzzer/FuzzerFlags.def +++ b/lib/fuzzer/FuzzerFlags.def @@ -17,7 +17,7 @@ FUZZER_FLAG_INT(runs, -1, FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. " "If 0, libFuzzer tries to guess a good value based on the corpus " "and reports it. ") -FUZZER_FLAG_INT(len_control, 1000, "Try generating small inputs first, " +FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, " "then try larger inputs over time. Specifies the rate at which the length " "limit is increased (smaller == faster). If 0, immediately try inputs with " "size up to max_len.") @@ -110,15 +110,6 @@ FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text" FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated." " If 1, dump coverage information as a" " .sancov file at exit.") -FUZZER_FLAG_INT(handle_unstable, 0, "Experimental." - " Executes every input 3 times in total if a unique feature" - " is found during the first execution." - " If 1, we only use the minimum hit count from the 3 runs" - " to determine whether an input is interesting." - " If 2, we disregard edges that are found unstable for" - " feature collection.") -FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental." - " If 1, print unstable statistics at exit.") FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.") FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.") diff --git a/lib/fuzzer/FuzzerInternal.h b/lib/fuzzer/FuzzerInternal.h index bfc898248..a7fdc89cb 100644 --- a/lib/fuzzer/FuzzerInternal.h +++ b/lib/fuzzer/FuzzerInternal.h @@ -67,7 +67,6 @@ public: static void StaticGracefulExitCallback(); void ExecuteCallback(const uint8_t *Data, size_t Size); - void CheckForUnstableCounters(const uint8_t *Data, size_t Size); bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr); diff --git a/lib/fuzzer/FuzzerLoop.cpp b/lib/fuzzer/FuzzerLoop.cpp index 09c57c3f6..a32a30723 100644 --- a/lib/fuzzer/FuzzerLoop.cpp +++ b/lib/fuzzer/FuzzerLoop.cpp @@ -355,8 +355,6 @@ void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) { void Fuzzer::PrintFinalStats() { if (Options.PrintCoverage) TPC.PrintCoverage(); - if (Options.PrintUnstableStats) - TPC.PrintUnstableStats(); if (Options.DumpCoverage) TPC.DumpCoverage(); if (Options.PrintCorpusStats) @@ -449,29 +447,6 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { } } -void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) { - auto CBSetupAndRun = [&]() { - ScopedEnableMsanInterceptorChecks S; - UnitStartTime = system_clock::now(); - TPC.ResetMaps(); - RunningUserCallback = true; - CB(Data, Size); - RunningUserCallback = false; - UnitStopTime = system_clock::now(); - }; - - // Copy original run counters into our unstable counters - TPC.InitializeUnstableCounters(); - - // First Rerun - CBSetupAndRun(); - if (TPC.UpdateUnstableCounters(Options.HandleUnstable)) { - // Second Rerun - CBSetupAndRun(); - TPC.UpdateAndApplyUnstableCounters(Options.HandleUnstable); - } -} - bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, InputInfo *II, bool *FoundUniqFeatures) { if (!Size) @@ -482,17 +457,6 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, UniqFeatureSetTmp.clear(); size_t FoundUniqFeaturesOfII = 0; size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); - bool NewFeaturesUnstable = false; - - if (Options.HandleUnstable || Options.PrintUnstableStats) { - TPC.CollectFeatures([&](size_t Feature) { - if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink)) - NewFeaturesUnstable = true; - }); - if (NewFeaturesUnstable) - CheckForUnstableCounters(Data, Size); - } - TPC.CollectFeatures([&](size_t Feature) { if (Corpus.AddFeature(Feature, Size, Options.Shrink)) UniqFeatureSetTmp.push_back(Feature); @@ -501,12 +465,10 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, II->UniqFeatureSet.end(), Feature)) FoundUniqFeaturesOfII++; }); - if (FoundUniqFeatures) *FoundUniqFeatures = FoundUniqFeaturesOfII; PrintPulseAndReportSlowInput(Data, Size); size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; - if (NumNewFeatures) { TPC.UpdateObservedPCs(); Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, diff --git a/lib/fuzzer/FuzzerOptions.h b/lib/fuzzer/FuzzerOptions.h index bb642f1e2..ab90df82a 100644 --- a/lib/fuzzer/FuzzerOptions.h +++ b/lib/fuzzer/FuzzerOptions.h @@ -54,8 +54,6 @@ struct FuzzingOptions { bool PrintFinalStats = false; bool PrintCorpusStats = false; bool PrintCoverage = false; - bool PrintUnstableStats = false; - int HandleUnstable = 0; bool DumpCoverage = false; bool DetectLeaks = true; int PurgeAllocatorIntervalSec = 1; diff --git a/lib/fuzzer/FuzzerTracePC.cpp b/lib/fuzzer/FuzzerTracePC.cpp index 7ba75c7b2..80b33105b 100644 --- a/lib/fuzzer/FuzzerTracePC.cpp +++ b/lib/fuzzer/FuzzerTracePC.cpp @@ -13,6 +13,8 @@ //===----------------------------------------------------------------------===// #include "FuzzerTracePC.h" +#include "FuzzerBuiltins.h" +#include "FuzzerBuiltinsMsvc.h" #include "FuzzerCorpus.h" #include "FuzzerDefs.h" #include "FuzzerDictionary.h" @@ -56,59 +58,6 @@ size_t TracePC::GetTotalPCCoverage() { return Res; } -template<class CallBack> -void TracePC::IterateInline8bitCounters(CallBack CB) const { - if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) { - size_t CounterIdx = 0; - for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { - uint8_t *Beg = ModuleCounters[i].Start; - size_t Size = ModuleCounters[i].Stop - Beg; - assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); - for (size_t j = 0; j < Size; j++, CounterIdx++) - CB(i, j, CounterIdx); - } - } -} - -// Initializes unstable counters by copying Inline8bitCounters to unstable -// counters. -void TracePC::InitializeUnstableCounters() { - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j]; - }); -} - -// Compares the current counters with counters from previous runs -// and records differences as unstable edges. -bool TracePC::UpdateUnstableCounters(int UnstableMode) { - bool Updated = false; - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) { - Updated = true; - UnstableCounters[UnstableIdx].IsUnstable = true; - if (UnstableMode == ZeroUnstable) - UnstableCounters[UnstableIdx].Counter = 0; - else if (UnstableMode == MinUnstable) - UnstableCounters[UnstableIdx].Counter = std::min( - ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter); - } - }); - return Updated; -} - -// Updates and applies unstable counters to ModuleCounters in single iteration -void TracePC::UpdateAndApplyUnstableCounters(int UnstableMode) { - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) { - UnstableCounters[UnstableIdx].IsUnstable = true; - if (UnstableMode == ZeroUnstable) - ModuleCounters[i].Start[j] = 0; - else if (UnstableMode == MinUnstable) - ModuleCounters[i].Start[j] = std::min( - ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter); - } - }); -} void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { if (Start == Stop) return; @@ -243,10 +192,15 @@ void TracePC::UpdateObservedPCs() { if (NumPCsInPCTables) { if (NumInline8bitCounters == NumPCsInPCTables) { - IterateInline8bitCounters([&](int i, int j, int CounterIdx) { - if (ModuleCounters[i].Start[j]) - Observe(ModulePCTable[i].Start[j]); - }); + for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { + uint8_t *Beg = ModuleCounters[i].Start; + size_t Size = ModuleCounters[i].Stop - Beg; + assert(Size == + (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); + for (size_t j = 0; j < Size; j++) + if (Beg[j]) + Observe(ModulePCTable[i].Start[j]); + } } else if (NumGuards == NumPCsInPCTables) { size_t GuardIdx = 1; for (size_t i = 0; i < NumModules; i++) { @@ -378,27 +332,6 @@ void TracePC::DumpCoverage() { } } -void TracePC::PrintUnstableStats() { - size_t count = 0; - Printf("UNSTABLE_FUNCTIONS:\n"); - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - const PCTableEntry &TE = ModulePCTable[i].Start[j]; - if (UnstableCounters[UnstableIdx].IsUnstable) { - count++; - if (ObservedFuncs.count(TE.PC)) { - auto VisualizePC = GetNextInstructionPc(TE.PC); - std::string FunctionStr = DescribePC("%F", VisualizePC); - if (FunctionStr.find("in ") == 0) - FunctionStr = FunctionStr.substr(3); - Printf("%s\n", FunctionStr.c_str()); - } - } - }); - - Printf("stat::stability_rate: %.2f\n", - 100 - static_cast<float>(count * 100) / NumInline8bitCounters); -} - // Value profile. // We keep track of various values that affect control flow. // These values are inserted into a bit-set-based hash map. @@ -446,9 +379,8 @@ void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) { TORC4.Insert(ArgXor, Arg1, Arg2); else if (sizeof(T) == 8) TORC8.Insert(ArgXor, Arg1, Arg2); - uint64_t HammingDistance = __builtin_popcountll(ArgXor); // [0,64] - uint64_t AbsoluteDistance = - (Arg1 == Arg2 ? 0 : __builtin_clzll(Arg1 - Arg2) + 1); + uint64_t HammingDistance = Popcountll(ArgXor); // [0,64] + uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1); ValueProfileMap.AddValue(PC * 128 + HammingDistance); ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); } @@ -491,7 +423,7 @@ extern "C" { ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); uint32_t Idx = *Guard; __sancov_trace_pc_pcs[Idx] = PC; __sancov_trace_pc_guard_8bit_counters[Idx]++; @@ -502,7 +434,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc() { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1); __sancov_trace_pc_pcs[Idx] = PC; __sancov_trace_pc_guard_8bit_counters[Idx]++; @@ -527,7 +459,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCallerCallee(PC, Callee); } @@ -535,7 +467,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -546,7 +478,7 @@ ATTRIBUTE_TARGET_POPCNT // the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however, // should be changed later to make full use of instrumentation. void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -554,7 +486,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -562,7 +494,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -570,7 +502,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -578,7 +510,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -586,7 +518,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -594,7 +526,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); } @@ -608,7 +540,7 @@ void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { // Skip the most common and the most boring case. if (Vals[N - 1] < 256 && Val < 256) return; - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); size_t i; uint64_t Token = 0; for (i = 0; i < N; i++) { @@ -629,7 +561,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_div4(uint32_t Val) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0); } @@ -637,7 +569,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_div8(uint64_t Val) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0); } @@ -645,7 +577,7 @@ ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_TARGET_POPCNT void __sanitizer_cov_trace_gep(uintptr_t Idx) { - uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0)); + uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0); } diff --git a/lib/fuzzer/FuzzerTracePC.h b/lib/fuzzer/FuzzerTracePC.h index 39f97acdb..46d6c2488 100644 --- a/lib/fuzzer/FuzzerTracePC.h +++ b/lib/fuzzer/FuzzerTracePC.h @@ -74,11 +74,6 @@ class TracePC { // How many bits of PC are used from __sanitizer_cov_trace_pc. static const size_t kTracePcBits = 18; - enum HandleUnstableOptions { - MinUnstable = 1, - ZeroUnstable = 2, - }; - void HandleInit(uint32_t *Start, uint32_t *Stop); void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop); void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop); @@ -109,7 +104,6 @@ class TracePC { void PrintCoverage(); void DumpCoverage(); - void PrintUnstableStats(); template<class CallBack> void IterateCoveredFunctions(CallBack CB); @@ -142,18 +136,7 @@ class TracePC { void SetFocusFunction(const std::string &FuncName); bool ObservedFocusFunction(); - void InitializeUnstableCounters(); - bool UpdateUnstableCounters(int UnstableMode); - void UpdateAndApplyUnstableCounters(int UnstableMode); - private: - struct UnstableEdge { - uint8_t Counter; - bool IsUnstable; - }; - - UnstableEdge UnstableCounters[kNumPCs]; - bool UseCounters = false; uint32_t UseValueProfileMask = false; bool DoPrintNewPCs = false; @@ -185,9 +168,6 @@ private: Set<uintptr_t> ObservedPCs; std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter. - template <class Callback> - void IterateInline8bitCounters(Callback CB) const; - std::pair<size_t, size_t> FocusFunction = {-1, -1}; // Module and PC IDs. ValueBitMap ValueProfileMap; diff --git a/lib/fuzzer/FuzzerUtil.h b/lib/fuzzer/FuzzerUtil.h index 8c5c57c3a..d2f1d5de4 100644 --- a/lib/fuzzer/FuzzerUtil.h +++ b/lib/fuzzer/FuzzerUtil.h @@ -12,8 +12,10 @@ #ifndef LLVM_FUZZER_UTIL_H #define LLVM_FUZZER_UTIL_H -#include "FuzzerDefs.h" +#include "FuzzerBuiltins.h" +#include "FuzzerBuiltinsMsvc.h" #include "FuzzerCommand.h" +#include "FuzzerDefs.h" namespace fuzzer { @@ -84,7 +86,7 @@ std::string SearchRegexCmd(const std::string &Regex); size_t SimpleFastHash(const uint8_t *Data, size_t Size); -inline uint32_t Log(uint32_t X) { return 32 - __builtin_clz(X) - 1; } +inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; } } // namespace fuzzer diff --git a/lib/hwasan/CMakeLists.txt b/lib/hwasan/CMakeLists.txt index ca257dfe1..20ab94dc0 100644 --- a/lib/hwasan/CMakeLists.txt +++ b/lib/hwasan/CMakeLists.txt @@ -7,6 +7,7 @@ set(HWASAN_RTL_SOURCES hwasan_dynamic_shadow.cc hwasan_interceptors.cc hwasan_linux.cc + hwasan_memintrinsics.cc hwasan_poisoning.cc hwasan_report.cc hwasan_thread.cc diff --git a/lib/hwasan/hwasan.cc b/lib/hwasan/hwasan.cc index da95891d8..e2bfea5e4 100644 --- a/lib/hwasan/hwasan.cc +++ b/lib/hwasan/hwasan.cc @@ -13,20 +13,20 @@ //===----------------------------------------------------------------------===// #include "hwasan.h" -#include "hwasan_mapping.h" +#include "hwasan_checks.h" #include "hwasan_poisoning.h" #include "hwasan_report.h" #include "hwasan_thread.h" #include "hwasan_thread_list.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_procmaps.h" +#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_symbolizer.h" -#include "sanitizer_common/sanitizer_stackdepot.h" #include "ubsan/ubsan_flags.h" #include "ubsan/ubsan_init.h" @@ -229,8 +229,8 @@ static InternalMmapVectorNoCtor<FrameDescriptionArray> AllFrames; void InitFrameDescriptors(uptr b, uptr e) { FrameDescription *beg = reinterpret_cast<FrameDescription *>(b); FrameDescription *end = reinterpret_cast<FrameDescription *>(e); - // Must have at least one entry, which we can use for a linked list. - CHECK_GE(end - beg, 1U); + if (beg == end) + return; AllFrames.push_back({beg, end}); if (Verbosity()) for (FrameDescription *frame_descr = beg; frame_descr < end; frame_descr++) @@ -365,63 +365,6 @@ void __sanitizer_unaligned_store64(uu64 *p, u64 x) { *p = x; } -template<unsigned X> -__attribute__((always_inline)) -static void SigTrap(uptr p) { -#if defined(__aarch64__) - (void)p; - // 0x900 is added to do not interfere with the kernel use of lower values of - // brk immediate. - // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch. - asm("brk %0\n\t" ::"n"(0x900 + X)); -#elif defined(__x86_64__) - // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes - // total. The pointer is passed via rdi. - // 0x40 is added as a safeguard, to help distinguish our trap from others and - // to avoid 0 offsets in the command (otherwise it'll be reduced to a - // different nop command, the three bytes one). - asm volatile( - "int3\n" - "nopl %c0(%%rax)\n" - :: "n"(0x40 + X), "D"(p)); -#else - // FIXME: not always sigill. - __builtin_trap(); -#endif - // __builtin_unreachable(); -} - -enum class ErrorAction { Abort, Recover }; -enum class AccessType { Load, Store }; - -template <ErrorAction EA, AccessType AT, unsigned LogSize> -__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) { - tag_t ptr_tag = GetTagFromPointer(p); - uptr ptr_raw = p & ~kAddressTagMask; - tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw); - if (UNLIKELY(ptr_tag != mem_tag)) { - SigTrap<0x20 * (EA == ErrorAction::Recover) + - 0x10 * (AT == AccessType::Store) + LogSize>(p); - if (EA == ErrorAction::Abort) __builtin_unreachable(); - } -} - -template <ErrorAction EA, AccessType AT> -__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p, - uptr sz) { - CHECK_NE(0, sz); - tag_t ptr_tag = GetTagFromPointer(p); - uptr ptr_raw = p & ~kAddressTagMask; - tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw); - tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1); - for (tag_t *t = shadow_first; t <= shadow_last; ++t) - if (UNLIKELY(ptr_tag != *t)) { - SigTrap<0x20 * (EA == ErrorAction::Recover) + - 0x10 * (AT == AccessType::Store) + 0xf>(p); - if (EA == ErrorAction::Abort) __builtin_unreachable(); - } -} - void __hwasan_loadN(uptr p, uptr sz) { CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz); } diff --git a/lib/hwasan/hwasan.h b/lib/hwasan/hwasan.h index 64b1f1a3d..ce9e904c5 100644 --- a/lib/hwasan/hwasan.h +++ b/lib/hwasan/hwasan.h @@ -77,7 +77,6 @@ void InitializeInterceptors(); void HwasanAllocatorInit(); void HwasanAllocatorThreadFinish(); -void HwasanDeallocate(StackTrace *stack, void *ptr); void *hwasan_malloc(uptr size, StackTrace *stack); void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack); @@ -88,6 +87,7 @@ void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack); void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack); int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size, StackTrace *stack); +void hwasan_free(void *ptr, StackTrace *stack); void InstallTrapHandler(); void InstallAtExitHandler(); diff --git a/lib/hwasan/hwasan_allocator.cc b/lib/hwasan/hwasan_allocator.cc index 8fd2349d9..8487ed7e1 100644 --- a/lib/hwasan/hwasan_allocator.cc +++ b/lib/hwasan/hwasan_allocator.cc @@ -21,6 +21,11 @@ #include "hwasan_thread.h" #include "hwasan_report.h" +#if HWASAN_WITH_INTERCEPTORS +DEFINE_REAL(void *, realloc, void *ptr, uptr size) +DEFINE_REAL(void, free, void *ptr) +#endif + namespace __hwasan { static Allocator allocator; @@ -199,7 +204,7 @@ static bool PointerAndMemoryTagsMatch(void *tagged_ptr) { return ptr_tag == mem_tag; } -void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { +static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { CHECK(tagged_ptr); HWASAN_FREE_HOOK(tagged_ptr); @@ -253,8 +258,8 @@ void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { } } -void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old, uptr new_size, - uptr alignment) { +static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old, + uptr new_size, uptr alignment) { if (!PointerAndMemoryTagsMatch(tagged_ptr_old)) ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr_old)); @@ -271,7 +276,7 @@ void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old, uptr new_size, return tagged_ptr_new; } -void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) { +static void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) { if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { if (AllocatorMayReturnNull()) return nullptr; @@ -315,6 +320,14 @@ void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack) { void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack) { if (!ptr) return SetErrnoOnNull(HwasanAllocate(stack, size, sizeof(u64), false)); + +#if HWASAN_WITH_INTERCEPTORS + // A tag of 0 means that this is a system allocator allocation, so we must use + // the system allocator to realloc it. + if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0) + return REAL(realloc)(ptr, size); +#endif + if (size == 0) { HwasanDeallocate(stack, ptr); return nullptr; @@ -376,6 +389,17 @@ int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size, return 0; } +void hwasan_free(void *ptr, StackTrace *stack) { +#if HWASAN_WITH_INTERCEPTORS + // A tag of 0 means that this is a system allocator allocation, so we must use + // the system allocator to free it. + if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0) + return REAL(free)(ptr); +#endif + + return HwasanDeallocate(stack, ptr); +} + } // namespace __hwasan using namespace __hwasan; @@ -385,6 +409,15 @@ void __hwasan_enable_allocator_tagging() { } void __hwasan_disable_allocator_tagging() { +#if HWASAN_WITH_INTERCEPTORS + // Allocator tagging must be enabled for the system allocator fallback to work + // correctly. This means that we can't disable it at runtime if it was enabled + // at startup since that might result in our deallocations going to the system + // allocator. If tagging was disabled at startup we avoid this problem by + // disabling the fallback altogether. + CHECK(flags()->disable_allocator_tagging); +#endif + atomic_store_relaxed(&hwasan_allocator_tagging_enabled, 0); } diff --git a/lib/hwasan/hwasan_allocator.h b/lib/hwasan/hwasan_allocator.h index b3f2d6c84..6ab722fa6 100644 --- a/lib/hwasan/hwasan_allocator.h +++ b/lib/hwasan/hwasan_allocator.h @@ -14,6 +14,7 @@ #ifndef HWASAN_ALLOCATOR_H #define HWASAN_ALLOCATOR_H +#include "interception/interception.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_allocator_checks.h" #include "sanitizer_common/sanitizer_allocator_interface.h" @@ -26,6 +27,11 @@ #error Unsupported platform #endif +#if HWASAN_WITH_INTERCEPTORS +DECLARE_REAL(void *, realloc, void *ptr, uptr size) +DECLARE_REAL(void, free, void *ptr) +#endif + namespace __hwasan { struct Metadata { @@ -45,28 +51,22 @@ struct HwasanMapUnmapCallback { }; static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G -static const uptr kRegionSizeLog = 20; -static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; -typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; -struct AP32 { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; +struct AP64 { + static const uptr kSpaceBeg = ~0ULL; + static const uptr kSpaceSize = 0x2000000000ULL; static const uptr kMetadataSize = sizeof(Metadata); - typedef __sanitizer::CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __hwasan::kRegionSizeLog; + typedef __sanitizer::VeryDenseSizeClassMap SizeClassMap; using AddressSpaceView = LocalAddressSpaceView; - using ByteMap = __hwasan::ByteMap; typedef HwasanMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; }; -typedef SizeClassAllocator32<AP32> PrimaryAllocator; +typedef SizeClassAllocator64<AP64> PrimaryAllocator; typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; typedef LargeMmapAllocator<HwasanMapUnmapCallback> SecondaryAllocator; typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator> Allocator; - void AllocatorSwallowThreadLocalCache(AllocatorCache *cache); class HwasanChunkView { diff --git a/lib/hwasan/hwasan_checks.h b/lib/hwasan/hwasan_checks.h new file mode 100644 index 000000000..688b5e2be --- /dev/null +++ b/lib/hwasan/hwasan_checks.h @@ -0,0 +1,80 @@ +//===-- hwasan_checks.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer. +// +//===----------------------------------------------------------------------===// + +#ifndef HWASAN_CHECKS_H +#define HWASAN_CHECKS_H + +#include "hwasan_mapping.h" + +namespace __hwasan { +template <unsigned X> +__attribute__((always_inline)) static void SigTrap(uptr p) { +#if defined(__aarch64__) + (void)p; + // 0x900 is added to do not interfere with the kernel use of lower values of + // brk immediate. + // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch. + asm("brk %0\n\t" ::"n"(0x900 + X)); +#elif defined(__x86_64__) + // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes + // total. The pointer is passed via rdi. + // 0x40 is added as a safeguard, to help distinguish our trap from others and + // to avoid 0 offsets in the command (otherwise it'll be reduced to a + // different nop command, the three bytes one). + asm volatile( + "int3\n" + "nopl %c0(%%rax)\n" ::"n"(0x40 + X), + "D"(p)); +#else + // FIXME: not always sigill. + __builtin_trap(); +#endif + // __builtin_unreachable(); +} + +enum class ErrorAction { Abort, Recover }; +enum class AccessType { Load, Store }; + +template <ErrorAction EA, AccessType AT, unsigned LogSize> +__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) { + tag_t ptr_tag = GetTagFromPointer(p); + uptr ptr_raw = p & ~kAddressTagMask; + tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw); + if (UNLIKELY(ptr_tag != mem_tag)) { + SigTrap<0x20 * (EA == ErrorAction::Recover) + + 0x10 * (AT == AccessType::Store) + LogSize>(p); + if (EA == ErrorAction::Abort) + __builtin_unreachable(); + } +} + +template <ErrorAction EA, AccessType AT> +__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p, + uptr sz) { + if (sz == 0) + return; + tag_t ptr_tag = GetTagFromPointer(p); + uptr ptr_raw = p & ~kAddressTagMask; + tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw); + tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1); + for (tag_t *t = shadow_first; t <= shadow_last; ++t) + if (UNLIKELY(ptr_tag != *t)) { + SigTrap<0x20 * (EA == ErrorAction::Recover) + + 0x10 * (AT == AccessType::Store) + 0xf>(p); + if (EA == ErrorAction::Abort) + __builtin_unreachable(); + } +} +} // end namespace __hwasan + +#endif // HWASAN_CHECKS_H diff --git a/lib/hwasan/hwasan_interceptors.cc b/lib/hwasan/hwasan_interceptors.cc index d20bdd95a..fb0dcb890 100644 --- a/lib/hwasan/hwasan_interceptors.cc +++ b/lib/hwasan/hwasan_interceptors.cc @@ -17,6 +17,7 @@ #include "interception/interception.h" #include "hwasan.h" +#include "hwasan_allocator.h" #include "hwasan_mapping.h" #include "hwasan_thread.h" #include "hwasan_poisoning.h" @@ -44,11 +45,6 @@ using __sanitizer::atomic_load; using __sanitizer::atomic_store; using __sanitizer::atomic_uintptr_t; -DECLARE_REAL(SIZE_T, strlen, const char *s) -DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) -DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n) -DECLARE_REAL(void *, memset, void *dest, int c, uptr n) - bool IsInInterceptorScope() { Thread *t = GetCurrentThread(); return t && t->InInterceptorScope(); @@ -130,13 +126,13 @@ void * __sanitizer_pvalloc(uptr size) { void __sanitizer_free(void *ptr) { GET_MALLOC_STACK_TRACE; if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; - HwasanDeallocate(&stack, ptr); + hwasan_free(ptr, &stack); } void __sanitizer_cfree(void *ptr) { GET_MALLOC_STACK_TRACE; if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; - HwasanDeallocate(&stack, ptr); + hwasan_free(ptr, &stack); } uptr __sanitizer_malloc_usable_size(const void *ptr) { @@ -222,33 +218,15 @@ INTERCEPTOR_ALIAS(void, malloc_stats, void); #endif // HWASAN_WITH_INTERCEPTORS -#if HWASAN_WITH_INTERCEPTORS -extern "C" int pthread_attr_init(void *attr); -extern "C" int pthread_attr_destroy(void *attr); - -struct ThreadStartArg { - thread_callback_t callback; - void *param; -}; - -static void *HwasanThreadStartFunc(void *arg) { - __hwasan_thread_enter(); - ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg); - UnmapOrDie(arg, GetPageSizeCached()); - return A.callback(A.param); -} - -INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), - void * param) { +#if HWASAN_WITH_INTERCEPTORS && !defined(__aarch64__) +INTERCEPTOR(int, pthread_create, void *th, void *attr, + void *(*callback)(void *), void *param) { ScopedTaggingDisabler disabler; - ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie( - GetPageSizeCached(), "pthread_create")); - *A = {callback, param}; int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr), - &HwasanThreadStartFunc, A); + callback, param); return res; } -#endif // HWASAN_WITH_INTERCEPTORS +#endif static void BeforeFork() { StackDepotLockAll(); @@ -289,8 +267,12 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(fork); #if HWASAN_WITH_INTERCEPTORS +#if !defined(__aarch64__) INTERCEPT_FUNCTION(pthread_create); #endif + INTERCEPT_FUNCTION(realloc); + INTERCEPT_FUNCTION(free); +#endif inited = 1; } diff --git a/lib/hwasan/hwasan_interface_internal.h b/lib/hwasan/hwasan_interface_internal.h index 0e49a3fc2..d3b2087d0 100644 --- a/lib/hwasan/hwasan_interface_internal.h +++ b/lib/hwasan/hwasan_interface_internal.h @@ -194,6 +194,13 @@ void * __sanitizer_realloc(void *ptr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void * __sanitizer_malloc(uptr size); + +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memcpy(void *dst, const void *src, uptr size); +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memset(void *s, int c, uptr n); +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memmove(void *dest, const void *src, uptr n); } // extern "C" #endif // HWASAN_INTERFACE_INTERNAL_H diff --git a/lib/hwasan/hwasan_linux.cc b/lib/hwasan/hwasan_linux.cc index af9378c31..5b0a8b4ac 100644 --- a/lib/hwasan/hwasan_linux.cc +++ b/lib/hwasan/hwasan_linux.cc @@ -40,6 +40,7 @@ #include "sanitizer_common/sanitizer_procmaps.h" #if HWASAN_WITH_INTERCEPTORS && !SANITIZER_ANDROID +SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL uptr __hwasan_tls; #endif @@ -301,7 +302,12 @@ void AndroidTestTlsSlot() {} #endif Thread *GetCurrentThread() { - auto *R = (StackAllocationsRingBuffer*)GetCurrentThreadLongPtr(); + uptr *ThreadLong = GetCurrentThreadLongPtr(); +#if HWASAN_WITH_INTERCEPTORS + if (!*ThreadLong) + __hwasan_thread_enter(); +#endif + auto *R = (StackAllocationsRingBuffer *)ThreadLong; return hwasanThreadList().GetThreadByBufferAddress((uptr)(R->Next())); } diff --git a/lib/hwasan/hwasan_memintrinsics.cc b/lib/hwasan/hwasan_memintrinsics.cc new file mode 100644 index 000000000..9cb844e45 --- /dev/null +++ b/lib/hwasan/hwasan_memintrinsics.cc @@ -0,0 +1,45 @@ +//===-- hwasan_memintrinsics.cc ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file is a part of HWAddressSanitizer and contains HWASAN versions of +/// memset, memcpy and memmove +/// +//===----------------------------------------------------------------------===// + +#include <string.h> +#include "hwasan.h" +#include "hwasan_checks.h" +#include "hwasan_flags.h" +#include "hwasan_interface_internal.h" +#include "sanitizer_common/sanitizer_libc.h" + +using namespace __hwasan; + +void *__hwasan_memset(void *block, int c, uptr size) { + CheckAddressSized<ErrorAction::Recover, AccessType::Store>( + reinterpret_cast<uptr>(block), size); + return memset(UntagPtr(block), c, size); +} + +void *__hwasan_memcpy(void *to, const void *from, uptr size) { + CheckAddressSized<ErrorAction::Recover, AccessType::Store>( + reinterpret_cast<uptr>(to), size); + CheckAddressSized<ErrorAction::Recover, AccessType::Load>( + reinterpret_cast<uptr>(from), size); + return memcpy(UntagPtr(to), UntagPtr(from), size); +} + +void *__hwasan_memmove(void *to, const void *from, uptr size) { + CheckAddressSized<ErrorAction::Recover, AccessType::Store>( + reinterpret_cast<uptr>(to), size); + CheckAddressSized<ErrorAction::Recover, AccessType::Load>( + reinterpret_cast<uptr>(from), size); + return memmove(UntagPtr(to), UntagPtr(from), size); +} diff --git a/lib/hwasan/hwasan_new_delete.cc b/lib/hwasan/hwasan_new_delete.cc index 63ca74edd..f2e8faf5d 100644 --- a/lib/hwasan/hwasan_new_delete.cc +++ b/lib/hwasan/hwasan_new_delete.cc @@ -51,7 +51,7 @@ void *operator new[](size_t size, std::nothrow_t const&) { #define OPERATOR_DELETE_BODY \ GET_MALLOC_STACK_TRACE; \ - if (ptr) HwasanDeallocate(&stack, ptr) + if (ptr) hwasan_free(ptr, &stack) INTERCEPTOR_ATTRIBUTE void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } diff --git a/lib/hwasan/hwasan_report.cc b/lib/hwasan/hwasan_report.cc index b5d310a34..ea3e4096d 100644 --- a/lib/hwasan/hwasan_report.cc +++ b/lib/hwasan/hwasan_report.cc @@ -233,7 +233,7 @@ void PrintAddressDescription( t->Announce(); // Temporary report section, needs to be improved. - Printf("Previosly allocated frames:\n"); + Printf("Previously allocated frames:\n"); auto *sa = (t == GetCurrentThread() && current_stack_allocations) ? current_stack_allocations : t->stack_allocations(); diff --git a/lib/hwasan/hwasan_thread.cc b/lib/hwasan/hwasan_thread.cc index 0d15c7e46..631c2813e 100644 --- a/lib/hwasan/hwasan_thread.cc +++ b/lib/hwasan/hwasan_thread.cc @@ -43,27 +43,18 @@ void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size) { // ScopedTaggingDisable needs GetCurrentThread to be set up. ScopedTaggingDisabler disabler; - // If this process is "init" (pid 1), /proc may not be mounted yet. - if (IsMainThread() && !FileExists("/proc/self/maps")) { - stack_top_ = stack_bottom_ = 0; - tls_begin_ = tls_end_ = 0; - } else { - uptr tls_size; - uptr stack_size; - GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, - &tls_begin_, &tls_size); - stack_top_ = stack_bottom_ + stack_size; - tls_end_ = tls_begin_ + tls_size; - + uptr tls_size; + uptr stack_size; + GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, &tls_begin_, + &tls_size); + stack_top_ = stack_bottom_ + stack_size; + tls_end_ = tls_begin_ + tls_size; + + if (stack_bottom_) { int local; CHECK(AddrIsInStack((uptr)&local)); CHECK(MemIsApp(stack_bottom_)); CHECK(MemIsApp(stack_top_ - 1)); - - if (stack_bottom_) { - CHECK(MemIsApp(stack_bottom_)); - CHECK(MemIsApp(stack_top_ - 1)); - } } if (flags()->verbose_threads) { diff --git a/lib/lsan/lsan_allocator.cc b/lib/lsan/lsan_allocator.cc index c58c35480..1b338bd59 100644 --- a/lib/lsan/lsan_allocator.cc +++ b/lib/lsan/lsan_allocator.cc @@ -34,9 +34,6 @@ static const uptr kMaxAllowedMallocSize = 4UL << 30; #else static const uptr kMaxAllowedMallocSize = 8UL << 30; #endif -typedef LargeMmapAllocator<> SecondaryAllocator; -typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, - SecondaryAllocator> Allocator; static Allocator allocator; diff --git a/lib/lsan/lsan_allocator.h b/lib/lsan/lsan_allocator.h index 23ebc11f6..4c4e02fc0 100644 --- a/lib/lsan/lsan_allocator.h +++ b/lib/lsan/lsan_allocator.h @@ -81,6 +81,7 @@ const uptr kAllocatorSize = 0x20000000000ULL; // 2T. const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. # endif +template <typename AddressSpaceViewTy> struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -88,11 +89,30 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name. typedef DefaultSizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; -typedef SizeClassAllocator64<AP64> PrimaryAllocator; +template <typename AddressSpaceView> +using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; +using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; #endif -typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; + +template <typename AddressSpaceView> +using AllocatorCacheASVT = + SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>; +using AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>; + +template <typename AddressSpaceView> +using SecondaryAllocatorASVT = + LargeMmapAllocator<NoOpMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray, + AddressSpaceView>; + +template <typename AddressSpaceView> +using AllocatorASVT = + CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>, + AllocatorCacheASVT<AddressSpaceView>, + SecondaryAllocatorASVT<AddressSpaceView>>; +using Allocator = AllocatorASVT<LocalAddressSpaceView>; AllocatorCache *GetAllocatorCache(); diff --git a/lib/msan/msan_allocator.cc b/lib/msan/msan_allocator.cc index 8b9fa6506..053ab0280 100644 --- a/lib/msan/msan_allocator.cc +++ b/lib/msan/msan_allocator.cc @@ -79,6 +79,7 @@ struct MsanMapUnmapCallback { typedef DefaultSizeClassMap SizeClassMap; typedef MsanMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = LocalAddressSpaceView; }; typedef SizeClassAllocator64<AP64> PrimaryAllocator; @@ -93,6 +94,7 @@ struct MsanMapUnmapCallback { typedef DefaultSizeClassMap SizeClassMap; typedef MsanMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = LocalAddressSpaceView; }; typedef SizeClassAllocator64<AP64> PrimaryAllocator; diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc index 385a650c4..0b0208884 100644 --- a/lib/msan/msan_linux.cc +++ b/lib/msan/msan_linux.cc @@ -175,6 +175,51 @@ void InstallAtExitHandler() { // ---------------------- TSD ---------------- {{{1 +#if SANITIZER_NETBSD || SANITIZER_FREEBSD +// Thread Static Data cannot be used in early init on NetBSD and FreeBSD. +// Reuse the MSan TSD API for compatibility with existing code +// with an alternative implementation. + +static void (*tsd_destructor)(void *tsd) = nullptr; + +struct tsd_key { + tsd_key() : key(nullptr) {} + ~tsd_key() { + CHECK(tsd_destructor); + if (key) + (*tsd_destructor)(key); + } + MsanThread *key; +}; + +static thread_local struct tsd_key key; + +void MsanTSDInit(void (*destructor)(void *tsd)) { + CHECK(!tsd_destructor); + tsd_destructor = destructor; +} + +MsanThread *GetCurrentThread() { + CHECK(tsd_destructor); + return key.key; +} + +void SetCurrentThread(MsanThread *tsd) { + CHECK(tsd_destructor); + CHECK(tsd); + CHECK(!key.key); + key.key = tsd; +} + +void MsanTSDDtor(void *tsd) { + CHECK(tsd_destructor); + CHECK_EQ(key.key, tsd); + key.key = nullptr; + // Make sure that signal handler can not see a stale current thread pointer. + atomic_signal_fence(memory_order_seq_cst); + MsanThread::TSDDtor(tsd); +} +#else static pthread_key_t tsd_key; static bool tsd_key_inited = false; @@ -211,6 +256,7 @@ void MsanTSDDtor(void *tsd) { atomic_signal_fence(memory_order_seq_cst); MsanThread::TSDDtor(tsd); } +#endif } // namespace __msan diff --git a/lib/profile/InstrProfData.inc b/lib/profile/InstrProfData.inc index eb4a792ce..454620ed9 100644 --- a/lib/profile/InstrProfData.inc +++ b/lib/profile/InstrProfData.inc @@ -308,14 +308,14 @@ typedef struct ValueProfRecord { #ifdef __cplusplus /*! - * \brief Return the number of value sites. + * Return the number of value sites. */ uint32_t getNumValueSites() const { return NumValueSites; } /*! - * \brief Read data from this record and save it to Record. + * Read data from this record and save it to Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); /* * In-place byte swap: * Do byte swap for this instance. \c Old is the original order before @@ -393,7 +393,7 @@ typedef struct ValueProfData { * Read data from this data and save it to \c Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); void operator delete(void *ptr) { ::operator delete(ptr); } #endif } ValueProfData; @@ -458,7 +458,7 @@ getValueProfRecordHeaderSize(uint32_t NumValueSites); #endif /*! - * \brief Return the \c ValueProfRecord header size including the + * Return the \c ValueProfRecord header size including the * padding bytes. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE @@ -471,7 +471,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { } /*! - * \brief Return the total size of the value profile record including the + * Return the total size of the value profile record including the * header and the value data. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE @@ -482,7 +482,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites, } /*! - * \brief Return the pointer to the start of value data array. + * Return the pointer to the start of value data array. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { @@ -491,7 +491,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { } /*! - * \brief Return the total number of value data for \c This record. + * Return the total number of value data for \c This record. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { @@ -503,7 +503,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { } /*! - * \brief Use this method to advance to the next \c This \c ValueProfRecord. + * Use this method to advance to the next \c This \c ValueProfRecord. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { @@ -514,7 +514,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { } /*! - * \brief Return the first \c ValueProfRecord instance. + * Return the first \c ValueProfRecord instance. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { diff --git a/lib/profile/InstrProfilingPlatformLinux.c b/lib/profile/InstrProfilingPlatformLinux.c index a517821a2..3764df1d8 100644 --- a/lib/profile/InstrProfilingPlatformLinux.c +++ b/lib/profile/InstrProfilingPlatformLinux.c @@ -8,7 +8,7 @@ \*===----------------------------------------------------------------------===*/ #if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ - (defined(__sun__) && defined(__svr4__)) + (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) #include <stdlib.h> diff --git a/lib/profile/InstrProfilingPlatformOther.c b/lib/profile/InstrProfilingPlatformOther.c index a339abc7f..7c2f14cfc 100644 --- a/lib/profile/InstrProfilingPlatformOther.c +++ b/lib/profile/InstrProfilingPlatformOther.c @@ -8,7 +8,7 @@ \*===----------------------------------------------------------------------===*/ #if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \ - !(defined(__sun__) && defined(__svr4__)) + !(defined(__sun__) && defined(__svr4__)) && !defined(__NetBSD__) #include <stdlib.h> diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt index a8bd56933..f7bf4b009 100644 --- a/lib/sanitizer_common/CMakeLists.txt +++ b/lib/sanitizer_common/CMakeLists.txt @@ -38,6 +38,7 @@ set(SANITIZER_SOURCES_NOTERMINATION sanitizer_suppressions.cc sanitizer_tls_get_addr.cc sanitizer_thread_registry.cc + sanitizer_type_traits.cc sanitizer_win.cc) if(UNIX AND NOT APPLE AND NOT OS_NAME MATCHES "SunOS") @@ -191,11 +192,8 @@ set(SANITIZER_IMPL_HEADERS include_directories(..) -set(SANITIZER_COMMON_DEFINITIONS) - -include(CheckIncludeFile) -append_have_file_definition(rpc/xdr.h HAVE_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) -append_have_file_definition(tirpc/rpc/xdr.h HAVE_TIRPC_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) +set(SANITIZER_COMMON_DEFINITIONS + HAVE_RPC_XDR_H=${HAVE_RPC_XDR_H}) set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(OFF SANITIZER_CFLAGS) diff --git a/lib/sanitizer_common/sanitizer_allocator_combined.h b/lib/sanitizer_common/sanitizer_allocator_combined.h index 1f874d60b..fcc4469c9 100644 --- a/lib/sanitizer_common/sanitizer_allocator_combined.h +++ b/lib/sanitizer_common/sanitizer_allocator_combined.h @@ -21,19 +21,28 @@ // PrimaryAllocator is used via a local AllocatorCache. // SecondaryAllocator can allocate anything, but is not efficient. template <class PrimaryAllocator, class AllocatorCache, - class SecondaryAllocator> // NOLINT + class SecondaryAllocator, + typename AddressSpaceViewTy = LocalAddressSpaceView> // NOLINT class CombinedAllocator { public: + using AddressSpaceView = AddressSpaceViewTy; + static_assert(is_same<AddressSpaceView, + typename PrimaryAllocator::AddressSpaceView>::value, + "PrimaryAllocator is using wrong AddressSpaceView"); + static_assert(is_same<AddressSpaceView, + typename SecondaryAllocator::AddressSpaceView>::value, + "SecondaryAllocator is using wrong AddressSpaceView"); + void InitLinkerInitialized(s32 release_to_os_interval_ms) { + stats_.InitLinkerInitialized(); primary_.Init(release_to_os_interval_ms); secondary_.InitLinkerInitialized(); - stats_.InitLinkerInitialized(); } void Init(s32 release_to_os_interval_ms) { + stats_.Init(); primary_.Init(release_to_os_interval_ms); secondary_.Init(); - stats_.Init(); } void *Allocate(AllocatorCache *cache, uptr size, uptr alignment) { @@ -194,4 +203,3 @@ class CombinedAllocator { SecondaryAllocator secondary_; AllocatorGlobalStats stats_; }; - diff --git a/lib/sanitizer_common/sanitizer_allocator_primary32.h b/lib/sanitizer_common/sanitizer_allocator_primary32.h index e5d637665..abaac3d1a 100644 --- a/lib/sanitizer_common/sanitizer_allocator_primary32.h +++ b/lib/sanitizer_common/sanitizer_allocator_primary32.h @@ -57,6 +57,10 @@ class SizeClassAllocator32 { typedef typename Params::ByteMap ByteMap; typedef typename Params::MapUnmapCallback MapUnmapCallback; + static_assert( + is_same<typename ByteMap::AddressSpaceView, AddressSpaceView>::value, + "AddressSpaceView type mismatch"); + static const bool kRandomShuffleChunks = Params::kFlags & SizeClassAllocator32FlagMasks::kRandomShuffleChunks; static const bool kUseSeparateSizeClassForBatch = Params::kFlags & @@ -109,9 +113,6 @@ class SizeClassAllocator32 { typedef SizeClassAllocator32LocalCache<ThisT> AllocatorCache; void Init(s32 release_to_os_interval_ms) { - static_assert( - is_same<typename ByteMap::AddressSpaceView, AddressSpaceView>::value, - "AddressSpaceView type mismatch"); possible_regions.Init(); internal_memset(size_class_info_array, 0, sizeof(size_class_info_array)); } diff --git a/lib/sanitizer_common/sanitizer_allocator_primary64.h b/lib/sanitizer_common/sanitizer_allocator_primary64.h index 6acb4f8bc..b063bf0d3 100644 --- a/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -46,6 +46,7 @@ struct SizeClassAllocator64FlagMasks { // Bit masks. template <class Params> class SizeClassAllocator64 { public: + using AddressSpaceView = typename Params::AddressSpaceView; static const uptr kSpaceBeg = Params::kSpaceBeg; static const uptr kSpaceSize = Params::kSpaceSize; static const uptr kMetadataSize = Params::kMetadataSize; @@ -294,8 +295,10 @@ class SizeClassAllocator64 { RegionInfo *region = GetRegionInfo(class_id); uptr chunk_size = ClassIdToSize(class_id); uptr region_beg = SpaceBeg() + class_id * kRegionSize; + uptr region_allocated_user_size = + AddressSpaceView::Load(region)->allocated_user; for (uptr chunk = region_beg; - chunk < region_beg + region->allocated_user; + chunk < region_beg + region_allocated_user_size; chunk += chunk_size) { // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk)); callback(chunk, arg); diff --git a/lib/sanitizer_common/sanitizer_allocator_secondary.h b/lib/sanitizer_common/sanitizer_allocator_secondary.h index 455fcf3b4..0c8505c34 100644 --- a/lib/sanitizer_common/sanitizer_allocator_secondary.h +++ b/lib/sanitizer_common/sanitizer_allocator_secondary.h @@ -69,9 +69,10 @@ typedef LargeMmapAllocatorPtrArrayDynamic DefaultLargeMmapAllocatorPtrArray; // sizes not covered by more efficient allocators (e.g. SizeClassAllocator64). template <class MapUnmapCallback = NoOpMapUnmapCallback, class PtrArrayT = DefaultLargeMmapAllocatorPtrArray, - class AddressSpaceView = LocalAddressSpaceView> + class AddressSpaceViewTy = LocalAddressSpaceView> class LargeMmapAllocator { public: + using AddressSpaceView = AddressSpaceViewTy; void InitLinkerInitialized() { page_size_ = GetPageSizeCached(); chunks_ = reinterpret_cast<Header**>(ptr_array_.Init()); @@ -203,10 +204,10 @@ class LargeMmapAllocator { void EnsureSortedChunks() { if (chunks_sorted_) return; - Header **chunks = AddressSpaceView::Load(chunks_, n_chunks_); + Header **chunks = AddressSpaceView::LoadWritable(chunks_, n_chunks_); Sort(reinterpret_cast<uptr *>(chunks), n_chunks_); for (uptr i = 0; i < n_chunks_; i++) - AddressSpaceView::Load(chunks[i])->chunk_idx = i; + AddressSpaceView::LoadWritable(chunks[i])->chunk_idx = i; chunks_sorted_ = true; } @@ -274,9 +275,9 @@ class LargeMmapAllocator { // The allocator must be locked when calling this function. void ForEachChunk(ForEachChunkCallback callback, void *arg) { EnsureSortedChunks(); // Avoid doing the sort while iterating. - Header **chunks = AddressSpaceView::Load(chunks_, n_chunks_); + const Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_); for (uptr i = 0; i < n_chunks_; i++) { - Header *t = chunks[i]; + const Header *t = chunks[i]; callback(reinterpret_cast<uptr>(GetUser(t)), arg); // Consistency check: verify that the array did not change. CHECK_EQ(chunks[i], t); @@ -300,7 +301,7 @@ class LargeMmapAllocator { return GetHeader(reinterpret_cast<uptr>(p)); } - void *GetUser(Header *h) { + void *GetUser(const Header *h) { CHECK(IsAligned((uptr)h, page_size_)); return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_); } diff --git a/lib/sanitizer_common/sanitizer_allocator_size_class_map.h b/lib/sanitizer_common/sanitizer_allocator_size_class_map.h index 07958424c..1c05fb8ff 100644 --- a/lib/sanitizer_common/sanitizer_allocator_size_class_map.h +++ b/lib/sanitizer_common/sanitizer_allocator_size_class_map.h @@ -237,3 +237,6 @@ typedef SizeClassMap<2, 5, 9, 16, 64, 14> VeryCompactSizeClassMap; // allowing for denser per-class arrays, smaller memory footprint and usually // better performances in threaded environments. typedef SizeClassMap<3, 4, 8, 17, 8, 10> DenseSizeClassMap; +// Similar to VeryCompact map above, this one has a small number of different +// size classes, and also reduced thread-local caches. +typedef SizeClassMap<2, 5, 9, 16, 8, 10> VeryDenseSizeClassMap; diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index a0615fa87..d0aebd994 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -61,6 +61,15 @@ INLINE int Verbosity() { return atomic_load(¤t_verbosity, memory_order_relaxed); } +#if SANITIZER_ANDROID +INLINE uptr GetPageSize() { +// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array. + return 4096; +} +INLINE uptr GetPageSizeCached() { + return 4096; +} +#else uptr GetPageSize(); extern uptr PageSizeCached; INLINE uptr GetPageSizeCached() { @@ -68,6 +77,7 @@ INLINE uptr GetPageSizeCached() { PageSizeCached = GetPageSize(); return PageSizeCached; } +#endif uptr GetMmapGranularity(); uptr GetMaxVirtualAddress(); uptr GetMaxUserVirtualAddress(); @@ -223,6 +233,7 @@ bool SetEnv(const char *name, const char *value); u32 GetUid(); void ReExec(); void CheckASLR(); +void CheckMPROTECT(); char **GetArgv(); char **GetEnviron(); void PrintCmdline(); diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 36d5f9c9f..50f783774 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -95,6 +95,7 @@ #define getutxent __getutxent50 #define getutxid __getutxid50 #define getutxline __getutxline50 +#define pututxline __pututxline50 #define glob __glob30 #define gmtime __gmtime50 #define gmtime_r __gmtime_r50 @@ -5694,9 +5695,15 @@ INTERCEPTOR(void *, tsearch, void *key, void **rootp, void unpoison_file(__sanitizer_FILE *fp) { #if SANITIZER_HAS_STRUCT_FILE COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp)); +#if SANITIZER_NETBSD + if (fp->_bf._base && fp->_bf._size > 0) + COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base, + fp->_bf._size); +#else if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end) COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base, fp->_IO_read_end - fp->_IO_read_base); +#endif #endif // SANITIZER_HAS_STRUCT_FILE } #endif @@ -6566,10 +6573,21 @@ INTERCEPTOR(void *, getutxline, void *ut) { COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz); return res; } +INTERCEPTOR(void *, pututxline, const void *ut) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut); + if (ut) + COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz); + void *res = REAL(pututxline)(ut); + if (res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz); + return res; +} #define INIT_UTMPX \ COMMON_INTERCEPT_FUNCTION(getutxent); \ COMMON_INTERCEPT_FUNCTION(getutxid); \ - COMMON_INTERCEPT_FUNCTION(getutxline); + COMMON_INTERCEPT_FUNCTION(getutxline); \ + COMMON_INTERCEPT_FUNCTION(pututxline); #else #define INIT_UTMPX #endif @@ -7061,12 +7079,19 @@ INTERCEPTOR(char *, devname, u64 dev, u32 type) { #endif #if SANITIZER_INTERCEPT_DEVNAME_R -INTERCEPTOR(int, devname_r, u64 dev, u32 type, char *path, uptr len) { +#if SANITIZER_NETBSD +#define DEVNAME_R_RETTYPE int +#define DEVNAME_R_SUCCESS(x) (!(x)) +#else +#define DEVNAME_R_RETTYPE char* +#define DEVNAME_R_SUCCESS(x) (x) +#endif +INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path, + uptr len) { void *ctx; - int res; COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len); - res = REAL(devname_r)(dev, type, path, len); - if (!res) + DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len); + if (DEVNAME_R_SUCCESS(res)) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1); return res; } @@ -7421,6 +7446,16 @@ INTERCEPTOR(void, regfree, const void *preg) { COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz); REAL(regfree)(preg); } +#define INIT_REGEX \ + COMMON_INTERCEPT_FUNCTION(regcomp); \ + COMMON_INTERCEPT_FUNCTION(regexec); \ + COMMON_INTERCEPT_FUNCTION(regerror); \ + COMMON_INTERCEPT_FUNCTION(regfree); +#else +#define INIT_REGEX +#endif + +#if SANITIZER_INTERCEPT_REGEXSUB INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub, const struct __sanitizer_regmatch *rm, const char *str) { void *ctx; @@ -7455,15 +7490,12 @@ INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub, } return res; } -#define INIT_REGEX \ - COMMON_INTERCEPT_FUNCTION(regcomp); \ - COMMON_INTERCEPT_FUNCTION(regexec); \ - COMMON_INTERCEPT_FUNCTION(regerror); \ - COMMON_INTERCEPT_FUNCTION(regfree); \ + +#define INIT_REGEXSUB \ COMMON_INTERCEPT_FUNCTION(regnsub); \ COMMON_INTERCEPT_FUNCTION(regasub); #else -#define INIT_REGEX +#define INIT_REGEXSUB #endif #if SANITIZER_INTERCEPT_FTS @@ -7539,6 +7571,8 @@ INTERCEPTOR(int, fts_close, void *ftsp) { INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp, SIZE_T *oldlenp, void *newp, SIZE_T newlen) { void *ctx; + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) + return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen); COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp, newlen); if (name) @@ -7561,6 +7595,8 @@ INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp, INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp, void *newp, SIZE_T newlen) { void *ctx; + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) + return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen); COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp, newlen); if (sname) @@ -7844,6 +7880,74 @@ INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base, #endif #if SANITIZER_INTERCEPT_CAPSICUM +#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...) \ + { \ + void *ctx; \ + COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \ + if (rights) \ + COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ + __sanitizer_cap_rights_t *ret = \ + REAL(cap_rights_init)(rights, ##__VA_ARGS__); \ + if (ret) \ + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ + return ret; \ + } + +#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...) \ + { \ + void *ctx; \ + COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \ + if (rights) \ + COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ + __sanitizer_cap_rights_t *ret = \ + REAL(cap_rights_set)(rights, ##__VA_ARGS__); \ + if (ret) \ + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ + return ret; \ + } + +#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...) \ + { \ + void *ctx; \ + COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \ + if (rights) \ + COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ + __sanitizer_cap_rights_t *ret = \ + REAL(cap_rights_clear)(rights, ##__VA_ARGS__); \ + if (ret) \ + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \ + return ret; \ + } + +#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...) \ + { \ + void *ctx; \ + COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \ + if (rights) \ + COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \ + return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__); \ + } + +INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init, + __sanitizer_cap_rights_t *rights) { + CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights); +} + +INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set, + __sanitizer_cap_rights_t *rights) { + CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights); +} + +INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear, + __sanitizer_cap_rights_t *rights) { + CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights); +} + +INTERCEPTOR(bool, cap_rights_is_set, + __sanitizer_cap_rights_t *rights) { + CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights); +} + INTERCEPTOR(int, cap_rights_limit, int fd, const __sanitizer_cap_rights_t *rights) { void *ctx; @@ -7932,6 +8036,10 @@ INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) { return ret; } #define INIT_CAPSICUM \ + COMMON_INTERCEPT_FUNCTION(cap_rights_init); \ + COMMON_INTERCEPT_FUNCTION(cap_rights_set); \ + COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \ + COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \ COMMON_INTERCEPT_FUNCTION(cap_rights_get); \ COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \ COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \ @@ -8435,9 +8543,10 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len, if (context) \ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ } \ - INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[SHA##LEN##_digest_length], \ + INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \ void *context) { \ void *ctx; \ + CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \ if (context) \ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \ @@ -8961,6 +9070,403 @@ INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) { #define INIT_CDB #endif +#if SANITIZER_INTERCEPT_GETFSENT +INTERCEPTOR(void *, getfsent) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getfsent); + void *ret = REAL(getfsent)(); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); + return ret; +} + +INTERCEPTOR(void *, getfsspec, const char *spec) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec); + if (spec) + COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1); + void *ret = REAL(getfsspec)(spec); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); + return ret; +} + +INTERCEPTOR(void *, getfsfile, const char *file) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file); + if (file) + COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1); + void *ret = REAL(getfsfile)(file); + if (ret) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz); + return ret; +} + +#define INIT_GETFSENT \ + COMMON_INTERCEPT_FUNCTION(getfsent); \ + COMMON_INTERCEPT_FUNCTION(getfsspec); \ + COMMON_INTERCEPT_FUNCTION(getfsfile); +#else +#define INIT_GETFSENT +#endif + +#if SANITIZER_INTERCEPT_ARC4RANDOM +INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len); + REAL(arc4random_buf)(buf, len); + if (buf && len) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len); +} + +INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen); + if (dat && datlen) + COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen); + REAL(arc4random_addrandom)(dat, datlen); +} + +#define INIT_ARC4RANDOM \ + COMMON_INTERCEPT_FUNCTION(arc4random_buf); \ + COMMON_INTERCEPT_FUNCTION(arc4random_addrandom); +#else +#define INIT_ARC4RANDOM +#endif + +#if SANITIZER_INTERCEPT_POPEN +INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type); + if (command) + COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1); + if (type) + COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1); + __sanitizer_FILE *res = REAL(popen)(command, type); + COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr); + if (res) unpoison_file(res); + return res; +} +#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen) +#else +#define INIT_POPEN +#endif + +#if SANITIZER_INTERCEPT_POPENVE +INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path, + char *const *argv, char *const *envp, const char *type) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type); + if (path) + COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); + if (argv) { + for (char *const *pa = argv; ; ++pa) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **)); + if (!*pa) + break; + COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1); + } + } + if (envp) { + for (char *const *pa = envp; ; ++pa) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **)); + if (!*pa) + break; + COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1); + } + } + if (type) + COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1); + __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type); + COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr); + if (res) unpoison_file(res); + return res; +} +#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve) +#else +#define INIT_POPENVE +#endif + +#if SANITIZER_INTERCEPT_PCLOSE +INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp); + COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp); + const FileMetadata *m = GetInterceptorMetadata(fp); + int res = REAL(pclose)(fp); + if (m) { + COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size); + DeleteInterceptorMetadata(fp); + } + return res; +} +#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose); +#else +#define INIT_PCLOSE +#endif + +#if SANITIZER_INTERCEPT_FUNOPEN +typedef int (*funopen_readfn)(void *cookie, char *buf, int len); +typedef int (*funopen_writefn)(void *cookie, const char *buf, int len); +typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence); +typedef int (*funopen_closefn)(void *cookie); + +struct WrappedFunopenCookie { + void *real_cookie; + funopen_readfn real_read; + funopen_writefn real_write; + funopen_seekfn real_seek; + funopen_closefn real_close; +}; + +static int wrapped_funopen_read(void *cookie, char *buf, int len) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; + funopen_readfn real_read = wrapped_cookie->real_read; + return real_read(wrapped_cookie->real_cookie, buf, len); +} + +static int wrapped_funopen_write(void *cookie, const char *buf, int len) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; + funopen_writefn real_write = wrapped_cookie->real_write; + return real_write(wrapped_cookie->real_cookie, buf, len); +} + +static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; + funopen_seekfn real_seek = wrapped_cookie->real_seek; + return real_seek(wrapped_cookie->real_cookie, offset, whence); +} + +static int wrapped_funopen_close(void *cookie) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(1); + WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie; + funopen_closefn real_close = wrapped_cookie->real_close; + int res = real_close(wrapped_cookie->real_cookie); + InternalFree(wrapped_cookie); + return res; +} + +INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn, + funopen_writefn writefn, funopen_seekfn seekfn, + funopen_closefn closefn) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn, + closefn); + + WrappedFunopenCookie *wrapped_cookie = + (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie)); + wrapped_cookie->real_cookie = cookie; + wrapped_cookie->real_read = readfn; + wrapped_cookie->real_write = writefn; + wrapped_cookie->real_seek = seekfn; + wrapped_cookie->real_close = closefn; + + __sanitizer_FILE *res = + REAL(funopen)(wrapped_cookie, + readfn ? wrapped_funopen_read : nullptr, + writefn ? wrapped_funopen_write : nullptr, + seekfn ? wrapped_funopen_seek : nullptr, + closefn ? wrapped_funopen_close : nullptr); + if (res) + unpoison_file(res); + return res; +} +#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen) +#else +#define INIT_FUNOPEN +#endif + +#if SANITIZER_INTERCEPT_FUNOPEN2 +typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len); +typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len); +typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence); +typedef int (*funopen2_flushfn)(void *cookie); +typedef int (*funopen2_closefn)(void *cookie); + +struct WrappedFunopen2Cookie { + void *real_cookie; + funopen2_readfn real_read; + funopen2_writefn real_write; + funopen2_seekfn real_seek; + funopen2_flushfn real_flush; + funopen2_closefn real_close; +}; + +static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; + funopen2_readfn real_read = wrapped_cookie->real_read; + return real_read(wrapped_cookie->real_cookie, buf, len); +} + +static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf, + SIZE_T len) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; + funopen2_writefn real_write = wrapped_cookie->real_write; + return real_write(wrapped_cookie->real_cookie, buf, len); +} + +static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); + WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; + funopen2_seekfn real_seek = wrapped_cookie->real_seek; + return real_seek(wrapped_cookie->real_cookie, offset, whence); +} + +static int wrapped_funopen2_flush(void *cookie) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(1); + WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; + funopen2_flushfn real_flush = wrapped_cookie->real_flush; + return real_flush(wrapped_cookie->real_cookie); +} + +static int wrapped_funopen2_close(void *cookie) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(1); + WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie; + funopen2_closefn real_close = wrapped_cookie->real_close; + int res = real_close(wrapped_cookie->real_cookie); + InternalFree(wrapped_cookie); + return res; +} + +INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn, + funopen2_writefn writefn, funopen2_seekfn seekfn, + funopen2_flushfn flushfn, funopen2_closefn closefn) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn, + flushfn, closefn); + + WrappedFunopen2Cookie *wrapped_cookie = + (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie)); + wrapped_cookie->real_cookie = cookie; + wrapped_cookie->real_read = readfn; + wrapped_cookie->real_write = writefn; + wrapped_cookie->real_seek = seekfn; + wrapped_cookie->real_flush = flushfn; + wrapped_cookie->real_close = closefn; + + __sanitizer_FILE *res = + REAL(funopen2)(wrapped_cookie, + readfn ? wrapped_funopen2_read : nullptr, + writefn ? wrapped_funopen2_write : nullptr, + seekfn ? wrapped_funopen2_seek : nullptr, + flushfn ? wrapped_funopen2_flush : nullptr, + closefn ? wrapped_funopen2_close : nullptr); + if (res) + unpoison_file(res); + return res; +} +#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2) +#else +#define INIT_FUNOPEN2 +#endif + +#if SANITIZER_INTERCEPT_FDEVNAME +INTERCEPTOR(char *, fdevname, int fd) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + char *name = REAL(fdevname)(fd); + if (name) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1); + if (fd > 0) + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); + } + return name; +} + +INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + char *name = REAL(fdevname_r)(fd, buf, len); + if (name && buf && len > 0) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1); + if (fd > 0) + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); + } + return name; +} + +#define INIT_FDEVNAME \ + COMMON_INTERCEPT_FUNCTION(fdevname); \ + COMMON_INTERCEPT_FUNCTION(fdevname_r); +#else +#define INIT_FDEVNAME +#endif + +#if SANITIZER_INTERCEPT_GETUSERSHELL +INTERCEPTOR(char *, getusershell) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getusershell); + char *res = REAL(getusershell)(); + if (res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + return res; +} + +#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell); +#else +#define INIT_GETUSERSHELL +#endif + +#if SANITIZER_INTERCEPT_SL_INIT +INTERCEPTOR(void *, sl_init) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sl_init); + void *res = REAL(sl_init)(); + if (res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz); + return res; +} + +INTERCEPTOR(int, sl_add, void *sl, char *item) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item); + if (sl) + COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); + if (item) + COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1); + int res = REAL(sl_add)(sl, item); + if (!res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); + return res; +} + +INTERCEPTOR(char *, sl_find, void *sl, const char *item) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item); + if (sl) + COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); + if (item) + COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1); + char *res = REAL(sl_find)(sl, item); + if (res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + return res; +} + +INTERCEPTOR(void, sl_free, void *sl, int freeall) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall); + if (sl) + COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz); + REAL(sl_free)(sl, freeall); +} + +#define INIT_SL_INIT \ + COMMON_INTERCEPT_FUNCTION(sl_init); \ + COMMON_INTERCEPT_FUNCTION(sl_add); \ + COMMON_INTERCEPT_FUNCTION(sl_find); \ + COMMON_INTERCEPT_FUNCTION(sl_free); +#else +#define INIT_SL_INIT +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = @@ -9220,6 +9726,7 @@ static void InitializeCommonInterceptors() { INIT_SETVBUF; INIT_GETVFSSTAT; INIT_REGEX; + INIT_REGEXSUB; INIT_FTS; INIT_SYSCTL; INIT_ASYSCTL; @@ -9240,6 +9747,16 @@ static void InitializeCommonInterceptors() { INIT_SHA2; INIT_VIS; INIT_CDB; + INIT_GETFSENT; + INIT_ARC4RANDOM; + INIT_POPEN; + INIT_POPENVE; + INIT_PCLOSE; + INIT_FUNOPEN; + INIT_FUNOPEN2; + INIT_FDEVNAME; + INIT_GETUSERSHELL; + INIT_SL_INIT; INIT___PRINTF_CHK; } diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index ab42b2167..1c0995b2d 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -25,7 +25,7 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) { SoftRssLimitExceededCallback = Callback; } -#if SANITIZER_LINUX && !SANITIZER_GO +#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO // Weak default implementation for when sanitizer_stackdepot is not linked in. SANITIZER_WEAK_ATTRIBUTE StackDepotStats *StackDepotGetStats() { return nullptr; @@ -114,7 +114,7 @@ void WriteToSyslog(const char *msg) { } void MaybeStartBackgroudThread() { -#if SANITIZER_LINUX && \ +#if (SANITIZER_LINUX || SANITIZER_NETBSD) && \ !SANITIZER_GO // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. if (!common_flags()->hard_rss_limit_mb && diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index cfe8af893..b047741b9 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -103,7 +103,7 @@ COMMON_FLAG(bool, allow_user_segv_handler, true, "handle_*=1 will be upgraded to handle_*=2.") COMMON_FLAG(bool, use_sigaltstack, true, "If set, uses alternate stack for signal handling.") -COMMON_FLAG(bool, detect_deadlocks, false, +COMMON_FLAG(bool, detect_deadlocks, true, "If set, deadlock detection is enabled.") COMMON_FLAG( uptr, clear_shadow_mmap_threshold, 64 * 1024, @@ -243,3 +243,6 @@ COMMON_FLAG(bool, dump_registers, true, COMMON_FLAG(bool, detect_write_exec, false, "If true, triggers warning when writable-executable pages requests " "are being made") +COMMON_FLAG(bool, test_only_emulate_no_memorymap, false, + "TEST ONLY fail to read memory mappings to emulate sanitized " + "\"init\"") diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cc b/lib/sanitizer_common/sanitizer_fuchsia.cc index 069866641..2c259b6cd 100644 --- a/lib/sanitizer_common/sanitizer_fuchsia.cc +++ b/lib/sanitizer_common/sanitizer_fuchsia.cc @@ -89,6 +89,7 @@ void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) { void InitializePlatformEarly() {} void MaybeReexec() {} void CheckASLR() {} +void CheckMPROTECT() {} void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {} void DisableCoreDumperIfNecessary() {} void InstallDeadlySignalHandlers(SignalHandlerType handler) {} @@ -209,10 +210,10 @@ uptr ReservedAddressRange::Init(uptr init_size, const char *name, uintptr_t base; zx_handle_t vmar; zx_status_t status = - _zx_vmar_allocate_old(_zx_vmar_root_self(), 0, init_size, - ZX_VM_FLAG_CAN_MAP_READ | ZX_VM_FLAG_CAN_MAP_WRITE | - ZX_VM_FLAG_CAN_MAP_SPECIFIC, - &vmar, &base); + _zx_vmar_allocate( + _zx_vmar_root_self(), + ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, + 0, init_size, &vmar, &base); if (status != ZX_OK) ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status); base_ = reinterpret_cast<void *>(base); diff --git a/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc b/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc index dcfce3c1e..86cb44047 100644 --- a/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc +++ b/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc @@ -25,7 +25,7 @@ struct ioctl_desc { const char *name; }; -const unsigned ioctl_table_max = 1201; +const unsigned ioctl_table_max = 1202; static ioctl_desc ioctl_table[ioctl_table_max]; static unsigned ioctl_table_size = 0; @@ -649,6 +649,23 @@ static void ioctl_table_fill() { _(SPKRTUNE, NONE, 0); _(SPKRGETVOL, WRITE, sizeof(unsigned int)); _(SPKRSETVOL, READ, sizeof(unsigned int)); + /* Entries from file: dev/nvmm/nvmm_ioctl.h */ +#if 0 /* WIP */ + _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz); + _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz); + _(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz); + _(NVMM_IOC_MACHINE_CONFIGURE, READ, struct_nvmm_ioc_machine_configure_sz); + _(NVMM_IOC_VCPU_CREATE, READ, struct_nvmm_ioc_vcpu_create_sz); + _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz); + _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz); + _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz); + _(NVMM_IOC_VCPU_INJECT, READWRITE, struct_nvmm_ioc_vcpu_inject_sz); + _(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz); + _(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz); + _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz); + _(NVMM_IOC_HVA_MAP, READ, struct_nvmm_ioc_hva_map_sz); + _(NVMM_IOC_HVA_UNMAP, READ, struct_nvmm_ioc_hva_unmap_sz); +#endif /* Entries from file: fs/autofs/autofs_ioctl.h */ _(AUTOFSREQUEST, WRITE, struct_autofs_daemon_request_sz); _(AUTOFSDONE, READ, struct_autofs_daemon_done_sz); @@ -1192,6 +1209,7 @@ static void ioctl_table_fill() { _(SIOCSLINKSTR, READ, struct_ifdrv_sz); _(SIOCGETHERCAP, READWRITE, struct_eccapreq_sz); _(SIOCGIFINDEX, READWRITE, struct_ifreq_sz); + _(SIOCSETHERCAP, READ, struct_eccapreq_sz); _(SIOCGUMBINFO, READWRITE, struct_ifreq_sz); _(SIOCSUMBPARAM, READ, struct_ifreq_sz); _(SIOCGUMBPARAM, READWRITE, struct_ifreq_sz); diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 6cfb61506..48795674c 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -381,6 +381,10 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } +uptr internal_dup(int oldfd) { + return internal_syscall(SYSCALL(dup), oldfd); +} + uptr internal_dup2(int oldfd, int newfd) { #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0); @@ -449,6 +453,8 @@ uptr internal_execve(const char *filename, char *const argv[], // ----------------- sanitizer_common.h bool FileExists(const char *filename) { + if (ShouldMockFailureToOpen(filename)) + return false; struct stat st; #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0)) @@ -1004,6 +1010,8 @@ static uptr GetKernelAreaSize() { // Firstly check if there are writable segments // mapped to top gigabyte (e.g. stack). MemoryMappingLayout proc_maps(/*cache_enabled*/true); + if (proc_maps.Error()) + return 0; MemoryMappedSegment segment; while (proc_maps.Next(&segment)) { if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0; @@ -1069,11 +1077,9 @@ uptr GetMaxUserVirtualAddress() { return addr; } +#if !SANITIZER_ANDROID uptr GetPageSize() { -// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array. -#if SANITIZER_ANDROID - return 4096; -#elif SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) +#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) return EXEC_PAGESIZE; #elif SANITIZER_USE_GETAUXVAL return getauxval(AT_PAGESZ); @@ -1089,6 +1095,7 @@ uptr GetPageSize() { return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. #endif } +#endif // !SANITIZER_ANDROID #if !SANITIZER_OPENBSD uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { @@ -2019,6 +2026,30 @@ void CheckASLR() { #endif } +void CheckMPROTECT() { +#if SANITIZER_NETBSD + int mib[3]; + int paxflags; + uptr len = sizeof(paxflags); + + mib[0] = CTL_PROC; + mib[1] = internal_getpid(); + mib[2] = PROC_PID_PAXFLAGS; + + if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) { + Printf("sysctl failed\n"); + Die(); + } + + if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_MPROTECT)) { + Printf("This sanitizer is not compatible with enabled MPROTECT\n"); + Die(); + } +#else + // Do nothing +#endif +} + void PrintModuleMap() { } void CheckNoDeepBind(const char *filename, int flag) { diff --git a/lib/sanitizer_common/sanitizer_linux.h b/lib/sanitizer_common/sanitizer_linux.h index 6f5387e16..c309e33f8 100644 --- a/lib/sanitizer_common/sanitizer_linux.h +++ b/lib/sanitizer_common/sanitizer_linux.h @@ -134,13 +134,13 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); #error "Unsupported architecture." #endif -// The Android Bionic team has allocated a TLS slot for TSan starting with N, -// given that Android currently doesn't support ELF TLS. It is used to store -// Sanitizers thread specific data. -static const int TLS_SLOT_TSAN = 8; +// The Android Bionic team has allocated a TLS slot for sanitizers starting +// with Q, given that Android currently doesn't support ELF TLS. It is used to +// store sanitizer thread specific data. +static const int TLS_SLOT_SANITIZER = 6; ALWAYS_INLINE uptr *get_android_tls_ptr() { - return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_TSAN]); + return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]); } #endif // SANITIZER_ANDROID diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 84da23e3f..6ce47ec62 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -100,6 +100,10 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, // Find the mapping that contains a stack variable. MemoryMappingLayout proc_maps(/*cache_enabled*/true); + if (proc_maps.Error()) { + *stack_top = *stack_bottom = 0; + return; + } MemoryMappedSegment segment; uptr prev_end = 0; while (proc_maps.Next(&segment)) { diff --git a/lib/sanitizer_common/sanitizer_local_address_space_view.h b/lib/sanitizer_common/sanitizer_local_address_space_view.h index 9fbf593f4..ec1847abc 100644 --- a/lib/sanitizer_common/sanitizer_local_address_space_view.h +++ b/lib/sanitizer_common/sanitizer_local_address_space_view.h @@ -12,7 +12,7 @@ // provides a simple interface to load memory from another process (i.e. // out-of-process) // -// The `AddressSpaveView` interface requires that the type can be used as a +// The `AddressSpaceView` interface requires that the type can be used as a // template parameter to objects that wish to be able to operate in an // out-of-process manner. In normal usage, objects are in-process and are thus // instantiated with the `LocalAddressSpaceView` type. This type is used to @@ -31,18 +31,42 @@ namespace __sanitizer { struct LocalAddressSpaceView { - // Load memory `sizeof(T) * num_elements` bytes of memory - // from the target process (always local for this implementation) - // starting at address `target_address`. The local copy of - // this memory is returned as a pointer. It is guaranteed that + // Load memory `sizeof(T) * num_elements` bytes of memory from the target + // process (always local for this implementation) starting at address + // `target_address`. The local copy of this memory is returned as a pointer. + // The caller should not write to this memory. The behaviour when doing so is + // undefined. Callers should use `LoadWritable()` to get access to memory + // that is writable. // - // * That the function will always return the same value - // for a given set of arguments. - // * That the memory returned is writable and that writes will persist. + // The lifetime of loaded memory is implementation defined. + template <typename T> + static const T *Load(const T *target_address, uptr num_elements = 1) { + // The target address space is the local address space so + // nothing needs to be copied. Just return the pointer. + return target_address; + } + + // Load memory `sizeof(T) * num_elements` bytes of memory from the target + // process (always local for this implementation) starting at address + // `target_address`. The local copy of this memory is returned as a pointer. + // The memory returned may be written to. + // + // Writes made to the returned memory will be visible in the memory returned + // by subsequent `Load()` or `LoadWritable()` calls provided the + // `target_address` parameter is the same. It is not guaranteed that the + // memory returned by previous calls to `Load()` will contain any performed + // writes. If two or more overlapping regions of memory are loaded via + // separate calls to `LoadWritable()`, it is implementation defined whether + // writes made to the region returned by one call are visible in the regions + // returned by other calls. + // + // Given the above it is recommended to load the largest possible object + // that requires modification (e.g. a class) rather than individual fields + // from a class to avoid issues with overlapping writable regions. // // The lifetime of loaded memory is implementation defined. template <typename T> - static T *Load(T *target_address, uptr num_elements = 1) { + static T *LoadWritable(T *target_address, uptr num_elements = 1) { // The target address space is the local address space so // nothing needs to be copied. Just return the pointer. return target_address; diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 95c47babe..8954a7a88 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -174,6 +174,10 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } +uptr internal_dup(int oldfd) { + return dup(oldfd); +} + uptr internal_dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); } @@ -278,6 +282,8 @@ uptr internal_waitpid(int pid, int *status, int options) { // ----------------- sanitizer_common.h bool FileExists(const char *filename) { + if (ShouldMockFailureToOpen(filename)) + return false; struct stat st; if (stat(filename, &st)) return false; @@ -373,6 +379,10 @@ void CheckASLR() { // Do nothing } +void CheckMPROTECT() { + // Do nothing +} + uptr GetPageSize() { return sysconf(_SC_PAGESIZE); } diff --git a/lib/sanitizer_common/sanitizer_netbsd.cc b/lib/sanitizer_common/sanitizer_netbsd.cc index 83beb008f..80d0855ef 100644 --- a/lib/sanitizer_common/sanitizer_netbsd.cc +++ b/lib/sanitizer_common/sanitizer_netbsd.cc @@ -169,6 +169,11 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } +uptr internal_dup(int oldfd) { + DEFINE__REAL(int, dup, int a); + return _REAL(dup, oldfd); +} + uptr internal_dup2(int oldfd, int newfd) { DEFINE__REAL(int, dup2, int a, int b); return _REAL(dup2, oldfd, newfd); @@ -202,7 +207,7 @@ void internal__exit(int exitcode) { unsigned int internal_sleep(unsigned int seconds) { struct timespec ts; - ts.tv_sec = 1; + ts.tv_sec = seconds; ts.tv_nsec = 0; CHECK(&_sys___nanosleep50); int res = _sys___nanosleep50(&ts, &ts); diff --git a/lib/sanitizer_common/sanitizer_platform.h b/lib/sanitizer_common/sanitizer_platform.h index fd7228c3b..82bb1af77 100644 --- a/lib/sanitizer_common/sanitizer_platform.h +++ b/lib/sanitizer_common/sanitizer_platform.h @@ -275,12 +275,6 @@ # define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12) #endif -// Assume obsolete RPC headers are available by default -#if !defined(HAVE_RPC_XDR_H) && !defined(HAVE_TIRPC_RPC_XDR_H) -# define HAVE_RPC_XDR_H (SANITIZER_LINUX && !SANITIZER_ANDROID) -# define HAVE_TIRPC_RPC_XDR_H 0 -#endif - /// \macro MSC_PREREQ /// \brief Is the compiler MSVC of at least the specified version? /// The common \param version values to check for are: diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index aedcc7c5f..4d146651b 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -387,7 +387,7 @@ #define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \ (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP \ - (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) + (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_TLS_GET_ADDR \ (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) @@ -522,15 +522,16 @@ #define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC) #define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD #define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD -#define SANITIZER_INTERCEPT_REGEX SI_NETBSD -#define SANITIZER_INTERCEPT_FTS SI_NETBSD +#define SANITIZER_INTERCEPT_REGEX (SI_NETBSD || SI_FREEBSD || SI_LINUX) +#define SANITIZER_INTERCEPT_REGEXSUB SI_NETBSD +#define SANITIZER_INTERCEPT_FTS (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_SYSCTL (SI_NETBSD || SI_FREEBSD || SI_MAC) #define SANITIZER_INTERCEPT_ASYSCTL SI_NETBSD #define SANITIZER_INTERCEPT_SYSCTLGETMIBINFO SI_NETBSD #define SANITIZER_INTERCEPT_NL_LANGINFO (SI_NETBSD || SI_FREEBSD || SI_MAC) #define SANITIZER_INTERCEPT_MODCTL SI_NETBSD #define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD -#define SANITIZER_INTERCEPT_STRTONUM SI_NETBSD +#define SANITIZER_INTERCEPT_STRTONUM (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_FPARSELN SI_NETBSD #define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD #define SANITIZER_INTERCEPT_STRTOI SI_NETBSD @@ -543,6 +544,16 @@ #define SANITIZER_INTERCEPT_MD2 SI_NETBSD #define SANITIZER_INTERCEPT_SHA2 SI_NETBSD #define SANITIZER_INTERCEPT_CDB SI_NETBSD -#define SANITIZER_INTERCEPT_VIS SI_NETBSD +#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD) +#define SANITIZER_INTERCEPT_POPEN SI_POSIX +#define SANITIZER_INTERCEPT_POPENVE SI_NETBSD +#define SANITIZER_INTERCEPT_PCLOSE SI_POSIX +#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD) +#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD +#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC) +#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD) +#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD +#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_POSIX) +#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD) #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cc b/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cc index cebb216ec..377a62cab 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cc @@ -18,6 +18,8 @@ #include <arpa/inet.h> #include <dirent.h> +#include <fts.h> +#include <fstab.h> #include <grp.h> #include <limits.h> #include <net/if.h> @@ -25,6 +27,7 @@ #include <poll.h> #include <pthread.h> #include <pwd.h> +#include <regex.h> #include <signal.h> #include <stddef.h> #include <sys/mman.h> @@ -62,9 +65,11 @@ #include <net/ppp_defs.h> #include <glob.h> #include <stdio.h> +#include <stringlist.h> #include <term.h> #include <utmpx.h> #include <wchar.h> +#include <vis.h> #define _KERNEL // to declare 'shminfo' structure # include <sys/shm.h> @@ -124,6 +129,12 @@ namespace __sanitizer { unsigned struct_statvfs_sz = sizeof(struct statvfs); unsigned struct_shminfo_sz = sizeof(struct shminfo); unsigned struct_shm_info_sz = sizeof(struct shm_info); + unsigned struct_regmatch_sz = sizeof(regmatch_t); + unsigned struct_regex_sz = sizeof(regex_t); + unsigned struct_fstab_sz = sizeof(struct fstab); + unsigned struct_FTS_sz = sizeof(FTS); + unsigned struct_FTSENT_sz = sizeof(FTSENT); + unsigned struct_StringList_sz = sizeof(StringList); const uptr sig_ign = (uptr)SIG_IGN; const uptr sig_dfl = (uptr)SIG_DFL; @@ -338,6 +349,8 @@ namespace __sanitizer { const int si_SEGV_MAPERR = SEGV_MAPERR; const int si_SEGV_ACCERR = SEGV_ACCERR; + const int unvis_valid = UNVIS_VALID; + const int unvis_validpush = UNVIS_VALIDPUSH; } // namespace __sanitizer using namespace __sanitizer; @@ -494,7 +507,7 @@ CHECK_SIZE_AND_OFFSET(group, gr_passwd); CHECK_SIZE_AND_OFFSET(group, gr_gid); CHECK_SIZE_AND_OFFSET(group, gr_mem); -#if HAVE_RPC_XDR_H || HAVE_TIRPC_RPC_XDR_H +#if HAVE_RPC_XDR_H CHECK_TYPE_SIZE(XDR); CHECK_SIZE_AND_OFFSET(XDR, x_op); CHECK_SIZE_AND_OFFSET(XDR, x_ops); diff --git a/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h index 90329acb3..588bead2a 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h @@ -62,6 +62,12 @@ namespace __sanitizer { extern unsigned struct_rlimit_sz; extern unsigned struct_utimbuf_sz; extern unsigned struct_timespec_sz; + extern unsigned struct_regmatch_sz; + extern unsigned struct_regex_sz; + extern unsigned struct_FTS_sz; + extern unsigned struct_FTSENT_sz; + extern const int unvis_valid; + extern const int unvis_validpush; struct __sanitizer_iocb { u64 aio_data; @@ -622,6 +628,9 @@ namespace __sanitizer { typedef struct __sanitizer_cap_rights __sanitizer_cap_rights_t; extern unsigned struct_cap_rights_sz; + + extern unsigned struct_fstab_sz; + extern unsigned struct_StringList_sz; } // namespace __sanitizer #define CHECK_TYPE_SIZE(TYPE) \ diff --git a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc index 6633a36b4..b23b430d9 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -125,6 +125,7 @@ #include <dev/isa/satlinkio.h> #include <dev/isa/wtreg.h> #include <dev/iscsi/iscsi_ioctl.h> +#include <dev/nvmm/nvmm_ioctl.h> #include <dev/ofw/openfirmio.h> #include <dev/pci/amrio.h> #include <dev/pci/mlyreg.h> @@ -218,6 +219,8 @@ #include <ttyent.h> #include <fts.h> #include <regex.h> +#include <fstab.h> +#include <stringlist.h> // clang-format on // Include these after system headers to avoid name clashes and ambiguities. @@ -257,6 +260,7 @@ unsigned struct_FTS_sz = sizeof(FTS); unsigned struct_FTSENT_sz = sizeof(FTSENT); unsigned struct_regex_sz = sizeof(regex_t); unsigned struct_regmatch_sz = sizeof(regmatch_t); +unsigned struct_fstab_sz = sizeof(struct fstab); unsigned struct_utimbuf_sz = sizeof(struct utimbuf); unsigned struct_itimerspec_sz = sizeof(struct itimerspec); unsigned struct_timex_sz = sizeof(struct timex); @@ -828,6 +832,7 @@ unsigned struct_RF_ComponentLabel_sz = sizeof(RF_ComponentLabel_t); unsigned struct_RF_SingleComponent_sz = sizeof(RF_SingleComponent_t); unsigned struct_RF_ProgressInfo_sz = sizeof(RF_ProgressInfo_t); unsigned struct_nvlist_ref_sz = sizeof(struct __sanitizer_nvlist_ref_t); +unsigned struct_StringList_sz = sizeof(StringList); const unsigned IOCTL_NOT_PRESENT = 0; @@ -1422,6 +1427,22 @@ unsigned IOCTL_SPKRTONE = SPKRTONE; unsigned IOCTL_SPKRTUNE = SPKRTUNE; unsigned IOCTL_SPKRGETVOL = SPKRGETVOL; unsigned IOCTL_SPKRSETVOL = SPKRSETVOL; +#if 0 /* interfaces are WIP */ +unsigned IOCTL_NVMM_IOC_CAPABILITY = NVMM_IOC_CAPABILITY; +unsigned IOCTL_NVMM_IOC_MACHINE_CREATE = NVMM_IOC_MACHINE_CREATE; +unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY = NVMM_IOC_MACHINE_DESTROY; +unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE = NVMM_IOC_MACHINE_CONFIGURE; +unsigned IOCTL_NVMM_IOC_VCPU_CREATE = NVMM_IOC_VCPU_CREATE; +unsigned IOCTL_NVMM_IOC_VCPU_DESTROY = NVMM_IOC_VCPU_DESTROY; +unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE = NVMM_IOC_VCPU_SETSTATE; +unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE = NVMM_IOC_VCPU_GETSTATE; +unsigned IOCTL_NVMM_IOC_VCPU_INJECT = NVMM_IOC_VCPU_INJECT; +unsigned IOCTL_NVMM_IOC_VCPU_RUN = NVMM_IOC_VCPU_RUN; +unsigned IOCTL_NVMM_IOC_GPA_MAP = NVMM_IOC_GPA_MAP; +unsigned IOCTL_NVMM_IOC_GPA_UNMAP = NVMM_IOC_GPA_UNMAP; +unsigned IOCTL_NVMM_IOC_HVA_MAP = NVMM_IOC_HVA_MAP; +unsigned IOCTL_NVMM_IOC_HVA_UNMAP = NVMM_IOC_HVA_UNMAP; +#endif unsigned IOCTL_AUTOFSREQUEST = AUTOFSREQUEST; unsigned IOCTL_AUTOFSDONE = AUTOFSDONE; unsigned IOCTL_BIOCGBLEN = BIOCGBLEN; @@ -1927,6 +1948,7 @@ unsigned IOCTL_SIOCGLINKSTR = SIOCGLINKSTR; unsigned IOCTL_SIOCSLINKSTR = SIOCSLINKSTR; unsigned IOCTL_SIOCGETHERCAP = SIOCGETHERCAP; unsigned IOCTL_SIOCGIFINDEX = SIOCGIFINDEX; +unsigned IOCTL_SIOCSETHERCAP = SIOCSETHERCAP; unsigned IOCTL_SIOCGUMBINFO = SIOCGUMBINFO; unsigned IOCTL_SIOCSUMBPARAM = SIOCSUMBPARAM; unsigned IOCTL_SIOCGUMBPARAM = SIOCGUMBPARAM; @@ -2224,6 +2246,29 @@ CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc); CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv); CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs); +COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE)); +CHECK_SIZE_AND_OFFSET(FILE, _p); +CHECK_SIZE_AND_OFFSET(FILE, _r); +CHECK_SIZE_AND_OFFSET(FILE, _w); +CHECK_SIZE_AND_OFFSET(FILE, _flags); +CHECK_SIZE_AND_OFFSET(FILE, _file); +CHECK_SIZE_AND_OFFSET(FILE, _bf); +CHECK_SIZE_AND_OFFSET(FILE, _lbfsize); +CHECK_SIZE_AND_OFFSET(FILE, _cookie); +CHECK_SIZE_AND_OFFSET(FILE, _close); +CHECK_SIZE_AND_OFFSET(FILE, _read); +CHECK_SIZE_AND_OFFSET(FILE, _seek); +CHECK_SIZE_AND_OFFSET(FILE, _write); +CHECK_SIZE_AND_OFFSET(FILE, _ext); +CHECK_SIZE_AND_OFFSET(FILE, _up); +CHECK_SIZE_AND_OFFSET(FILE, _ur); +CHECK_SIZE_AND_OFFSET(FILE, _ubuf); +CHECK_SIZE_AND_OFFSET(FILE, _nbuf); +CHECK_SIZE_AND_OFFSET(FILE, _flush); +CHECK_SIZE_AND_OFFSET(FILE, _lb_unused); +CHECK_SIZE_AND_OFFSET(FILE, _blksize); +CHECK_SIZE_AND_OFFSET(FILE, _offset); + CHECK_TYPE_SIZE(tm); CHECK_SIZE_AND_OFFSET(tm, tm_sec); CHECK_SIZE_AND_OFFSET(tm, tm_min); diff --git a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h index 39581361d..0c0c8a837 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -66,6 +66,8 @@ extern unsigned struct_FTSENT_sz; extern unsigned struct_regex_sz; extern unsigned struct_regmatch_sz; +extern unsigned struct_fstab_sz; + struct __sanitizer_regmatch { OFF_T rm_so; OFF_T rm_eo; @@ -446,8 +448,36 @@ struct __sanitizer_wordexp_t { uptr we_nbytes; }; -typedef char __sanitizer_FILE; -#define SANITIZER_HAS_STRUCT_FILE 0 +struct __sanitizer_FILE { + unsigned char *_p; + int _r; + int _w; + unsigned short _flags; + short _file; + struct { + unsigned char *_base; + int _size; + } _bf; + int _lbfsize; + void *_cookie; + int (*_close)(void *ptr); + u64 (*_read)(void *, void *, uptr); + u64 (*_seek)(void *, u64, int); + uptr (*_write)(void *, const void *, uptr); + struct { + unsigned char *_base; + int _size; + } _ext; + unsigned char *_up; + int _ur; + unsigned char _ubuf[3]; + unsigned char _nbuf[1]; + int (*_flush)(void *ptr); + char _lb_unused[sizeof(uptr)]; + int _blksize; + u64 _offset; +}; +#define SANITIZER_HAS_STRUCT_FILE 1 extern int shmctl_ipc_stat; @@ -959,6 +989,7 @@ extern unsigned struct_RF_ComponentLabel_sz; extern unsigned struct_RF_SingleComponent_sz; extern unsigned struct_RF_ProgressInfo_sz; extern unsigned struct_nvlist_ref_sz; +extern unsigned struct_StringList_sz; // A special value to mark ioctls that are not present on the target platform, @@ -1549,6 +1580,22 @@ extern unsigned IOCTL_SPKRTONE; extern unsigned IOCTL_SPKRTUNE; extern unsigned IOCTL_SPKRGETVOL; extern unsigned IOCTL_SPKRSETVOL; +#if 0 /* interfaces are WIP */ +extern unsigned IOCTL_NVMM_IOC_CAPABILITY; +extern unsigned IOCTL_NVMM_IOC_MACHINE_CREATE; +extern unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY; +extern unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE; +extern unsigned IOCTL_NVMM_IOC_VCPU_CREATE; +extern unsigned IOCTL_NVMM_IOC_VCPU_DESTROY; +extern unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE; +extern unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE; +extern unsigned IOCTL_NVMM_IOC_VCPU_INJECT; +extern unsigned IOCTL_NVMM_IOC_VCPU_RUN; +extern unsigned IOCTL_NVMM_IOC_GPA_MAP; +extern unsigned IOCTL_NVMM_IOC_GPA_UNMAP; +extern unsigned IOCTL_NVMM_IOC_HVA_MAP; +extern unsigned IOCTL_NVMM_IOC_HVA_UNMAP; +#endif extern unsigned IOCTL_AUTOFSREQUEST; extern unsigned IOCTL_AUTOFSDONE; extern unsigned IOCTL_BIOCGBLEN; @@ -2054,6 +2101,7 @@ extern unsigned IOCTL_SIOCGLINKSTR; extern unsigned IOCTL_SIOCSLINKSTR; extern unsigned IOCTL_SIOCGETHERCAP; extern unsigned IOCTL_SIOCGIFINDEX; +extern unsigned IOCTL_SIOCSETHERCAP; extern unsigned IOCTL_SIOCGUMBINFO; extern unsigned IOCTL_SIOCSUMBPARAM; extern unsigned IOCTL_SIOCGUMBPARAM; diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index a383ebf9f..ecc69bcea 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -45,6 +45,7 @@ #include <termios.h> #include <time.h> #include <wchar.h> +#include <regex.h> #if !SANITIZER_MAC #include <utmp.h> #endif @@ -54,6 +55,7 @@ #endif #if !SANITIZER_ANDROID +#include <fstab.h> #include <sys/mount.h> #include <sys/timeb.h> #include <utmpx.h> @@ -114,8 +116,6 @@ typedef struct user_fpregs elf_fpregset_t; #include <netrom/netrom.h> #if HAVE_RPC_XDR_H # include <rpc/xdr.h> -#elif HAVE_TIRPC_RPC_XDR_H -# include <tirpc/rpc/xdr.h> #endif #include <scsi/scsi.h> #include <sys/mtio.h> @@ -189,13 +189,15 @@ namespace __sanitizer { unsigned struct_tms_sz = sizeof(struct tms); unsigned struct_sigevent_sz = sizeof(struct sigevent); unsigned struct_sched_param_sz = sizeof(struct sched_param); - + unsigned struct_regex_sz = sizeof(regex_t); + unsigned struct_regmatch_sz = sizeof(regmatch_t); #if SANITIZER_MAC && !SANITIZER_IOS unsigned struct_statfs64_sz = sizeof(struct statfs64); #endif // SANITIZER_MAC && !SANITIZER_IOS #if !SANITIZER_ANDROID + unsigned struct_fstab_sz = sizeof(struct fstab); unsigned struct_statfs_sz = sizeof(struct statfs); unsigned struct_sockaddr_sz = sizeof(struct sockaddr); unsigned ucontext_t_sz = sizeof(ucontext_t); @@ -1210,7 +1212,7 @@ CHECK_SIZE_AND_OFFSET(group, gr_passwd); CHECK_SIZE_AND_OFFSET(group, gr_gid); CHECK_SIZE_AND_OFFSET(group, gr_mem); -#if HAVE_RPC_XDR_H || HAVE_TIRPC_RPC_XDR_H +#if HAVE_RPC_XDR_H CHECK_TYPE_SIZE(XDR); CHECK_SIZE_AND_OFFSET(XDR, x_op); CHECK_SIZE_AND_OFFSET(XDR, x_ops); diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index f51644e3c..de69852d3 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -49,8 +49,11 @@ namespace __sanitizer { extern unsigned struct_sigevent_sz; extern unsigned struct_sched_param_sz; extern unsigned struct_statfs64_sz; + extern unsigned struct_regex_sz; + extern unsigned struct_regmatch_sz; #if !SANITIZER_ANDROID + extern unsigned struct_fstab_sz; extern unsigned struct_statfs_sz; extern unsigned struct_sockaddr_sz; extern unsigned ucontext_t_sz; diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index 116270f8d..b965fb0da 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -18,6 +18,7 @@ #include "sanitizer_common.h" #include "sanitizer_file.h" +#include "sanitizer_flags.h" #include "sanitizer_libc.h" #include "sanitizer_posix.h" #include "sanitizer_procmaps.h" @@ -157,6 +158,8 @@ void MprotectMallocZones(void *addr, int prot) {} #endif fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { + if (ShouldMockFailureToOpen(filename)) + return kInvalidFd; int flags; switch (mode) { case RdOnly: flags = O_RDONLY; break; @@ -166,7 +169,7 @@ fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { fd_t res = internal_open(filename, flags, 0660); if (internal_iserror(res, errno_p)) return kInvalidFd; - return res; + return ReserveStandardFds(res); } void CloseFile(fd_t fd) { @@ -230,6 +233,8 @@ static inline bool IntervalsAreSeparate(uptr start1, uptr end1, // memory). bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { MemoryMappingLayout proc_maps(/*cache_enabled*/true); + if (proc_maps.Error()) + return true; // and hope for the best MemoryMappedSegment segment; while (proc_maps.Next(&segment)) { if (segment.start == segment.end) continue; // Empty range. @@ -269,13 +274,8 @@ bool IsAbsolutePath(const char *path) { void ReportFile::Write(const char *buffer, uptr length) { SpinMutexLock l(mu); - static const char *kWriteError = - "ReportFile::Write() can't output requested buffer!\n"; ReopenIfNecessary(); - if (length != internal_write(fd, buffer, length)) { - internal_write(fd, kWriteError, internal_strlen(kWriteError)); - Die(); - } + internal_write(fd, buffer, length); } bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { @@ -323,6 +323,27 @@ const char *SignalContext::Describe() const { return "UNKNOWN SIGNAL"; } +fd_t ReserveStandardFds(fd_t fd) { + CHECK_GE(fd, 0); + if (fd > 2) + return fd; + bool used[3]; + internal_memset(used, 0, sizeof(used)); + while (fd <= 2) { + used[fd] = true; + fd = internal_dup(fd); + } + for (int i = 0; i <= 2; ++i) + if (used[i]) + internal_close(i); + return fd; +} + +bool ShouldMockFailureToOpen(const char *path) { + return common_flags()->test_only_emulate_no_memorymap && + internal_strncmp(path, "/proc/", 6) == 0; +} + } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/sanitizer_common/sanitizer_posix.h b/lib/sanitizer_common/sanitizer_posix.h index 2ebfae8ba..04a76445e 100644 --- a/lib/sanitizer_common/sanitizer_posix.h +++ b/lib/sanitizer_common/sanitizer_posix.h @@ -49,6 +49,7 @@ uptr internal_filesize(fd_t fd); // -1 on error. uptr internal_stat(const char *path, void *buf); uptr internal_lstat(const char *path, void *buf); uptr internal_fstat(fd_t fd, void *buf); +uptr internal_dup(int oldfd); uptr internal_dup2(int oldfd, int newfd); uptr internal_readlink(const char *path, char *buf, uptr bufsize); uptr internal_unlink(const char *path); @@ -99,6 +100,11 @@ uptr internal_execve(const char *filename, char *const argv[], bool IsStateDetached(int state); +// Move the fd out of {0, 1, 2} range. +fd_t ReserveStandardFds(fd_t fd); + +bool ShouldMockFailureToOpen(const char *path); + } // namespace __sanitizer #endif // SANITIZER_POSIX_H diff --git a/lib/sanitizer_common/sanitizer_procmaps.h b/lib/sanitizer_common/sanitizer_procmaps.h index 9fde040a1..acb7104f3 100644 --- a/lib/sanitizer_common/sanitizer_procmaps.h +++ b/lib/sanitizer_common/sanitizer_procmaps.h @@ -70,6 +70,7 @@ class MemoryMappingLayout { explicit MemoryMappingLayout(bool cache_enabled); ~MemoryMappingLayout(); bool Next(MemoryMappedSegment *segment); + bool Error() const; void Reset(); // In some cases, e.g. when running under a sandbox on Linux, ASan is unable // to obtain the memory mappings. It should fall back to pre-cached data diff --git a/lib/sanitizer_common/sanitizer_procmaps_bsd.cc b/lib/sanitizer_common/sanitizer_procmaps_bsd.cc index 4cebd9858..362a424d7 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_bsd.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_bsd.cc @@ -99,6 +99,7 @@ void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { } bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { + CHECK(!Error()); // can not fail char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; if (data_.current >= last) return false; diff --git a/lib/sanitizer_common/sanitizer_procmaps_common.cc b/lib/sanitizer_common/sanitizer_procmaps_common.cc index 1f2b431c7..17d61b6c5 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_common.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_common.cc @@ -80,12 +80,14 @@ MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { ReadProcMaps(&data_.proc_self_maps); if (cache_enabled && data_.proc_self_maps.mmaped_size == 0) LoadFromCache(); - CHECK_GT(data_.proc_self_maps.mmaped_size, 0); - CHECK_GT(data_.proc_self_maps.len, 0); Reset(); } +bool MemoryMappingLayout::Error() const { + return data_.current == nullptr; +} + MemoryMappingLayout::~MemoryMappingLayout() { // Only unmap the buffer if it is different from the cached one. Otherwise // it will be unmapped when the cache is refreshed. diff --git a/lib/sanitizer_common/sanitizer_procmaps_linux.cc b/lib/sanitizer_common/sanitizer_procmaps_linux.cc index 633e9393c..cf9cb25ba 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_linux.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_linux.cc @@ -31,6 +31,7 @@ static bool IsOneOf(char c, char c1, char c2) { } bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { + if (Error()) return false; // simulate empty maps char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; if (data_.current >= last) return false; char *next_line = diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc index d90e4b993..267c960b5 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -88,6 +88,10 @@ MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) { MemoryMappingLayout::~MemoryMappingLayout() { } +bool MemoryMappingLayout::Error() const { + return false; +} + // More information about Mach-O headers can be found in mach-o/loader.h // Each Mach-O image has a header (mach_header or mach_header_64) starting with // a magic number, and a list of linker load commands directly following the diff --git a/lib/sanitizer_common/sanitizer_procmaps_solaris.cc b/lib/sanitizer_common/sanitizer_procmaps_solaris.cc index 9e5e37e6b..49bb46c31 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_solaris.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_solaris.cc @@ -21,11 +21,16 @@ namespace __sanitizer { void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { - ReadFileToBuffer("/proc/self/xmap", &proc_maps->data, &proc_maps->mmaped_size, - &proc_maps->len); + if (!ReadFileToBuffer("/proc/self/xmap", &proc_maps->data, + &proc_maps->mmaped_size, &proc_maps->len)) { + proc_maps->data = nullptr; + proc_maps->mmaped_size = 0; + proc_maps->len = 0; + } } bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { + if (Error()) return false; // simulate empty maps char *last = data_.proc_self_maps.data + data_.proc_self_maps.len; if (data_.current >= last) return false; diff --git a/lib/sanitizer_common/sanitizer_rtems.cc b/lib/sanitizer_common/sanitizer_rtems.cc index 678906a18..76aebe419 100644 --- a/lib/sanitizer_common/sanitizer_rtems.cc +++ b/lib/sanitizer_common/sanitizer_rtems.cc @@ -98,6 +98,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, void InitializePlatformEarly() {} void MaybeReexec() {} void CheckASLR() {} +void CheckMPROTECT() {} void DisableCoreDumperIfNecessary() {} void InstallDeadlySignalHandlers(SignalHandlerType handler) {} void SetAlternateSignalStack() {} diff --git a/lib/sanitizer_common/sanitizer_solaris.cc b/lib/sanitizer_common/sanitizer_solaris.cc index 9d0c3d93d..cc0201c7a 100644 --- a/lib/sanitizer_common/sanitizer_solaris.cc +++ b/lib/sanitizer_common/sanitizer_solaris.cc @@ -88,8 +88,8 @@ uptr internal_open(const char *filename, int flags, u32 mode) { } uptr OpenFile(const char *filename, bool write) { - return internal_open(filename, - write ? O_WRONLY | O_CREAT : O_RDONLY, 0660); + return ReserveStandardFds( + internal_open(filename, write ? O_WRONLY | O_CREAT : O_RDONLY, 0660)); } DECLARE__REAL_AND_INTERNAL(uptr, read, fd_t fd, void *buf, uptr count) { diff --git a/lib/sanitizer_common/sanitizer_stackdepot.cc b/lib/sanitizer_common/sanitizer_stackdepot.cc index 3bd5b677a..6aab98485 100644 --- a/lib/sanitizer_common/sanitizer_stackdepot.cc +++ b/lib/sanitizer_common/sanitizer_stackdepot.cc @@ -26,7 +26,7 @@ struct StackDepotNode { u32 tag; uptr stack[1]; // [size] - static const u32 kTabSizeLog = 20; + static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20; // Lower kTabSizeLog bits are equal for all items in one bucket. // We use these bits to store the per-stack use counter. static const u32 kUseCountBits = kTabSizeLog; diff --git a/lib/sanitizer_common/sanitizer_stackdepot.h b/lib/sanitizer_common/sanitizer_stackdepot.h index cb7345002..e22ed2e38 100644 --- a/lib/sanitizer_common/sanitizer_stackdepot.h +++ b/lib/sanitizer_common/sanitizer_stackdepot.h @@ -32,7 +32,7 @@ struct StackDepotHandle { void inc_use_count_unsafe(); }; -const int kStackDepotMaxUseCount = 1U << 20; +const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20); StackDepotStats *StackDepotGetStats(); u32 StackDepotPut(StackTrace stack); diff --git a/lib/sanitizer_common/sanitizer_type_traits.cc b/lib/sanitizer_common/sanitizer_type_traits.cc new file mode 100644 index 000000000..27fec6e1f --- /dev/null +++ b/lib/sanitizer_common/sanitizer_type_traits.cc @@ -0,0 +1,21 @@ +//===-- sanitizer_type_traits.cc --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements a subset of C++ type traits. This is so we can avoid depending +// on system C++ headers. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_type_traits.h" + +namespace __sanitizer { + +const bool true_type::value; +const bool false_type::value; + +} // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_type_traits.h b/lib/sanitizer_common/sanitizer_type_traits.h index 572eaa5a0..4495f2c34 100644 --- a/lib/sanitizer_common/sanitizer_type_traits.h +++ b/lib/sanitizer_common/sanitizer_type_traits.h @@ -39,6 +39,6 @@ struct is_same : public false_type {}; template <typename T> struct is_same<T, T> : public true_type {}; -}; // namespace __sanitizer +} // namespace __sanitizer #endif diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index d3b7df690..9a574dd23 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -1016,6 +1016,10 @@ void CheckASLR() { // Do nothing } +void CheckMPROTECT() { + // Do nothing +} + char **GetArgv() { // FIXME: Actually implement this function. return 0; diff --git a/lib/sanitizer_common/scripts/gen_dynamic_list.py b/lib/sanitizer_common/scripts/gen_dynamic_list.py index 25632ed77..4a9c7af95 100755 --- a/lib/sanitizer_common/scripts/gen_dynamic_list.py +++ b/lib/sanitizer_common/scripts/gen_dynamic_list.py @@ -14,6 +14,7 @@ # gen_dynamic_list.py libclang_rt.*san*.a [ files ... ] # #===------------------------------------------------------------------------===# +from __future__ import print_function import argparse import os import re @@ -84,6 +85,7 @@ def main(argv): parser.add_argument('--version-list', action='store_true') parser.add_argument('--extra', default=[], action='append') parser.add_argument('libraries', default=[], nargs='+') + parser.add_argument('-o', '--output', required=True) args = parser.parse_args() result = [] @@ -117,16 +119,17 @@ def main(argv): for line in f: result.append(line.rstrip()) # Print the resulting list in the format recognized by ld. - print('{') - if args.version_list: - print('global:') - result.sort() - for f in result: - print(u' %s;' % f) - if args.version_list: - print('local:') - print(' *;') - print('};') + with open(args.output, 'w') as f: + print('{', file=f) + if args.version_list: + print('global:', file=f) + result.sort() + for sym in result: + print(u' %s;' % sym, file=f) + if args.version_list: + print('local:', file=f) + print(' *;', file=f) + print('};', file=f) if __name__ == '__main__': main(sys.argv) diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index f12b70e7b..3123a1d5a 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -53,6 +53,7 @@ static const u64 kAddressSpaceSize = 1ULL << 47; typedef DefaultSizeClassMap SizeClassMap; #endif +template <typename AddressSpaceViewTy> struct AP64 { // Allocator Params. Short name for shorter demangled names.. static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -60,8 +61,10 @@ struct AP64 { // Allocator Params. Short name for shorter demangled names.. typedef ::SizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; +template <typename AddressSpaceViewTy> struct AP64Dyn { static const uptr kSpaceBeg = ~(uptr)0; static const uptr kSpaceSize = kAllocatorSize; @@ -69,8 +72,10 @@ struct AP64Dyn { typedef ::SizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; +template <typename AddressSpaceViewTy> struct AP64Compact { static const uptr kSpaceBeg = ~(uptr)0; static const uptr kSpaceSize = kAllocatorSize; @@ -78,8 +83,10 @@ struct AP64Compact { typedef CompactSizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; +template <typename AddressSpaceViewTy> struct AP64VeryCompact { static const uptr kSpaceBeg = ~(uptr)0; static const uptr kSpaceSize = 1ULL << 37; @@ -87,8 +94,10 @@ struct AP64VeryCompact { typedef VeryCompactSizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; +template <typename AddressSpaceViewTy> struct AP64Dense { static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -96,13 +105,32 @@ struct AP64Dense { typedef DenseSizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; -typedef SizeClassAllocator64<AP64> Allocator64; -typedef SizeClassAllocator64<AP64Dyn> Allocator64Dynamic; -typedef SizeClassAllocator64<AP64Compact> Allocator64Compact; -typedef SizeClassAllocator64<AP64VeryCompact> Allocator64VeryCompact; -typedef SizeClassAllocator64<AP64Dense> Allocator64Dense; +template <typename AddressSpaceView> +using Allocator64ASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; +using Allocator64 = Allocator64ASVT<LocalAddressSpaceView>; + +template <typename AddressSpaceView> +using Allocator64DynamicASVT = SizeClassAllocator64<AP64Dyn<AddressSpaceView>>; +using Allocator64Dynamic = Allocator64DynamicASVT<LocalAddressSpaceView>; + +template <typename AddressSpaceView> +using Allocator64CompactASVT = + SizeClassAllocator64<AP64Compact<AddressSpaceView>>; +using Allocator64Compact = Allocator64CompactASVT<LocalAddressSpaceView>; + +template <typename AddressSpaceView> +using Allocator64VeryCompactASVT = + SizeClassAllocator64<AP64VeryCompact<AddressSpaceView>>; +using Allocator64VeryCompact = + Allocator64VeryCompactASVT<LocalAddressSpaceView>; + +template <typename AddressSpaceView> +using Allocator64DenseASVT = SizeClassAllocator64<AP64Dense<AddressSpaceView>>; +using Allocator64Dense = Allocator64DenseASVT<LocalAddressSpaceView>; + #elif defined(__mips64) static const u64 kAddressSpaceSize = 1ULL << 40; #elif defined(__aarch64__) @@ -404,6 +432,7 @@ int TestMapUnmapCallback::unmap_count; // to run them all at the same time. FIXME: Make them not flaky and reenable. #if !SANITIZER_WINDOWS +template <typename AddressSpaceViewTy = LocalAddressSpaceView> struct AP64WithCallback { static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -411,12 +440,13 @@ struct AP64WithCallback { typedef ::SizeClassMap SizeClassMap; typedef TestMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) { TestMapUnmapCallback::map_count = 0; TestMapUnmapCallback::unmap_count = 0; - typedef SizeClassAllocator64<AP64WithCallback> Allocator64WithCallBack; + typedef SizeClassAllocator64<AP64WithCallback<>> Allocator64WithCallBack; Allocator64WithCallBack *a = new Allocator64WithCallBack; a->Init(kReleaseToOSIntervalNever); EXPECT_EQ(TestMapUnmapCallback::map_count, 1); // Allocator state. @@ -1003,6 +1033,7 @@ TEST(SanitizerCommon, LargeMmapAllocatorBlockBegin) { // machine to OOM. #if SANITIZER_CAN_USE_ALLOCATOR64 && !SANITIZER_WINDOWS64 && !SANITIZER_ANDROID typedef SizeClassMap<3, 4, 8, 63, 128, 16> SpecialSizeClassMap; +template <typename AddressSpaceViewTy = LocalAddressSpaceView> struct AP64_SpecialSizeClassMap { static const uptr kSpaceBeg = kAllocatorSpace; static const uptr kSpaceSize = kAllocatorSize; @@ -1010,12 +1041,13 @@ struct AP64_SpecialSizeClassMap { typedef SpecialSizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = AddressSpaceViewTy; }; // Regression test for out-of-memory condition in PopulateFreeList(). TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) { // In a world where regions are small and chunks are huge... - typedef SizeClassAllocator64<AP64_SpecialSizeClassMap> SpecialAllocator64; + typedef SizeClassAllocator64<AP64_SpecialSizeClassMap<>> SpecialAllocator64; const uptr kRegionSize = kAllocatorSize / SpecialSizeClassMap::kNumClassesRounded; SpecialAllocator64 *a = new SpecialAllocator64; diff --git a/lib/scudo/scudo_allocator.h b/lib/scudo/scudo_allocator.h index 869e74a5e..814bb08ab 100644 --- a/lib/scudo/scudo_allocator.h +++ b/lib/scudo/scudo_allocator.h @@ -81,6 +81,7 @@ struct AP64 { typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = SizeClassAllocator64FlagMasks::kRandomShuffleChunks; + using AddressSpaceView = LocalAddressSpaceView; }; typedef SizeClassAllocator64<AP64> PrimaryT; #else diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index d501d0cba..e1da319cc 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -220,11 +220,12 @@ else() endif() # Make sure that non-platform-specific files don't include any system headers. -# FreeBSD does not install a number of Clang-provided headers for the compiler -# in the base system due to incompatibilities between FreeBSD's and Clang's -# versions. As a workaround do not use --sysroot=. on FreeBSD until this is -# addressed. -if(COMPILER_RT_HAS_SYSROOT_FLAG AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") +# FreeBSD/NetBSD do not install a number of Clang-provided headers for the +# compiler in the base system due to incompatibilities between FreeBSD/NetBSD's +# and Clang's versions. As a workaround do not use --sysroot=. on FreeBSD/NetBSD +# until this is addressed. +if(COMPILER_RT_HAS_SYSROOT_FLAG AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD" + AND NOT CMAKE_SYSTEM_NAME MATCHES "NetBSD") file(GLOB _tsan_generic_sources rtl/tsan*) file(GLOB _tsan_platform_sources rtl/tsan*posix* rtl/tsan*mac* rtl/tsan*linux*) diff --git a/lib/tsan/rtl/tsan_debugging.cc b/lib/tsan/rtl/tsan_debugging.cc index 9e5465d37..067aeef97 100644 --- a/lib/tsan/rtl/tsan_debugging.cc +++ b/lib/tsan/rtl/tsan_debugging.cc @@ -20,31 +20,37 @@ using namespace __tsan; static const char *ReportTypeDescription(ReportType typ) { - if (typ == ReportTypeRace) return "data-race"; - if (typ == ReportTypeVptrRace) return "data-race-vptr"; - if (typ == ReportTypeUseAfterFree) return "heap-use-after-free"; - if (typ == ReportTypeVptrUseAfterFree) return "heap-use-after-free-vptr"; - if (typ == ReportTypeExternalRace) return "external-race"; - if (typ == ReportTypeThreadLeak) return "thread-leak"; - if (typ == ReportTypeMutexDestroyLocked) return "locked-mutex-destroy"; - if (typ == ReportTypeMutexDoubleLock) return "mutex-double-lock"; - if (typ == ReportTypeMutexInvalidAccess) return "mutex-invalid-access"; - if (typ == ReportTypeMutexBadUnlock) return "mutex-bad-unlock"; - if (typ == ReportTypeMutexBadReadLock) return "mutex-bad-read-lock"; - if (typ == ReportTypeMutexBadReadUnlock) return "mutex-bad-read-unlock"; - if (typ == ReportTypeSignalUnsafe) return "signal-unsafe-call"; - if (typ == ReportTypeErrnoInSignal) return "errno-in-signal-handler"; - if (typ == ReportTypeDeadlock) return "lock-order-inversion"; - return ""; + switch (typ) { + case ReportTypeRace: return "data-race"; + case ReportTypeVptrRace: return "data-race-vptr"; + case ReportTypeUseAfterFree: return "heap-use-after-free"; + case ReportTypeVptrUseAfterFree: return "heap-use-after-free-vptr"; + case ReportTypeExternalRace: return "external-race"; + case ReportTypeThreadLeak: return "thread-leak"; + case ReportTypeMutexDestroyLocked: return "locked-mutex-destroy"; + case ReportTypeMutexDoubleLock: return "mutex-double-lock"; + case ReportTypeMutexInvalidAccess: return "mutex-invalid-access"; + case ReportTypeMutexBadUnlock: return "mutex-bad-unlock"; + case ReportTypeMutexBadReadLock: return "mutex-bad-read-lock"; + case ReportTypeMutexBadReadUnlock: return "mutex-bad-read-unlock"; + case ReportTypeSignalUnsafe: return "signal-unsafe-call"; + case ReportTypeErrnoInSignal: return "errno-in-signal-handler"; + case ReportTypeDeadlock: return "lock-order-inversion"; + // No default case so compiler warns us if we miss one + } + UNREACHABLE("missing case"); } static const char *ReportLocationTypeDescription(ReportLocationType typ) { - if (typ == ReportLocationGlobal) return "global"; - if (typ == ReportLocationHeap) return "heap"; - if (typ == ReportLocationStack) return "stack"; - if (typ == ReportLocationTLS) return "tls"; - if (typ == ReportLocationFD) return "fd"; - return ""; + switch (typ) { + case ReportLocationGlobal: return "global"; + case ReportLocationHeap: return "heap"; + case ReportLocationStack: return "stack"; + case ReportLocationTLS: return "tls"; + case ReportLocationFD: return "fd"; + // No default case so compiler warns us if we miss one + } + UNREACHABLE("missing case"); } static void CopyTrace(SymbolizedStack *first_frame, void **trace, diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc index 89e22a132..877fc8b81 100644 --- a/lib/tsan/rtl/tsan_flags.cc +++ b/lib/tsan/rtl/tsan_flags.cc @@ -61,8 +61,7 @@ void InitializeFlags(Flags *f, const char *env) { // Does not work as expected for Go: runtime handles SIGABRT and crashes. cf.abort_on_error = false; // Go does not have mutexes. - } else { - cf.detect_deadlocks = true; + cf.detect_deadlocks = false; } cf.print_suppressions = false; cf.stack_trace_format = " #%n %f %S %M"; diff --git a/lib/tsan/rtl/tsan_flags.inc b/lib/tsan/rtl/tsan_flags.inc index e9b3e35f0..d3b678fdd 100644 --- a/lib/tsan/rtl/tsan_flags.inc +++ b/lib/tsan/rtl/tsan_flags.inc @@ -77,8 +77,6 @@ TSAN_FLAG(int, io_sync, 1, TSAN_FLAG(bool, die_after_fork, true, "Die after multi-threaded fork if the child creates new threads.") TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") -TSAN_FLAG(bool, ignore_interceptors_accesses, false, - "Ignore reads and writes from all interceptors.") TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_MAC ? true : false, "Interceptors should only detect races when called from instrumented " "modules.") diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index cc6dab8f1..9e49dfe5d 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -42,16 +42,12 @@ using namespace __tsan; // NOLINT #if SANITIZER_NETBSD #define dirfd(dirp) (*(int *)(dirp)) -#define fileno_unlocked fileno +#define fileno_unlocked(fp) \ + (((__sanitizer_FILE*)fp)->_file == -1 ? -1 : \ + (int)(unsigned short)(((__sanitizer_FILE*)fp)->_file)) // NOLINT -#if _LP64 -#define __sF_size 152 -#else -#define __sF_size 88 -#endif - -#define stdout ((char*)&__sF + (__sF_size * 1)) -#define stderr ((char*)&__sF + (__sF_size * 2)) +#define stdout ((__sanitizer_FILE*)&__sF[1]) +#define stderr ((__sanitizer_FILE*)&__sF[2]) #define nanosleep __nanosleep50 #define vfork __vfork14 @@ -96,8 +92,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) extern "C" void *pthread_self(); extern "C" void _exit(int status); -extern "C" int fileno_unlocked(void *stream); #if !SANITIZER_NETBSD +extern "C" int fileno_unlocked(void *stream); extern "C" int dirfd(void *dirp); #endif #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_NETBSD @@ -258,8 +254,7 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, if (!thr_->ignore_interceptors) FuncEntry(thr, pc); DPrintf("#%d: intercept %s()\n", thr_->tid, fname); ignoring_ = - !thr_->in_ignored_lib && (flags()->ignore_interceptors_accesses || - libignore()->IsIgnored(pc, &in_ignored_lib_)); + !thr_->in_ignored_lib && libignore()->IsIgnored(pc, &in_ignored_lib_); EnableIgnores(); } @@ -2254,7 +2249,8 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, (void) ctx; #define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \ - Acquire(thr, pc, File2addr(path)); \ + if (path) \ + Acquire(thr, pc, File2addr(path)); \ if (file) { \ int fd = fileno_unlocked(file); \ if (fd >= 0) FdFileCreate(thr, pc, fd); \ diff --git a/lib/tsan/rtl/tsan_interceptors_mac.cc b/lib/tsan/rtl/tsan_interceptors_mac.cc index 5e8b58fc2..579c4d0c0 100644 --- a/lib/tsan/rtl/tsan_interceptors_mac.cc +++ b/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -19,8 +19,10 @@ #include "tsan_interceptors.h" #include "tsan_interface.h" #include "tsan_interface_ann.h" +#include "sanitizer_common/sanitizer_addrhashmap.h" #include <libkern/OSAtomic.h> +#include <objc/objc-sync.h> #if defined(__has_include) && __has_include(<xpc/xpc.h>) #include <xpc/xpc.h> @@ -294,41 +296,62 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) { #endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>) -// Is the Obj-C object a tagged pointer (i.e. isn't really a valid pointer and -// contains data in the pointers bits instead)? -static bool IsTaggedObjCPointer(void *obj) { +// Determines whether the Obj-C object pointer is a tagged pointer. Tagged +// pointers encode the object data directly in their pointer bits and do not +// have an associated memory allocation. The Obj-C runtime uses tagged pointers +// to transparently optimize small objects. +static bool IsTaggedObjCPointer(id obj) { const uptr kPossibleTaggedBits = 0x8000000000000001ull; return ((uptr)obj & kPossibleTaggedBits) != 0; } -// Return an address on which we can synchronize (Acquire and Release) for a -// Obj-C tagged pointer (which is not a valid pointer). Ideally should be a -// derived address from 'obj', but for now just return the same global address. -// TODO(kubamracek): Return different address for different pointers. -static uptr SyncAddressForTaggedPointer(void *obj) { - (void)obj; - static u64 addr; - return (uptr)&addr; +// Returns an address which can be used to inform TSan about synchronization +// points (MutexLock/Unlock). The TSan infrastructure expects this to be a valid +// address in the process space. We do a small allocation here to obtain a +// stable address (the array backing the hash map can change). The memory is +// never free'd (leaked) and allocation and locking are slow, but this code only +// runs for @synchronized with tagged pointers, which is very rare. +static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) { + typedef AddrHashMap<uptr, 5> Map; + static Map Addresses; + Map::Handle h(&Addresses, addr); + if (h.created()) { + ThreadIgnoreBegin(thr, pc); + *h = (uptr) user_alloc(thr, pc, /*size=*/1); + ThreadIgnoreEnd(thr, pc); + } + return *h; } -// Address on which we can synchronize for an Objective-C object. Supports -// tagged pointers. -static uptr SyncAddressForObjCObject(void *obj) { - if (IsTaggedObjCPointer(obj)) return SyncAddressForTaggedPointer(obj); +// Returns an address on which we can synchronize given an Obj-C object pointer. +// For normal object pointers, this is just the address of the object in memory. +// Tagged pointers are not backed by an actual memory allocation, so we need to +// synthesize a valid address. +static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) { + if (IsTaggedObjCPointer(obj)) + return GetOrCreateSyncAddress((uptr)obj, thr, pc); return (uptr)obj; } -TSAN_INTERCEPTOR(int, objc_sync_enter, void *obj) { +TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj); + if (!obj) return REAL(objc_sync_enter)(obj); + uptr addr = SyncAddressForObjCObject(obj, thr, pc); + MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant); int result = REAL(objc_sync_enter)(obj); - if (obj) Acquire(thr, pc, SyncAddressForObjCObject(obj)); + CHECK_EQ(result, OBJC_SYNC_SUCCESS); + MutexPostLock(thr, pc, addr, MutexFlagWriteReentrant); return result; } -TSAN_INTERCEPTOR(int, objc_sync_exit, void *obj) { +TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj); - if (obj) Release(thr, pc, SyncAddressForObjCObject(obj)); - return REAL(objc_sync_exit)(obj); + if (!obj) return REAL(objc_sync_exit)(obj); + uptr addr = SyncAddressForObjCObject(obj, thr, pc); + MutexUnlock(thr, pc, addr); + int result = REAL(objc_sync_exit)(obj); + if (result != OBJC_SYNC_SUCCESS) MutexInvalidAccess(thr, pc, addr); + return result; } // On macOS, libc++ is always linked dynamically, so intercepting works the diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index af4707696..629c3e933 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -77,39 +77,42 @@ const char *thread_name(char *buf, int tid) { } static const char *ReportTypeString(ReportType typ, uptr tag) { - if (typ == ReportTypeRace) - return "data race"; - if (typ == ReportTypeVptrRace) - return "data race on vptr (ctor/dtor vs virtual call)"; - if (typ == ReportTypeUseAfterFree) - return "heap-use-after-free"; - if (typ == ReportTypeVptrUseAfterFree) - return "heap-use-after-free (virtual call vs free)"; - if (typ == ReportTypeExternalRace) { - const char *str = GetReportHeaderFromTag(tag); - return str ? str : "race on external object"; + switch (typ) { + case ReportTypeRace: + return "data race"; + case ReportTypeVptrRace: + return "data race on vptr (ctor/dtor vs virtual call)"; + case ReportTypeUseAfterFree: + return "heap-use-after-free"; + case ReportTypeVptrUseAfterFree: + return "heap-use-after-free (virtual call vs free)"; + case ReportTypeExternalRace: { + const char *str = GetReportHeaderFromTag(tag); + return str ? str : "race on external object"; + } + case ReportTypeThreadLeak: + return "thread leak"; + case ReportTypeMutexDestroyLocked: + return "destroy of a locked mutex"; + case ReportTypeMutexDoubleLock: + return "double lock of a mutex"; + case ReportTypeMutexInvalidAccess: + return "use of an invalid mutex (e.g. uninitialized or destroyed)"; + case ReportTypeMutexBadUnlock: + return "unlock of an unlocked mutex (or by a wrong thread)"; + case ReportTypeMutexBadReadLock: + return "read lock of a write locked mutex"; + case ReportTypeMutexBadReadUnlock: + return "read unlock of a write locked mutex"; + case ReportTypeSignalUnsafe: + return "signal-unsafe call inside of a signal"; + case ReportTypeErrnoInSignal: + return "signal handler spoils errno"; + case ReportTypeDeadlock: + return "lock-order-inversion (potential deadlock)"; + // No default case so compiler warns us if we miss one } - if (typ == ReportTypeThreadLeak) - return "thread leak"; - if (typ == ReportTypeMutexDestroyLocked) - return "destroy of a locked mutex"; - if (typ == ReportTypeMutexDoubleLock) - return "double lock of a mutex"; - if (typ == ReportTypeMutexInvalidAccess) - return "use of an invalid mutex (e.g. uninitialized or destroyed)"; - if (typ == ReportTypeMutexBadUnlock) - return "unlock of an unlocked mutex (or by a wrong thread)"; - if (typ == ReportTypeMutexBadReadLock) - return "read lock of a write locked mutex"; - if (typ == ReportTypeMutexBadReadUnlock) - return "read unlock of a write locked mutex"; - if (typ == ReportTypeSignalUnsafe) - return "signal-unsafe call inside of a signal"; - if (typ == ReportTypeErrnoInSignal) - return "signal handler spoils errno"; - if (typ == ReportTypeDeadlock) - return "lock-order-inversion (potential deadlock)"; - return ""; + UNREACHABLE("missing case"); } #if SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index 60e6f82f7..3410be294 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -81,6 +81,7 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name. typedef DefaultSizeClassMap SizeClassMap; typedef __tsan::MapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; + using AddressSpaceView = LocalAddressSpaceView; }; typedef SizeClassAllocator64<AP64> PrimaryAllocator; #endif diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc index be38f331a..6df074118 100644 --- a/lib/tsan/rtl/tsan_suppressions.cc +++ b/lib/tsan/rtl/tsan_suppressions.cc @@ -66,38 +66,30 @@ SuppressionContext *Suppressions() { } static const char *conv(ReportType typ) { - if (typ == ReportTypeRace) - return kSuppressionRace; - else if (typ == ReportTypeVptrRace) - return kSuppressionRace; - else if (typ == ReportTypeUseAfterFree) - return kSuppressionRace; - else if (typ == ReportTypeVptrUseAfterFree) - return kSuppressionRace; - else if (typ == ReportTypeExternalRace) - return kSuppressionRace; - else if (typ == ReportTypeThreadLeak) - return kSuppressionThread; - else if (typ == ReportTypeMutexDestroyLocked) - return kSuppressionMutex; - else if (typ == ReportTypeMutexDoubleLock) - return kSuppressionMutex; - else if (typ == ReportTypeMutexInvalidAccess) - return kSuppressionMutex; - else if (typ == ReportTypeMutexBadUnlock) - return kSuppressionMutex; - else if (typ == ReportTypeMutexBadReadLock) - return kSuppressionMutex; - else if (typ == ReportTypeMutexBadReadUnlock) - return kSuppressionMutex; - else if (typ == ReportTypeSignalUnsafe) - return kSuppressionSignal; - else if (typ == ReportTypeErrnoInSignal) - return kSuppressionNone; - else if (typ == ReportTypeDeadlock) - return kSuppressionDeadlock; - Printf("ThreadSanitizer: unknown report type %d\n", typ); - Die(); + switch (typ) { + case ReportTypeRace: + case ReportTypeVptrRace: + case ReportTypeUseAfterFree: + case ReportTypeVptrUseAfterFree: + case ReportTypeExternalRace: + return kSuppressionRace; + case ReportTypeThreadLeak: + return kSuppressionThread; + case ReportTypeMutexDestroyLocked: + case ReportTypeMutexDoubleLock: + case ReportTypeMutexInvalidAccess: + case ReportTypeMutexBadUnlock: + case ReportTypeMutexBadReadLock: + case ReportTypeMutexBadReadUnlock: + return kSuppressionMutex; + case ReportTypeSignalUnsafe: + case ReportTypeErrnoInSignal: + return kSuppressionSignal; + case ReportTypeDeadlock: + return kSuppressionDeadlock; + // No default case so compiler warns us if we miss one + } + UNREACHABLE("missing case"); } static uptr IsSuppressed(const char *stype, const AddressInfo &info, diff --git a/lib/ubsan/ubsan_checks.inc b/lib/ubsan/ubsan_checks.inc index e976ea4f6..ea82f89e1 100644 --- a/lib/ubsan/ubsan_checks.inc +++ b/lib/ubsan/ubsan_checks.inc @@ -21,6 +21,7 @@ UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined") UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null") UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow") UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment") +UBSAN_CHECK(AlignmentAssumption, "alignment-assumption", "alignment") UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size") UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow", "signed-integer-overflow") diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 53430a607..11e09b0ff 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -106,6 +106,62 @@ void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data, Die(); } +static void handleAlignmentAssumptionImpl(AlignmentAssumptionData *Data, + ValueHandle Pointer, + ValueHandle Alignment, + ValueHandle Offset, + ReportOptions Opts) { + Location Loc = Data->Loc.acquire(); + SourceLocation AssumptionLoc = Data->AssumptionLoc.acquire(); + + ErrorType ET = ErrorType::AlignmentAssumption; + + if (ignoreReport(Loc.getSourceLocation(), Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); + + uptr RealPointer = Pointer - Offset; + uptr LSB = LeastSignificantSetBitIndex(RealPointer); + uptr ActualAlignment = uptr(1) << LSB; + + uptr Mask = Alignment - 1; + uptr MisAlignmentOffset = RealPointer & Mask; + + if (!Offset) { + Diag(Loc, DL_Error, ET, + "assumption of %0 byte alignment for pointer of type %1 failed") + << Alignment << Data->Type; + } else { + Diag(Loc, DL_Error, ET, + "assumption of %0 byte alignment (with offset of %1 byte) for pointer " + "of type %2 failed") + << Alignment << Offset << Data->Type; + } + + if (!AssumptionLoc.isInvalid()) + Diag(AssumptionLoc, DL_Note, ET, "alignment assumption was specified here"); + + Diag(RealPointer, DL_Note, ET, + "%0address is %1 aligned, misalignment offset is %2 bytes") + << (Offset ? "offset " : "") << ActualAlignment << MisAlignmentOffset; +} + +void __ubsan::__ubsan_handle_alignment_assumption(AlignmentAssumptionData *Data, + ValueHandle Pointer, + ValueHandle Alignment, + ValueHandle Offset) { + GET_REPORT_OPTIONS(false); + handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts); +} +void __ubsan::__ubsan_handle_alignment_assumption_abort( + AlignmentAssumptionData *Data, ValueHandle Pointer, ValueHandle Alignment, + ValueHandle Offset) { + GET_REPORT_OPTIONS(true); + handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts); + Die(); +} + /// \brief Common diagnostic emission for various forms of integer overflow. template <typename T> static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 04405770e..2bf9ff432 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -39,6 +39,17 @@ struct TypeMismatchData { /// type. RECOVERABLE(type_mismatch_v1, TypeMismatchData *Data, ValueHandle Pointer) +struct AlignmentAssumptionData { + SourceLocation Loc; + SourceLocation AssumptionLoc; + const TypeDescriptor &Type; +}; + +/// \brief Handle a runtime alignment assumption check failure, +/// caused by a misaligned pointer. +RECOVERABLE(alignment_assumption, AlignmentAssumptionData *Data, + ValueHandle Pointer, ValueHandle Alignment, ValueHandle Offset) + struct OverflowData { SourceLocation Loc; const TypeDescriptor &Type; diff --git a/lib/ubsan/ubsan_interface.inc b/lib/ubsan/ubsan_interface.inc index 0be6010ad..81e06345d 100644 --- a/lib/ubsan/ubsan_interface.inc +++ b/lib/ubsan/ubsan_interface.inc @@ -10,6 +10,8 @@ //===----------------------------------------------------------------------===// INTERFACE_FUNCTION(__ubsan_handle_add_overflow) INTERFACE_FUNCTION(__ubsan_handle_add_overflow_abort) +INTERFACE_FUNCTION(__ubsan_handle_alignment_assumption) +INTERFACE_FUNCTION(__ubsan_handle_alignment_assumption_abort) INTERFACE_FUNCTION(__ubsan_handle_builtin_unreachable) INTERFACE_FUNCTION(__ubsan_handle_cfi_bad_type) INTERFACE_FUNCTION(__ubsan_handle_cfi_check_fail) diff --git a/lib/ubsan_minimal/ubsan_minimal_handlers.cc b/lib/ubsan_minimal/ubsan_minimal_handlers.cc index e8fc3a849..ed62ddd0f 100644 --- a/lib/ubsan_minimal/ubsan_minimal_handlers.cc +++ b/lib/ubsan_minimal/ubsan_minimal_handlers.cc @@ -95,6 +95,7 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) { HANDLER_NORECOVER(name, msg) HANDLER(type_mismatch, "type-mismatch") +HANDLER(alignment_assumption, "alignment-assumption") HANDLER(add_overflow, "add-overflow") HANDLER(sub_overflow, "sub-overflow") HANDLER(mul_overflow, "mul-overflow") diff --git a/lib/xray/tests/CMakeLists.txt b/lib/xray/tests/CMakeLists.txt index 16fb129d3..89a2b3b01 100644 --- a/lib/xray/tests/CMakeLists.txt +++ b/lib/xray/tests/CMakeLists.txt @@ -60,6 +60,10 @@ if (NOT APPLE) if (COMPILER_RT_STANDALONE_BUILD) append_list_if(COMPILER_RT_HAS_LLVMXRAY ${LLVM_XRAY_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_LLVMXRAY ${LLVM_XRAY_LIBLIST} XRAY_UNITTEST_LINK_FLAGS) + append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT + ${LLVM_TESTINGSUPPORT_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS) + append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT + ${LLVM_TESTINGSUPPORT_LIBLIST} XRAY_UNITTEST_LINK_FLAGS) else() # We add the library directories one at a time in our CFLAGS. foreach (DIR ${LLVM_LIBRARY_DIR}) diff --git a/lib/xray/tests/unit/CMakeLists.txt b/lib/xray/tests/unit/CMakeLists.txt index 42ea43750..d10524b8d 100644 --- a/lib/xray/tests/unit/CMakeLists.txt +++ b/lib/xray/tests/unit/CMakeLists.txt @@ -1,10 +1,16 @@ -add_xray_unittest(XRayTest SOURCES +set(TEST_SOURCES allocator_test.cc buffer_queue_test.cc - fdr_controller_test.cc - fdr_log_writer_test.cc function_call_trie_test.cc profile_collector_test.cc segmented_array_test.cc test_helpers.cc xray_unit_test_main.cc) + +if (NOT COMPILER_RT_STANDALONE_BUILD OR COMPILER_RT_HAS_LLVMTESTINGSUPPORT) + list(APPEND TEST_SOURCES + fdr_controller_test.cc + fdr_log_writer_test.cc) +endif() + +add_xray_unittest(XRayTest SOURCES ${TEST_SOURCES}) diff --git a/lib/xray/xray_basic_logging.cc b/lib/xray/xray_basic_logging.cc index b65c0e43e..ae1cc0ba7 100644 --- a/lib/xray/xray_basic_logging.cc +++ b/lib/xray/xray_basic_logging.cc @@ -55,7 +55,7 @@ struct alignas(16) StackEntry { static_assert(sizeof(StackEntry) == 16, "Wrong size for StackEntry"); -struct alignas(64) ThreadLocalData { +struct XRAY_TLS_ALIGNAS(64) ThreadLocalData { void *InMemoryBuffer = nullptr; size_t BufferSize = 0; size_t BufferOffset = 0; diff --git a/lib/xray/xray_defs.h b/lib/xray/xray_defs.h index e5c37c066..c009bcc87 100644 --- a/lib/xray/xray_defs.h +++ b/lib/xray/xray_defs.h @@ -19,4 +19,14 @@ #define XRAY_NEVER_INSTRUMENT #endif +#if SANITIZER_NETBSD +// NetBSD: thread_local is not aligned properly, and the code relying +// on it segfaults +#define XRAY_TLS_ALIGNAS(x) +#define XRAY_HAS_TLS_ALIGNAS 0 +#else +#define XRAY_TLS_ALIGNAS(x) alignas(x) +#define XRAY_HAS_TLS_ALIGNAS 1 +#endif + #endif // XRAY_XRAY_DEFS_H diff --git a/lib/xray/xray_fdr_log_writer.h b/lib/xray/xray_fdr_log_writer.h index dbd1a98fe..7712e1377 100644 --- a/lib/xray/xray_fdr_log_writer.h +++ b/lib/xray/xray_fdr_log_writer.h @@ -41,7 +41,7 @@ template <size_t Index> struct SerializerImpl { Index >= std::tuple_size<typename std::remove_reference< Tuple>::type>::value, int>::type = 0> - static void serializeTo(char *, Tuple &&){}; + static void serializeTo(char *, Tuple &&) {} }; using Serializer = SerializerImpl<0>; diff --git a/lib/xray/xray_fdr_logging.cc b/lib/xray/xray_fdr_logging.cc index 3893b7a2a..1eda26df7 100644 --- a/lib/xray/xray_fdr_logging.cc +++ b/lib/xray/xray_fdr_logging.cc @@ -51,7 +51,7 @@ namespace { // call so that it can be initialized on first use instead of as a global. We // force the alignment to 64-bytes for x86 cache line alignment, as this // structure is used in the hot path of implementation. -struct alignas(64) ThreadLocalData { +struct XRAY_TLS_ALIGNAS(64) ThreadLocalData { BufferQueue::Buffer Buffer{}; BufferQueue *BQ = nullptr; @@ -124,8 +124,10 @@ static atomic_sint32_t LogFlushStatus = { // critical section, calling a function that might be XRay instrumented (and // thus in turn calling into malloc by virtue of registration of the // thread_local's destructor). +#if XRAY_HAS_TLS_ALIGNAS static_assert(alignof(ThreadLocalData) >= 64, "ThreadLocalData must be cache line aligned."); +#endif static ThreadLocalData &getThreadLocalData() { thread_local typename std::aligned_storage< sizeof(ThreadLocalData), alignof(ThreadLocalData)>::type TLDStorage{}; diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc index d1c750f0c..b0922aa8e 100644 --- a/lib/xray/xray_init.cc +++ b/lib/xray/xray_init.cc @@ -67,6 +67,9 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { if (atomic_load(&XRayInitialized, memory_order_acquire)) return; + // XRAY is not compatible with PaX MPROTECT + CheckMPROTECT(); + if (!atomic_load(&XRayFlagsInitialized, memory_order_acquire)) { initializeFlags(); atomic_store(&XRayFlagsInitialized, true, memory_order_release); diff --git a/lib/xray/xray_trampoline_x86_64.S b/lib/xray/xray_trampoline_x86_64.S index 9dffae048..52985ffd1 100644 --- a/lib/xray/xray_trampoline_x86_64.S +++ b/lib/xray/xray_trampoline_x86_64.S @@ -91,10 +91,10 @@ .text #if !defined(__APPLE__) .section .text + .file "xray_trampoline_x86.S" #else .section __TEXT,__text #endif - .file "xray_trampoline_x86.S" //===----------------------------------------------------------------------===// diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 554ba5fa0..2e239d54e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,8 +15,6 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) endif() if(COMPILER_RT_STANDALONE_BUILD) - add_executable(FileCheck IMPORTED GLOBAL) - set_property(TARGET FileCheck PROPERTY IMPORTED_LOCATION ${LLVM_TOOLS_BINARY_DIR}/FileCheck) list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS FileCheck) endif() diff --git a/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc index 4c935e2b0..6328cbb2c 100644 --- a/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc +++ b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc @@ -1,8 +1,8 @@ // Test that mixed static/dynamic sanitization of program objects // is prohibited. // -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -// RUN: %clangxx_asan_static %s %t.so -o %t +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib +// RUN: %clangxx_asan_static %s %ld_flags_rpath_exe -o %t // RUN: not %run %t 2>&1 | FileCheck %s // REQUIRES: asan-dynamic-runtime diff --git a/test/asan/TestCases/Linux/local_alias.cc b/test/asan/TestCases/Linux/local_alias.cc index 635e30b87..a8b3d75e3 100644 --- a/test/asan/TestCases/Linux/local_alias.cc +++ b/test/asan/TestCases/Linux/local_alias.cc @@ -4,13 +4,10 @@ // false positive global-buffer-overflow due to sanitized library poisons // globals from non-sanitized one. // -// FIXME: https://github.com/google/sanitizers/issues/316 -// XFAIL: android -// -// RUN: %clangxx_asan -DBUILD_INSTRUMENTED_DSO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %t-INSTRUMENTED-SO.so -// RUN: %clangxx -DBUILD_UNINSTRUMENTED_DSO=1 -fPIC -shared %s -o %t-UNINSTRUMENTED-SO.so +// RUN: %clangxx_asan -DBUILD_INSTRUMENTED_DSO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %dynamiclib1 +// RUN: %clangxx -DBUILD_UNINSTRUMENTED_DSO=1 -fPIC -shared %s -o %dynamiclib2 // RUN: %clangxx %s -c -mllvm -asan-use-private-alias -o %t.o -// RUN: %clangxx_asan %t.o %t-UNINSTRUMENTED-SO.so %t-INSTRUMENTED-SO.so -o %t-EXE +// RUN: %clangxx_asan %t.o %ld_flags_rpath_exe2 %ld_flags_rpath_exe1 -o %t-EXE // RUN: %run %t-EXE #if defined (BUILD_INSTRUMENTED_DSO) diff --git a/test/asan/TestCases/Linux/new_delete_mismatch.cc b/test/asan/TestCases/Linux/new_delete_mismatch.cc index 3a71862fb..05f74bda7 100644 --- a/test/asan/TestCases/Linux/new_delete_mismatch.cc +++ b/test/asan/TestCases/Linux/new_delete_mismatch.cc @@ -14,3 +14,4 @@ int main() { } // CHECK: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x +// CHECK: is located 0 bytes inside of 10-byte region diff --git a/test/asan/TestCases/Linux/new_delete_mismatch_global.cc b/test/asan/TestCases/Linux/new_delete_mismatch_global.cc new file mode 100644 index 000000000..3f1a78715 --- /dev/null +++ b/test/asan/TestCases/Linux/new_delete_mismatch_global.cc @@ -0,0 +1,16 @@ +// Check that we report delete on a memory that belongs to a global variable. + +// RUN: %clangxx_asan -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s + +#include <stdlib.h> + +static volatile char *x; +char a[10]; + +int main() { + x = &a[0]; + delete x; +} + +// CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed +// CHECK: is located 0 bytes inside of global variable 'a' defined in diff --git a/test/asan/TestCases/Linux/new_delete_mismatch_stack.cc b/test/asan/TestCases/Linux/new_delete_mismatch_stack.cc new file mode 100644 index 000000000..bbf07cc21 --- /dev/null +++ b/test/asan/TestCases/Linux/new_delete_mismatch_stack.cc @@ -0,0 +1,17 @@ +// Check that we report delete on a memory that belongs to a stack variable. + +// RUN: %clangxx_asan -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s + +#include <stdlib.h> + +static volatile char *x; + +int main() { + char a[10]; + x = &a[0]; + delete x; +} + +// CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed +// CHECK: is located in stack of thread T0 at offset +// CHECK: 'a'{{.*}} <== Memory access at offset {{16|32}} is inside this variable diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc index 05ee1e5c1..a1941fcc8 100644 --- a/test/asan/TestCases/Linux/odr-violation.cc +++ b/test/asan/TestCases/Linux/odr-violation.cc @@ -5,15 +5,15 @@ // pointers. This setting is not on by default because it's too expensive. // // Different size: detect a bug if detect_odr_violation>=1 -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so -// RUN: %clangxx_asan %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib +// RUN: %clangxx_asan %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=1 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // // Same size: report a bug only if detect_odr_violation>=2. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so -DSZ=100 +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %dynamiclib -DSZ=100 // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=1 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s @@ -24,18 +24,18 @@ // RUN: rm -f %t.supp // // Use private aliases for global variables without indicator symbol. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %t-ODR-SO.so -DSZ=100 -// RUN: %clangxx_asan -mllvm -asan-use-private-alias %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -mllvm -asan-use-private-alias %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED // Use private aliases for global variables: use indicator symbol to detect ODR violation. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s -o %t-ODR-SO.so -DSZ=100 -// RUN: %clangxx_asan -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -mllvm -asan-use-private-alias -mllvm -asan-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // Same as above but with clang switches. -// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -fsanitize-address-use-odr-indicator %s -o %t-ODR-SO.so -DSZ=100 -// RUN: %clangxx_asan -fsanitize-address-use-odr-indicator %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared -fsanitize-address-use-odr-indicator %s -o %dynamiclib -DSZ=100 +// RUN: %clangxx_asan -fsanitize-address-use-odr-indicator %s %ld_flags_rpath_exe -o %t-ODR-EXE // RUN: %env_asan_opts=fast_unwind_on_malloc=0 not %run %t-ODR-EXE 2>&1 | FileCheck %s // GNU driver doesn't handle .so files properly. @@ -60,6 +60,6 @@ int main(int argc, char **argv) { // CHECK: These globals were registered at these points: // CHECK: ODR-EXE -// CHECK: ODR-SO +// CHECK: odr-violation.cc.dynamic // CHECK: SUMMARY: AddressSanitizer: odr-violation: global 'foo::G' at {{.*}}odr-violation.cc // DISABLED: PASS diff --git a/test/asan/TestCases/Linux/odr-vtable.cc b/test/asan/TestCases/Linux/odr-vtable.cc new file mode 100644 index 000000000..fdbab4bb1 --- /dev/null +++ b/test/asan/TestCases/Linux/odr-vtable.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx_asan -fno-rtti -DBUILD_SO1 -fPIC -shared %s -o %dynamiclib1 +// RUN: %clangxx_asan -fno-rtti -DBUILD_SO2 -fPIC -shared %s -o %dynamiclib2 +// RUN: %clangxx_asan -fno-rtti %s %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t +// RUN: %env_asan_opts=fast_unwind_on_malloc=0:detect_odr_violation=2 not %run %t 2>&1 | FileCheck %s + +struct XYZ { + virtual void foo(); +}; + +#if defined(BUILD_SO1) + +void XYZ::foo() {} + +#elif defined(BUILD_SO2) + +void XYZ::foo() {} + +#else + +int main() {} + +#endif + +// CHECK: AddressSanitizer: odr-violation +// CHECK-NEXT: 'vtable for XYZ' +// CHECK-NEXT: 'vtable for XYZ' diff --git a/test/asan/TestCases/Linux/odr_c_test.c b/test/asan/TestCases/Linux/odr_c_test.c index b1d23493b..c1423ed30 100644 --- a/test/asan/TestCases/Linux/odr_c_test.c +++ b/test/asan/TestCases/Linux/odr_c_test.c @@ -1,13 +1,11 @@ // Test that we can properly report an ODR violation // between an instrumented global and a non-instrumented global. -// RUN: %clang_asan %s -fPIC -shared -o %t-1.so -DFILE1 -// RUN: %clang_asan %s -fPIC -shared -o %t-2.so -DFILE2 -// RUN: %clang_asan %s -fPIE %t-1.so %t-2.so -Wl,-R`pwd` -o %t +// RUN: %clang_asan %s -fPIC -shared -o %dynamiclib1 -DFILE1 +// RUN: %clang_asan %s -fPIC -shared -o %dynamiclib2 -DFILE2 +// RUN: %clang_asan %s -fPIE %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t // RUN: not %run %t 2>&1 | FileCheck %s // -// REQUIRES: x86_64-target-arch -// // CHECK: The following global variable is not properly aligned. // CHECK: ERROR: AddressSanitizer: odr-violation #if defined(FILE1) diff --git a/test/asan/TestCases/Linux/preinit_test.cc b/test/asan/TestCases/Linux/preinit_test.cc index 10dde67d6..f8c2b6bf5 100644 --- a/test/asan/TestCases/Linux/preinit_test.cc +++ b/test/asan/TestCases/Linux/preinit_test.cc @@ -1,8 +1,5 @@ -// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 -// XFAIL: android -// -// RUN: %clangxx -DFUNC=zzzz %s -shared -o %t.so -fPIC -// RUN: %clangxx_asan -DFUNC=main %s -o %t -Wl,-R. %t.so +// RUN: %clangxx -DFUNC=zzzz %s -shared -o %dynamiclib -fPIC +// RUN: %clangxx_asan -DFUNC=main %s -o %t %ld_flags_rpath_exe // RUN: %run %t // GNU driver doesn't handle .so files properly. diff --git a/test/asan/TestCases/Posix/no-fd.cc b/test/asan/TestCases/Posix/no-fd.cc new file mode 100644 index 000000000..086b01412 --- /dev/null +++ b/test/asan/TestCases/Posix/no-fd.cc @@ -0,0 +1,43 @@ +// RUN: %clangxx_asan -std=c++11 -O0 %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=debug=1,verbosity=2 %run %t 2>&1 | FileCheck %s + +// Test ASan initialization + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +extern "C" const char *__asan_default_options() { + return "test_only_emulate_no_memorymap=1"; +} + +void parent(int argc, char **argv) { + fprintf(stderr, "hello\n"); + // CHECK: hello + close(0); + close(1); + dup2(2, 3); + close(2); + char *const newargv[] = {argv[0], (char *)"x", nullptr}; + execv(argv[0], newargv); + perror("execve"); + exit(1); +} + +void child() { + assert(dup(3) == 0); + assert(dup(3) == 1); + assert(dup(3) == 2); + fprintf(stderr, "world\n"); + // CHECK: world +} + +int main(int argc, char **argv) { + if (argc == 1) { + parent(argc, argv); + } else { + child(); + } +} diff --git a/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/test/asan/TestCases/Posix/tsd_dtor_leak.cc index 860f3459e..26109fe1a 100644 --- a/test/asan/TestCases/Posix/tsd_dtor_leak.cc +++ b/test/asan/TestCases/Posix/tsd_dtor_leak.cc @@ -3,6 +3,8 @@ // RUN: %clangxx_asan -O1 %s -pthread -o %t // RUN: %env_asan_opts=quarantine_size_mb=0 %run %t // XFAIL: x86_64-netbsd +// Assertion fails +// XFAIL: x86_64-freebsd #include <pthread.h> #include <stdio.h> #include <stdlib.h> diff --git a/test/asan/TestCases/asan_and_llvm_coverage_test.cc b/test/asan/TestCases/asan_and_llvm_coverage_test.cc index 005bf7de1..2ba5a42d1 100644 --- a/test/asan/TestCases/asan_and_llvm_coverage_test.cc +++ b/test/asan/TestCases/asan_and_llvm_coverage_test.cc @@ -4,8 +4,6 @@ // We don't really support running tests using profile runtime on Windows. // UNSUPPORTED: windows-msvc -// profile is disabled by default -// UNSUPPORTED: netbsd #include <stdio.h> int foo() { return 1; } int XXX = foo(); diff --git a/test/asan/TestCases/printf-3.c b/test/asan/TestCases/printf-3.c index 1183b2f6f..4f54ff956 100644 --- a/test/asan/TestCases/printf-3.c +++ b/test/asan/TestCases/printf-3.c @@ -6,6 +6,10 @@ // FIXME: printf is not intercepted on Windows yet. // XFAIL: windows-msvc +// New Bionic rejects %n +// https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336 +// UNSUPPORTED: android + #include <stdio.h> int main() { #ifdef _MSC_VER diff --git a/test/builtins/Unit/ppc/fixtfdi_test.c b/test/builtins/Unit/ppc/fixtfdi_test.c index ea6c40563..0dc663655 100644 --- a/test/builtins/Unit/ppc/fixtfdi_test.c +++ b/test/builtins/Unit/ppc/fixtfdi_test.c @@ -1,5 +1,5 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdio.h> #include <limits.h> #include <stdint.h> @@ -476,4 +476,4 @@ int main(int argc, char *argv[]) { } return 0; -}
\ No newline at end of file +} diff --git a/test/builtins/Unit/ppc/fixunstfti_test.c b/test/builtins/Unit/ppc/fixunstfti_test.c new file mode 100644 index 000000000..0eee31db1 --- /dev/null +++ b/test/builtins/Unit/ppc/fixunstfti_test.c @@ -0,0 +1,52 @@ +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t + +#include <stdint.h> +#include <stdio.h> + +#include "fixunstfti_test.h" + +/* The long double representation, with the high and low portions of + * the long double, and the corresponding bit patterns of each double. */ +typedef union { + long double ld; + double d[2]; /* [0] is the high double, [1] is the low double. */ + unsigned long long ull[2]; /* High and low doubles as 64-bit integers. */ +} ldUnion; + +__uint128_t __fixunstfti(long double); + +int main(int argc, char *argv[]) { + /* Necessary long double and (unsigned) 128 bit integer + * declarations used to compare the computed and expected results + * from converting the IBM double-double to int128. */ + ldUnion ldInput; + __uint128_t expectedResult, computedResult; + + for (int i = 0; i < numTests; ++i) { + /* Set the expected 128 bit integer and the high and low + * values of the long double input. */ + ldInput.d[0] = testList[i].hiInput; + ldInput.d[1] = testList[i].loInput; + expectedResult = testList[i].result128; + + /* Get the computed 128 bit integer from the long double-> + * uint128 conversion, and check for errors between results. */ + computedResult = __fixunstfti(ldInput.ld); + + if (computedResult != expectedResult) { + printf("Error for __fixunstfti at input %La = ( %a , %a ):\n", ldInput.ld, + ldInput.d[0], ldInput.d[1]); + printf("\tExpected __uint128_t: 0x%016llx 0x%016llx\n", + (unsigned long long)(expectedResult >> 64), + (unsigned long long)expectedResult); + printf("\tComputed __uint128_t: 0x%016llx 0x%016llx\n\n", + (unsigned long long)(computedResult >> 64), + (unsigned long long)computedResult); + + return 1; + } + } + + return 0; +} diff --git a/test/builtins/Unit/ppc/fixunstfti_test.h b/test/builtins/Unit/ppc/fixunstfti_test.h new file mode 100644 index 000000000..d7de0ce14 --- /dev/null +++ b/test/builtins/Unit/ppc/fixunstfti_test.h @@ -0,0 +1,706 @@ +/* +* Test case inputs for: __uint128_t __fixunstfti (long double) +* Conversion from long double (IBM double-double) to 128 bit integer. +*/ + +#define INFINITY __builtin_inf() +#define QNAN __builtin_nan("") +#define INIT_U128(HI, LO) (((__uint128_t) (HI) << 64) | (LO)) + +struct testCase { + double hiInput; + double loInput; + __uint128_t result128; +}; + +struct testCase testList[] = { + { 0x0p+0, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { -0x0p+0, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { -0x0p+0, -0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0p+0, -0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { -0x1p+0, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1p+0, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000001 ) }, + { -INFINITY, 0x0p+0, ((__uint128_t)0x0000000000000000 << 64) | 0x0000000000000000 }, + { INFINITY, 0x0p+0, ((__uint128_t)0xffffffffffffffff << 64) | 0xffffffffffffffff }, + { QNAN, 0x0p+0, ((__uint128_t)0x7ff8000000000000 << 64) | 0x0000000000000000 }, + { -QNAN, 0x0p+0, ((__uint128_t)0x7ff8000000000000 << 64) | 0x0000000000000000 }, + { -0x1p+127, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1p+127, -0x1p+0, INIT_U128( 0x7fffffffffffffff, 0xffffffffffffffff ) }, + { 0x1p+0, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000001 ) }, + { 0x1p+60, 0x0p+0, INIT_U128( 0x0000000000000000, 0x1000000000000000 ) }, + { 0x1p+64, -0x1p+0, INIT_U128( 0x0000000000000000, 0xffffffffffffffff ) }, + { 0x1p+63, -0x1p+0, INIT_U128( 0x0000000000000000, 0x7fffffffffffffff ) }, + { 0x1p+64, 0x0p+0, INIT_U128( 0x0000000000000001, 0x0000000000000000 ) }, + { 0x1p+64, 0x1p+0, INIT_U128( 0x0000000000000001, 0x0000000000000001 ) }, + { 0x1.8p+64, -0x1p+0, INIT_U128( 0x0000000000000001, 0x7fffffffffffffff ) }, + { 0x1.1p+64, 0x0p+0, INIT_U128( 0x0000000000000001, 0x1000000000000000 ) }, + { 0x1p+65, -0x1p+0, INIT_U128( 0x0000000000000001, 0xffffffffffffffff ) }, + { 0x1p+127, -0x1p+64, INIT_U128( 0x7fffffffffffffff, 0x0000000000000000 ) }, + { 0x1p+127, -0x1.ep+64, INIT_U128( 0x7ffffffffffffffe, 0x2000000000000000 ) }, + { 0x1p+127, -0x1p+63, INIT_U128( 0x7fffffffffffffff, 0x8000000000000000 ) }, + { 0x1p+124, 0x0p+0, INIT_U128( 0x1000000000000000, 0x0000000000000000 ) }, + { 0x1p+124, 0x1p+0, INIT_U128( 0x1000000000000000, 0x0000000000000001 ) }, + { 0x1p+124, 0x1p+63, INIT_U128( 0x1000000000000000, 0x8000000000000000 ) }, + { 0x1p+124, 0x1p+64, INIT_U128( 0x1000000000000001, 0x0000000000000000 ) }, + { -0x1p+64, 0x0p+0, INIT_U128( 0x00000000000000000, 0x0000000000000000 ) }, + { 0x1.84p+70, 0x1.84p+6, INIT_U128( 0x0000000000000061, 0x0000000000000061 ) }, + { 0x1.5cp+6, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000057 ) }, + { 0x1p+64, -0x1.88p+6, INIT_U128( 0x0000000000000000, 0xffffffffffffff9e ) }, + { 0x1.88p+6, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000062 ) }, + { 0x1.00cp+10, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000403 ) }, + { 0x1.fffffffffffffp+63, 0x1.fep+9, INIT_U128( 0x0000000000000000, 0xfffffffffffffbfc ) }, + { 0x1.028p+10, 0x0p+0, INIT_U128( 0x0000000000000000, 0x000000000000040a ) }, + { 0x1.44p+10, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000510 ) }, + { 0x1.fffffffffffffp+63, 0x1.738p+9, INIT_U128( 0x0000000000000000, 0xfffffffffffffae7 ) }, + { 0x1.808p+10, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000602 ) }, + { 0x1.fffffffffffffp+63, 0x1.fdp+8, INIT_U128( 0x0000000000000000, 0xfffffffffffff9fd ) }, + { 0x1.048p+13, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000002090 ) }, + { 0x1.ffffffffffffbp+63, 0x1.ed8p+9, INIT_U128( 0x0000000000000000, 0xffffffffffffdbdb ) }, + { 0x1.0101p+17, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000020202 ) }, + { 0x1.fffffffffffbep+63, -0x1.09p+8, INIT_U128( 0x0000000000000000, 0xfffffffffffdeef7 ) }, + { 0x1.9002p+17, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000032004 ) }, + { 0x1.fffffffffff9cp+63, -0x1.4p+2, INIT_U128( 0x0000000000000000, 0xfffffffffffcdffb ) }, + { 0x1.902p+17, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000032040 ) }, + { 0x1.ffffffffff7fcp+63, -0x1.14p+6, INIT_U128( 0x0000000000000000, 0xffffffffffbfdfbb ) }, + { 0x1.00822p+22, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000402088 ) }, + { 0x1.0010011p+31, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000080080088 ) }, + { 0x1.0a000001p+35, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000850000008 ) }, + { 0x1.000000224p+37, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000002000000448 ) }, + { 0x1.ffffffbffefb8p+63, -0x1p+0, INIT_U128( 0x0000000000000000, 0xffffffdfff7dbfff ) }, + { 0x1.00080044p+102, 0x1.00080044p+38, INIT_U128( 0x0000004002001100, 0x0000004002001100 ) }, + { 0x1.00400000018p+107, 0x1.00400000018p+43, INIT_U128( 0x000008020000000c, 0x000008020000000c ) }, + { 0x1.ffffeffcp+63, -0x1.ap+3, INIT_U128( 0x0000000000000000, 0xfffff7fdfffffff3 ) }, + { 0x1.000000001048p+47, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000800000000824 ) }, + { 0x1.fffbffffffp+63, -0x1.808p+9, INIT_U128( 0x0000000000000000, 0xfffdffffff7ffcff ) }, + { 0x1.000810004p+62, 0x0p+0, INIT_U128( 0x0000000000000000, 0x4002040010000000 ) }, + { 0x1.7ffbf7ffep+63, -0x1p+0, INIT_U128( 0x0000000000000000, 0xbffdfbffefffffff ) }, + { 0x1p+63, 0x0p+0, INIT_U128( 0x0000000000000000, 0x8000000000000000 ) }, + { 0x1.ffffffffe8319p+63, -0x1.1f8p+9, INIT_U128( 0x0000000000000000, 0xfffffffff418c5c1 ) }, + { 0x1p+68, -0x1p+0, INIT_U128( 0x000000000000000f, 0xffffffffffffffff ) }, + { 0x1p+72, -0x1p+0, INIT_U128( 0x00000000000000ff, 0xffffffffffffffff ) }, + { 0x1p+76, -0x1p+0, INIT_U128( 0x0000000000000fff, 0xffffffffffffffff ) }, + { 0x1p+80, -0x1p+0, INIT_U128( 0x000000000000ffff, 0xffffffffffffffff ) }, + { 0x1p+84, -0x1p+0, INIT_U128( 0x00000000000fffff, 0xffffffffffffffff ) }, + { 0x1p+88, -0x1p+0, INIT_U128( 0x0000000000ffffff, 0xffffffffffffffff ) }, + { 0x1p+92, -0x1p+0, INIT_U128( 0x000000000fffffff, 0xffffffffffffffff ) }, + { 0x1p+96, -0x1p+0, INIT_U128( 0x00000000ffffffff, 0xffffffffffffffff ) }, + { 0x1p+100, -0x1p+0, INIT_U128( 0x0000000fffffffff, 0xffffffffffffffff ) }, + { 0x1p+104, -0x1p+0, INIT_U128( 0x000000ffffffffff, 0xffffffffffffffff ) }, + { 0x1p+108, -0x1p+0, INIT_U128( 0x00000fffffffffff, 0xffffffffffffffff ) }, + { 0x1p+112, -0x1p+0, INIT_U128( 0x0000ffffffffffff, 0xffffffffffffffff ) }, + { 0x1p+116, -0x1p+0, INIT_U128( 0x000fffffffffffff, 0xffffffffffffffff ) }, + { 0x1p+120, -0x1p+0, INIT_U128( 0x00ffffffffffffff, 0xffffffffffffffff ) }, + { 0x1p+124, -0x1p+0, INIT_U128( 0x0fffffffffffffff, 0xffffffffffffffff ) }, + { 0x1p+124, 0x0p+0, INIT_U128( 0x1000000000000000, 0x0000000000000000 ) }, + { 0x1p+124, 0x1.1p+4, INIT_U128( 0x1000000000000000, 0x0000000000000011 ) }, + { 0x1p+124, 0x1.11p+8, INIT_U128( 0x1000000000000000, 0x0000000000000111 ) }, + { 0x1p+124, 0x1.111p+12, INIT_U128( 0x1000000000000000, 0x0000000000001111 ) }, + { 0x1p+124, 0x1.1111p+16, INIT_U128( 0x1000000000000000, 0x0000000000011111 ) }, + { 0x1p+124, 0x1.11111p+20, INIT_U128( 0x1000000000000000, 0x0000000000111111 ) }, + { 0x1p+124, 0x1.111111p+24, INIT_U128( 0x1000000000000000, 0x0000000001111111 ) }, + { 0x1p+124, 0x1.1111111p+28, INIT_U128( 0x1000000000000000, 0x0000000011111111 ) }, + { 0x1p+124, 0x1.11111111p+32, INIT_U128( 0x1000000000000000, 0x0000000111111111 ) }, + { 0x1p+124, 0x1.111111111p+36, INIT_U128( 0x1000000000000000, 0x0000001111111111 ) }, + { 0x1p+124, 0x1.1111111111p+40, INIT_U128( 0x1000000000000000, 0x0000011111111111 ) }, + { 0x1p+124, 0x1.11111111111p+44, INIT_U128( 0x1000000000000000, 0x0000111111111111 ) }, + { 0x1p+124, 0x1.111111111111p+48, INIT_U128( 0x1000000000000000, 0x0001111111111111 ) }, + { 0x1p+124, 0x1.1111111111111p+52, INIT_U128( 0x1000000000000000, 0x0011111111111111 ) }, + { 0x1p+124, 0x1.11111111111111p+56, INIT_U128( 0x1000000000000000, 0x0111111111111110 ) }, + { 0x1p+124, 0x1.111111111111111p+60, INIT_U128( 0x1000000000000000, 0x1111111111111100 ) }, + { 0x1.6ffffffefp+63, -0x1p+0, INIT_U128( 0x0000000000000000, 0xb7ffffff77ffffff ) }, + { 0x1p+106, 0x0p+0, INIT_U128( 0x0000040000000000, 0x0000000000000000 ) }, + { 0x1.ff8p+29, 0x0p+0, INIT_U128( 0x0000000000000000, 0x000000003ff00000 ) }, + { 0x1.6ff7ffffffffcp+63, -0x1p+0, INIT_U128( 0x0000000000000000, 0xb7fbffffffffdfff ) }, + { 0x1.2400000000004p+62, 0x0p+0, INIT_U128( 0x0000000000000000, 0x4900000000001000 ) }, + { 0x1.24000000001p+126, 0x1.24000000001p+62, INIT_U128( 0x4900000000040000, 0x4900000000040000 ) }, + { 0x1.2400001p+126, 0x1.2400001p+62, INIT_U128( 0x4900000400000000, 0x4900000400000000 ) }, + { 0x1.240001p+126, 0x1.240001p+62, INIT_U128( 0x4900004000000000, 0x4900004000000000 ) }, + { 0x1.24001p+126, 0x1.24001p+62, INIT_U128( 0x4900040000000000, 0x4900040000000000 ) }, + { 0x1.24008p+126, 0x1.24008p+62, INIT_U128( 0x4900200000000000, 0x4900200000000000 ) }, + { 0x1.2404p+126, 0x1.2404p+62, INIT_U128( 0x4901000000000000, 0x4901000000000000 ) }, + { 0x1.244p+126, 0x1.244p+62, INIT_U128( 0x4910000000000000, 0x4910000000000000 ) }, + { 0x1.26p+126, 0x1.26p+62, INIT_U128( 0x4980000000000000, 0x4980000000000000 ) }, + { 0x1.3p+126, 0x1.3p+62, INIT_U128( 0x4c00000000000000, 0x4c00000000000000 ) }, + { 0x1.800000000001p+126, 0x1.6000000000004p+64, INIT_U128( 0x6000000000004001, 0x6000000000004000 ) }, + { 0x1.cp+126, 0x1.00ep+71, INIT_U128( 0x7000000000000080, 0x7000000000000000 ) }, + { 0x1.c000000000008p+126, 0x1.c000000000008p+62, INIT_U128( 0x7000000000002000, 0x7000000000002000 ) }, + { 0x1.c00000000004p+126, 0x1.c00000000004p+62, INIT_U128( 0x7000000000010000, 0x7000000000010000 ) }, + { 0x1.c0000000002p+126, 0x1.c0000000002p+62, INIT_U128( 0x7000000000080000, 0x7000000000080000 ) }, + { 0x1.c000000002p+126, 0x1.c000000002p+62, INIT_U128( 0x7000000000800000, 0x7000000000800000 ) }, + { 0x1.c00000002p+126, 0x1.c00000002p+62, INIT_U128( 0x7000000008000000, 0x7000000008000000 ) }, + { 0x1.c0000008p+126, 0x1.c0000008p+62, INIT_U128( 0x7000000200000000, 0x7000000200000000 ) }, + { 0x1.c000002p+126, 0x1.c000002p+62, INIT_U128( 0x7000000800000000, 0x7000000800000000 ) }, + { 0x1.c00004p+126, 0x1.c00004p+62, INIT_U128( 0x7000010000000000, 0x7000010000000000 ) }, + { 0x1.c0002p+126, 0x1.c0002p+62, INIT_U128( 0x7000080000000000, 0x7000080000000000 ) }, + { 0x1.c008p+126, 0x1.c008p+62, INIT_U128( 0x7002000000000000, 0x7002000000000000 ) }, + { 0x1.c02p+126, 0x1.c02p+62, INIT_U128( 0x7008000000000000, 0x7008000000000000 ) }, + { 0x1.c2p+126, 0x1.c2p+62, INIT_U128( 0x7080000000000000, 0x7080000000000000 ) }, + { 0x1.dp+126, 0x1.dp+62, INIT_U128( 0x7400000000000000, 0x7400000000000000 ) }, + { 0x1.80be0cccccccdp+63, 0x1.80bc266666666p+63, INIT_U128( 0x0000000000000001, 0x80bd199999999800 ) }, + { 0x1.017c19999999ap+62, 0x1.01784cccccccdp+62, INIT_U128( 0x0000000000000000, 0x80bd199999999c00 ) }, + { 0x1.80be0cccccccdp+63, 0x1.01784cccccccdp+62, INIT_U128( 0x0000000000000001, 0x00bd199999999c00 ) }, + { 0x1.88a1831790ce8p+63, 0x1.1143062f219d8p+62, INIT_U128( 0x0000000000000001, 0x08a1831790cea000 ) }, + { 0x1.1143062f219dp+62, 0x1.88a1831790cecp+63, INIT_U128( 0x0000000000000001, 0x08a1831790cea000 ) }, + { 0x1.88a1831790ce8p+63, 0x1.88a1831790cecp+63, INIT_U128( 0x0000000000000001, 0x88a1831790cea000 ) }, + { 0x1.00014f3089001p+64, 0x1.e133333333333p+6, INIT_U128( 0x0000000000000001, 0x00014f3089001078 ) }, + { 0x1.fffffffffffffp+127, 0x1p+75, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.fffffffffffffp+127, 0x1.fffffffffffffp+74, INIT_U128( 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFC00000 ) }, + { 0x1.f066666666666p+6, -0x1.f066666666667p-768, INIT_U128( 0x0000000000000000, 0x000000000000007C ) }, + { 0x1.f066666666666p+6, 0x1.f066666666667p-768, INIT_U128( 0x0000000000000000, 0x000000000000007C ) }, + { 0x1.1111111111111p+124, 0x1.1p+68, INIT_U128( 0x1111111111111111, 0x0000000000000000 ) }, + { 0x0.0000000000001p-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0.0000001160e9fp-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0.0000001a26f3cp-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { -0x0.0000001134f35p-1022, -0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0.00003f9eec3ep-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0.0a40bec0e4818p-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x0.0d4e1fcc5a9c4p-1022, 0x0p+0, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.acf5f5ef59ebfp-1007, 0x0.00000000000a8p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.1f45384e3e8a7p-1007, 0x0.00000000000b4p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.8474983f08e93p-1007, 0x0.00000000000d9p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.47ad6cf88f5aep-1007, 0x0.00000000000bcp-1022, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.2da4480a5b489p-1, 0x1.9e20ea6f3c41dp-618, INIT_U128( 0x0000000000000000, 0x0000000000000000 ) }, + { 0x1.438fba0a871f8p+0, 0x1.086e1f6e10dc4p-992, INIT_U128( 0x0000000000000000, 0x0000000000000001 ) }, + { 0x1.51c874cca390ep+0, 0x1.5dd30576bba6p-992, INIT_U128( 0x0000000000000000, 0x0000000000000001 ) }, + { 0x1.3691a8086d235p+1, 0x1.3670ebb66ce1ep-281, INIT_U128( 0x0000000000000000, 0x0000000000000002 ) }, + { 0x1.b800c73570019p+1, 0x1.1bf9094c37f21p-281, INIT_U128( 0x0000000000000000, 0x0000000000000003 ) }, + { 0x1.c1e89f3783d14p+1, 0x1.69999266d3332p-281, INIT_U128( 0x0000000000000000, 0x0000000000000003 ) }, + { 0x1.390b19fa72163p+1, 0x1.25bf7f6c4b7fp-281, INIT_U128( 0x0000000000000000, 0x0000000000000002 ) }, + { 0x1.4beee12897ddcp+2, 0x1.549d853aa93bp-815, INIT_U128( 0x0000000000000000, 0x0000000000000005 ) }, + { 0x1.e37742bfc6ee9p+2, 0x1.081a6dda1034ep-815, INIT_U128( 0x0000000000000000, 0x0000000000000007 ) }, + { 0x1.e6c0b50fcd816p+2, 0x1.c3d7967b87af3p-815, INIT_U128( 0x0000000000000000, 0x0000000000000007 ) }, + { 0x1.590290feb2052p+2, 0x1.07756f600eeaep-815, INIT_U128( 0x0000000000000000, 0x0000000000000005 ) }, + { 0x1.66154348cc2a8p+3, 0x1.bb93d1a97727ap-619, INIT_U128( 0x0000000000000000, 0x000000000000000b ) }, + { 0x1.69cf9e9ed39f4p+3, 0x1.ce842e739d086p-619, INIT_U128( 0x0000000000000000, 0x000000000000000b ) }, + { 0x1.e884574bd108bp+3, 0x1.9c6561f338cacp-619, INIT_U128( 0x0000000000000000, 0x000000000000000f ) }, + { 0x1.6263a430c4c74p+4, 0x1.6b327792d664fp-117, INIT_U128( 0x0000000000000000, 0x0000000000000016 ) }, + { 0x1.43637d1286c7p+4, 0x1.546df60aa8dbfp-117, INIT_U128( 0x0000000000000000, 0x0000000000000014 ) }, + { 0x1.faa21259f5443p+4, 0x1.b6708ecf6ce12p-117, INIT_U128( 0x0000000000000000, 0x000000000000001f ) }, + { 0x1.fd3105d1fa62p+4, 0x1.370912046e122p-117, INIT_U128( 0x0000000000000000, 0x000000000000001f ) }, + { 0x1.cf952d399f2a5p+5, 0x1.0d283ebe1a508p-735, INIT_U128( 0x0000000000000000, 0x0000000000000039 ) }, + { 0x1.6ac8f880d591fp+5, 0x1.ec284da5d8509p-735, INIT_U128( 0x0000000000000000, 0x000000000000002d ) }, + { 0x1.919c82bf2339p+5, 0x1.a58971fd4b12ep-735, INIT_U128( 0x0000000000000000, 0x0000000000000032 ) }, + { 0x1.789a89ccf1351p+5, 0x1.ebd48283d7a91p-735, INIT_U128( 0x0000000000000000, 0x000000000000002f ) }, + { 0x1.8db2068d1b641p+6, 0x1.056174ca0ac2ep-802, INIT_U128( 0x0000000000000000, 0x0000000000000063 ) }, + { 0x1.8d618e6f1ac32p+6, 0x1.0643da660c87cp-802, INIT_U128( 0x0000000000000000, 0x0000000000000063 ) }, + { 0x1.f10fc45fe21f8p+6, 0x1.d71f2d6bae3e5p-802, INIT_U128( 0x0000000000000000, 0x000000000000007c ) }, + { 0x1.1cafcb76395fap+8, 0x1.026dfe9a04dcp-78, INIT_U128( 0x0000000000000000, 0x000000000000011c ) }, + { 0x1.8b9a3b5917348p+8, 0x1.f64ef081ec9dep-78, INIT_U128( 0x0000000000000000, 0x000000000000018b ) }, + { 0x1.347ea22c68fd4p+8, 0x1.a86c77e750d8fp-78, INIT_U128( 0x0000000000000000, 0x0000000000000134 ) }, + { 0x1.c498c82389319p+8, 0x1.0d4d96061a9b3p-78, INIT_U128( 0x0000000000000000, 0x00000000000001c4 ) }, + { 0x1.3e4fa8b47c9f5p+9, 0x1.d0718139a0e3p-293, INIT_U128( 0x0000000000000000, 0x000000000000027c ) }, + { 0x1.5ffd3878bffa7p+9, 0x1.1828a29c30514p-293, INIT_U128( 0x0000000000000000, 0x00000000000002bf ) }, + { 0x1.bbbb3b8577768p+9, 0x1.ba79b21b74f36p-293, INIT_U128( 0x0000000000000000, 0x0000000000000377 ) }, + { 0x1.8777cb810eefap+9, 0x1.bb3afdc57676p-293, INIT_U128( 0x0000000000000000, 0x000000000000030e ) }, + { 0x1.8e7992a11cf32p+10, 0x1.a18e4033431c8p-789, INIT_U128( 0x0000000000000000, 0x0000000000000639 ) }, + { 0x1.7684faeced0ap+10, 0x1.5f11706abe22ep-789, INIT_U128( 0x0000000000000000, 0x00000000000005da ) }, + { 0x1.7d7ac11afaf58p+10, 0x1.64553beec8aa8p-789, INIT_U128( 0x0000000000000000, 0x00000000000005f5 ) }, + { 0x1.a540fa454a81fp+10, 0x1.329efbd6653ep-789, INIT_U128( 0x0000000000000000, 0x0000000000000695 ) }, + { 0x1.92ed812325dbp+11, 0x0.000012eafc716p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000c97 ) }, + { 0x1.b10abb4562158p+11, 0x0.00001e4765564p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000d88 ) }, + { 0x1.f6751879ecea3p+11, 0x0.000014435b4b9p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000fb3 ) }, + { 0x1.32e6b0a465cd6p+11, 0x0.00001729d5c09p-1022, INIT_U128( 0x0000000000000000, 0x0000000000000997 ) }, + { 0x1.11f336c623e67p+12, 0x1.9d9af61f3b35fp-489, INIT_U128( 0x0000000000000000, 0x000000000000111f ) }, + { 0x1.18ebab5631d76p+12, 0x1.47d8de9e8fb1cp-489, INIT_U128( 0x0000000000000000, 0x000000000000118e ) }, + { 0x1.c25a29f984b45p+12, 0x1.c65b51e78cb6ap-489, INIT_U128( 0x0000000000000000, 0x0000000000001c25 ) }, + { 0x1.cf37f3299e6ffp+12, 0x1.38601ed270c04p-489, INIT_U128( 0x0000000000000000, 0x0000000000001cf3 ) }, + { 0x1.00db141c01b62p+13, 0x1.a4ea801149d5p-963, INIT_U128( 0x0000000000000000, 0x000000000000201b ) }, + { 0x1.b81f3643703e7p+13, 0x1.849a11a509342p-963, INIT_U128( 0x0000000000000000, 0x0000000000003703 ) }, + { 0x1.6dbbb6a4db777p+13, 0x1.362f46546c5e9p-963, INIT_U128( 0x0000000000000000, 0x0000000000002db7 ) }, + { 0x1.eeb645abdd6c8p+13, 0x1.1edee6683dbddp-963, INIT_U128( 0x0000000000000000, 0x0000000000003dd6 ) }, + { 0x1.dc7ac6d3b8f59p+14, 0x1.3a4d2846749a5p-96, INIT_U128( 0x0000000000000000, 0x000000000000771e ) }, + { 0x1.51b38df4a3672p+14, 0x1.ef5f5533debeap-96, INIT_U128( 0x0000000000000000, 0x000000000000546c ) }, + { 0x1.5cdcee10b9b9ep+14, 0x1.dd44c049ba898p-96, INIT_U128( 0x0000000000000000, 0x0000000000005737 ) }, + { 0x1.f5266d45ea4cdp+14, 0x1.3970615e72e0cp-96, INIT_U128( 0x0000000000000000, 0x0000000000007d49 ) }, + { 0x1.2ab9252a55724p+15, 0x1.a85ba3d950b74p-690, INIT_U128( 0x0000000000000000, 0x000000000000955c ) }, + { 0x1.707a4edee0f4ap+15, 0x1.00541f2800a84p-690, INIT_U128( 0x0000000000000000, 0x000000000000b83d ) }, + { 0x1.594c6252b298cp+15, 0x1.837b6c0706f6ep-690, INIT_U128( 0x0000000000000000, 0x000000000000aca6 ) }, + { 0x1.41fad8e683f5bp+15, 0x1.7cb3a2bef9674p-690, INIT_U128( 0x0000000000000000, 0x000000000000a0fd ) }, + { 0x1.f150e9b3e2a1dp+16, 0x1.155a86a62ab51p-762, INIT_U128( 0x0000000000000000, 0x000000000001f150 ) }, + { 0x1.0a3ca44214794p+16, 0x1.5c85e07eb90bcp-762, INIT_U128( 0x0000000000000000, 0x0000000000010a3c ) }, + { 0x1.0ef4814e1de9p+16, 0x1.2cd0510659a0ap-762, INIT_U128( 0x0000000000000000, 0x0000000000010ef4 ) }, + { 0x1.99373a97326e7p+16, 0x1.98d239d731a47p-762, INIT_U128( 0x0000000000000000, 0x0000000000019937 ) }, + { 0x1.0062da5400c5cp+17, 0x1.12b3124825662p-940, INIT_U128( 0x0000000000000000, 0x00000000000200c5 ) }, + { 0x1.8ac0f0251581ep+17, 0x1.60b254d0c164ap-940, INIT_U128( 0x0000000000000000, 0x0000000000031581 ) }, + { 0x1.51c0eb94a381ep+17, 0x1.ce1da4059c3b4p-940, INIT_U128( 0x0000000000000000, 0x000000000002a381 ) }, + { 0x1.5e83e6a4bd07dp+17, 0x1.adcff7815b9ffp-940, INIT_U128( 0x0000000000000000, 0x000000000002bd07 ) }, + { 0x1.242e55bc485cap+18, 0x0.000000000001fp-1022, INIT_U128( 0x0000000000000000, 0x00000000000490b9 ) }, + { 0x1.7d59ac2cfab36p+18, 0x0.000000000001p-1022, INIT_U128( 0x0000000000000000, 0x000000000005f566 ) }, + { 0x1.d19e6101a33ccp+18, 0x0.0000000000014p-1022, INIT_U128( 0x0000000000000000, 0x0000000000074679 ) }, + { 0x1.34c9981869933p+18, 0x0.0000000000011p-1022, INIT_U128( 0x0000000000000000, 0x000000000004d326 ) }, + { 0x1.c066e34f80cddp+19, 0x1.e3f363b5c7e6dp-881, INIT_U128( 0x0000000000000000, 0x00000000000e0337 ) }, + { 0x1.df32bc2fbe658p+19, 0x1.df947163bf28ep-881, INIT_U128( 0x0000000000000000, 0x00000000000ef995 ) }, + { 0x1.3bbc859e7779p+19, 0x1.0773506c0ee6ap-881, INIT_U128( 0x0000000000000000, 0x000000000009dde4 ) }, + { 0x1.3b65fdae76ccp+19, 0x1.36924fde6d24ap-881, INIT_U128( 0x0000000000000000, 0x000000000009db2f ) }, + { 0x1.52c7a810a58f5p+20, 0x1.a11a939f42352p-561, INIT_U128( 0x0000000000000000, 0x0000000000152c7a ) }, + { 0x1.9546ee252a8dep+20, 0x1.eeb4a28ddd695p-561, INIT_U128( 0x0000000000000000, 0x000000000019546e ) }, + { 0x1.f50465bdea08cp+20, 0x1.7288f4c2e511ep-561, INIT_U128( 0x0000000000000000, 0x00000000001f5046 ) }, + { 0x1.b8199d2770334p+20, 0x1.a2d4ddfb45a9cp-561, INIT_U128( 0x0000000000000000, 0x00000000001b8199 ) }, + { 0x1.efe67d0fdfccfp+21, 0x1.05ac37920b587p-121, INIT_U128( 0x0000000000000000, 0x00000000003dfccf ) }, + { 0x1.a1c8a86343915p+21, 0x1.ff7f144bfefe2p-121, INIT_U128( 0x0000000000000000, 0x0000000000343915 ) }, + { 0x1.0b3b76001676fp+21, 0x1.742fba58e85f8p-121, INIT_U128( 0x0000000000000000, 0x000000000021676e ) }, + { 0x1.cb12f6579625fp+21, 0x1.5e77e020bcefcp-121, INIT_U128( 0x0000000000000000, 0x000000000039625e ) }, + { 0x1.bd380f437a702p+22, 0x1.491fe5e8923fcp-995, INIT_U128( 0x0000000000000000, 0x00000000006f4e03 ) }, + { 0x1.46fbb89c8df77p+22, 0x1.a09fc8f7413f9p-995, INIT_U128( 0x0000000000000000, 0x000000000051beee ) }, + { 0x1.17e871f42fd0ep+22, 0x1.a11fc1a7423f8p-995, INIT_U128( 0x0000000000000000, 0x000000000045fa1c ) }, + { 0x1.277e999a4efd3p+22, 0x1.4bd3e11097a7cp-995, INIT_U128( 0x0000000000000000, 0x000000000049dfa6 ) }, + { 0x1.6e4d3250dc9a6p+23, 0x1.edf09145dbe12p-447, INIT_U128( 0x0000000000000000, 0x0000000000b72699 ) }, + { 0x1.eb0413bfd6083p+23, 0x1.29c840b053908p-447, INIT_U128( 0x0000000000000000, 0x0000000000f58209 ) }, + { 0x1.283f1d32507e4p+23, 0x1.06daa0fe0db54p-447, INIT_U128( 0x0000000000000000, 0x0000000000941f8e ) }, + { 0x1.cf7790bd9eef2p+23, 0x1.22ebe99845d7dp-447, INIT_U128( 0x0000000000000000, 0x0000000000e7bbc8 ) }, + { 0x1.39fb1e1473f64p+24, 0x1.baafa729755f5p-263, INIT_U128( 0x0000000000000000, 0x000000000139fb1e ) }, + { 0x1.553510f0aa6a2p+24, 0x1.806a3d5d00d48p-263, INIT_U128( 0x0000000000000000, 0x0000000001553510 ) }, + { 0x1.876715390ece3p+24, 0x1.cdf668119becdp-263, INIT_U128( 0x0000000000000000, 0x0000000001876715 ) }, + { 0x1.11816ac62302ep+24, 0x1.5e8451ecbd08ap-263, INIT_U128( 0x0000000000000000, 0x000000000111816a ) }, + { 0x1.3e7e811e7cfdp+25, 0x1.2dc6a5685b8d4p-155, INIT_U128( 0x0000000000000000, 0x00000000027cfd02 ) }, + { 0x1.6ebc2c8cdd786p+25, 0x1.22f38cd645e72p-155, INIT_U128( 0x0000000000000000, 0x0000000002dd7859 ) }, + { 0x1.421ccf068439ap+25, 0x1.bef8b6f57df17p-155, INIT_U128( 0x0000000000000000, 0x000000000284399e ) }, + { 0x1.e10ee555c21dcp+25, 0x1.033cdd7a0679cp-155, INIT_U128( 0x0000000000000000, 0x0000000003c21dca ) }, + { 0x1.f0b6e7ede16ddp+26, 0x1.bc0a81517815p-634, INIT_U128( 0x0000000000000000, 0x0000000007c2db9f ) }, + { 0x1.f7b66dc5ef6cdp+26, 0x1.2bd3184a57a63p-634, INIT_U128( 0x0000000000000000, 0x0000000007ded9b7 ) }, + { 0x1.259706244b2e1p+26, 0x1.8b7dd07716fbap-634, INIT_U128( 0x0000000000000000, 0x0000000004965c18 ) }, + { 0x1.fdf5519ffbeaap+26, 0x1.19d4925433a92p-634, INIT_U128( 0x0000000000000000, 0x0000000007f7d546 ) }, + { 0x1.bb13b1d776276p+27, 0x1.e509cb23ca13ap-395, INIT_U128( 0x0000000000000000, 0x000000000dd89d8e ) }, + { 0x1.20754b2a40eaap+27, 0x1.bcc8cd6b7991ap-395, INIT_U128( 0x0000000000000000, 0x000000000903aa59 ) }, + { 0x1.dc036999b806dp+27, 0x1.62b438eec5687p-395, INIT_U128( 0x0000000000000000, 0x000000000ee01b4c ) }, + { 0x1.92b76e3d256eep+27, 0x1.33f6413067ec8p-395, INIT_U128( 0x0000000000000000, 0x000000000c95bb71 ) }, + { 0x1.7a6c4408f4d88p+28, 0x1.0f6d05b41edap-716, INIT_U128( 0x0000000000000000, 0x0000000017a6c440 ) }, + { 0x1.25d2c9ae4ba59p+28, 0x1.005f5a6a00becp-716, INIT_U128( 0x0000000000000000, 0x00000000125d2c9a ) }, + { 0x1.c8949d0b91293p+28, 0x1.6e7ca504dcf94p-716, INIT_U128( 0x0000000000000000, 0x000000001c8949d0 ) }, + { 0x1.21af1f7a435e4p+28, 0x1.98e05ef731c0cp-716, INIT_U128( 0x0000000000000000, 0x00000000121af1f7 ) }, + { 0x1.307b63f060f6cp+29, 0x1.17d4949a2fa92p-112, INIT_U128( 0x0000000000000000, 0x00000000260f6c7e ) }, + { 0x1.053d62740a7acp+29, 0x1.a8881e6551104p-112, INIT_U128( 0x0000000000000000, 0x0000000020a7ac4e ) }, + { 0x1.9b60d35b36c1ap+29, 0x1.005bb09600b76p-112, INIT_U128( 0x0000000000000000, 0x00000000336c1a6b ) }, + { 0x1.3ba73afe774e8p+29, 0x1.0efca74e1df95p-112, INIT_U128( 0x0000000000000000, 0x000000002774e75f ) }, + { 0x1.dd796675baf2dp+30, 0x1.aaba00775574p-990, INIT_U128( 0x0000000000000000, 0x00000000775e599d ) }, + { 0x1.8b282c8d16506p+30, 0x1.4e04f8449c09fp-990, INIT_U128( 0x0000000000000000, 0x0000000062ca0b23 ) }, + { 0x1.7d6ab930fad57p+30, 0x1.764a6e3cec94ep-990, INIT_U128( 0x0000000000000000, 0x000000005f5aae4c ) }, + { 0x1.6906027cd20cp+30, 0x1.d5b4ef4dab69ep-990, INIT_U128( 0x0000000000000000, 0x000000005a41809f ) }, + { 0x1.04a9da360953cp+31, 0x1.6c11a2e4d8234p-857, INIT_U128( 0x0000000000000000, 0x000000008254ed1b ) }, + { 0x1.fbba6e93f774ep+31, 0x1.0e9a6e5c1d34ep-857, INIT_U128( 0x0000000000000000, 0x00000000fddd3749 ) }, + { 0x1.380b108470162p+31, 0x1.65c0e5f6cb81cp-857, INIT_U128( 0x0000000000000000, 0x000000009c058842 ) }, + { 0x1.050dfc000a1cp+31, 0x1.1df2fc803be6p-857, INIT_U128( 0x0000000000000000, 0x000000008286fe00 ) }, + { 0x1.88bf9e1d117f4p+32, 0x1.8dd4aa1b1ba95p-126, INIT_U128( 0x0000000000000000, 0x0000000188bf9e1d ) }, + { 0x1.8b35d7ff166bbp+32, 0x1.91ca210923944p-126, INIT_U128( 0x0000000000000000, 0x000000018b35d7ff ) }, + { 0x1.286a366250d47p+32, 0x1.012c86ac02591p-126, INIT_U128( 0x0000000000000000, 0x00000001286a3662 ) }, + { 0x1.ef233cd5de467p+32, 0x1.2292a62645255p-126, INIT_U128( 0x0000000000000000, 0x00000001ef233cd5 ) }, + { 0x1.917a959722f53p+33, 0x1.85a7d93f0b4fbp-478, INIT_U128( 0x0000000000000000, 0x0000000322f52b2e ) }, + { 0x1.f630053bec6p+33, 0x1.f79a5227ef34bp-478, INIT_U128( 0x0000000000000000, 0x00000003ec600a77 ) }, + { 0x1.1a062b14340c6p+33, 0x1.21179acc422f4p-478, INIT_U128( 0x0000000000000000, 0x00000002340c5628 ) }, + { 0x1.d62acf15ac55ap+33, 0x1.bf1cd2697e39ap-478, INIT_U128( 0x0000000000000000, 0x00000003ac559e2b ) }, + { 0x1.823ddfaf047bcp+34, 0x1.e2d35df1c5a6cp-649, INIT_U128( 0x0000000000000000, 0x0000000608f77ebc ) }, + { 0x1.996ef6e332ddfp+34, 0x1.7af28278f5e5p-649, INIT_U128( 0x0000000000000000, 0x0000000665bbdb8c ) }, + { 0x1.81a2bfc703458p+34, 0x1.acc15cd15982cp-649, INIT_U128( 0x0000000000000000, 0x00000006068aff1c ) }, + { 0x1.4517e98e8a2fdp+34, 0x1.a3233fc546468p-649, INIT_U128( 0x0000000000000000, 0x00000005145fa63a ) }, + { 0x1.09f551a013eaap+35, 0x0.0000000000006p-1022, INIT_U128( 0x0000000000000000, 0x000000084faa8d00 ) }, + { 0x1.a2911b3d45224p+35, 0x0.0000000000005p-1022, INIT_U128( 0x0000000000000000, 0x0000000d1488d9ea ) }, + { 0x1.77a301deef46p+35, 0x0.0000000000008p-1022, INIT_U128( 0x0000000000000000, 0x0000000bbd180ef7 ) }, + { 0x1.f60ea85fec1d5p+35, 0x0.0000000000006p-1022, INIT_U128( 0x0000000000000000, 0x0000000fb07542ff ) }, + { 0x1.75c28ed8eb852p+36, 0x1.64300234c86p-938, INIT_U128( 0x0000000000000000, 0x000000175c28ed8e ) }, + { 0x1.394f8bae729f2p+36, 0x1.2119204042324p-938, INIT_U128( 0x0000000000000000, 0x0000001394f8bae7 ) }, + { 0x1.94d6bc7929ad8p+36, 0x1.4a8aa2aa95154p-938, INIT_U128( 0x0000000000000000, 0x000000194d6bc792 ) }, + { 0x1.1f519dcc3ea34p+36, 0x1.b4fbc9c969f79p-938, INIT_U128( 0x0000000000000000, 0x00000011f519dcc3 ) }, + { 0x1.bb2fb46f765f6p+37, 0x1.cd4047139a809p-718, INIT_U128( 0x0000000000000000, 0x0000003765f68dee ) }, + { 0x1.f80989d1f0131p+37, 0x1.c0546f4180a8ep-718, INIT_U128( 0x0000000000000000, 0x0000003f01313a3e ) }, + { 0x1.90be9171217d2p+37, 0x1.bcc6089d798c1p-718, INIT_U128( 0x0000000000000000, 0x0000003217d22e24 ) }, + { 0x1.37469d226e8d4p+37, 0x1.06aff8000d5ffp-718, INIT_U128( 0x0000000000000000, 0x00000026e8d3a44d ) }, + { 0x1.2e0114905c022p+38, 0x1.298bde145317cp-115, INIT_U128( 0x0000000000000000, 0x0000004b80452417 ) }, + { 0x1.77354c42ee6aap+38, 0x1.d9a75513b34eap-115, INIT_U128( 0x0000000000000000, 0x0000005dcd5310bb ) }, + { 0x1.0881a80c11035p+38, 0x1.44e5e01889cbcp-115, INIT_U128( 0x0000000000000000, 0x00000042206a0304 ) }, + { 0x1.a32b590f4656bp+38, 0x1.760fbd2eec1f8p-115, INIT_U128( 0x0000000000000000, 0x00000068cad643d1 ) }, + { 0x1.e7bc6861cf78dp+39, 0x1.72addca8e55bcp-767, INIT_U128( 0x0000000000000000, 0x000000f3de3430e7 ) }, + { 0x1.e1e11b1bc3c24p+39, 0x1.713729dae26e5p-767, INIT_U128( 0x0000000000000000, 0x000000f0f08d8de1 ) }, + { 0x1.8bbb377f17767p+39, 0x1.c296d213852dap-767, INIT_U128( 0x0000000000000000, 0x000000c5dd9bbf8b ) }, + { 0x1.7cb13d18f9628p+39, 0x1.8dcf87351b9f1p-767, INIT_U128( 0x0000000000000000, 0x000000be589e8c7c ) }, + { 0x1.1ddbaf383bb76p+40, 0x1.20c8d9d04191bp-497, INIT_U128( 0x0000000000000000, 0x0000011ddbaf383b ) }, + { 0x1.fde474e3fbc8ep+40, 0x1.7e6de35afcdbcp-497, INIT_U128( 0x0000000000000000, 0x000001fde474e3fb ) }, + { 0x1.02a202b00544p+40, 0x1.311b40f462368p-497, INIT_U128( 0x0000000000000000, 0x00000102a202b005 ) }, + { 0x1.ec0b6577d816cp+40, 0x1.8e49e85d1c93dp-497, INIT_U128( 0x0000000000000000, 0x000001ec0b6577d8 ) }, + { 0x1.95fa4b912bf4ap+41, 0x1.295d953652bb2p-872, INIT_U128( 0x0000000000000000, 0x0000032bf4972257 ) }, + { 0x1.fd243093fa486p+41, 0x1.91e0a45723c14p-872, INIT_U128( 0x0000000000000000, 0x000003fa486127f4 ) }, + { 0x1.d0beeb21a17dep+41, 0x1.97f98e272ff32p-872, INIT_U128( 0x0000000000000000, 0x000003a17dd64342 ) }, + { 0x1.750735faea0e6p+41, 0x1.97a4c8c92f499p-872, INIT_U128( 0x0000000000000000, 0x000002ea0e6bf5d4 ) }, + { 0x1.ab409c8f56814p+42, 0x1.1e820fc23d042p-84, INIT_U128( 0x0000000000000000, 0x000006ad02723d5a ) }, + { 0x1.85e79a910bcf3p+42, 0x1.75d44930eba89p-84, INIT_U128( 0x0000000000000000, 0x000006179e6a442f ) }, + { 0x1.e2fa47dfc5f49p+42, 0x1.f91c1067f2382p-84, INIT_U128( 0x0000000000000000, 0x0000078be91f7f17 ) }, + { 0x1.ecaf7567d95eep+42, 0x1.dd787be3baf1p-84, INIT_U128( 0x0000000000000000, 0x000007b2bdd59f65 ) }, + { 0x1.4fd770a89faeep+43, 0x1.883956a11072bp-669, INIT_U128( 0x0000000000000000, 0x00000a7ebb8544fd ) }, + { 0x1.b2b2aa2d65655p+43, 0x1.0c2516f2184a3p-669, INIT_U128( 0x0000000000000000, 0x00000d9595516b2b ) }, + { 0x1.5848b5b4b0916p+43, 0x1.d9a0d8cfb341bp-669, INIT_U128( 0x0000000000000000, 0x00000ac245ada584 ) }, + { 0x1.be7daa1f7cfb5p+43, 0x1.f0c9d223e193bp-669, INIT_U128( 0x0000000000000000, 0x00000df3ed50fbe7 ) }, + { 0x1.3f6d46f07eda9p+44, 0x1.3d2fa1b27a5f4p-539, INIT_U128( 0x0000000000000000, 0x000013f6d46f07ed ) }, + { 0x1.5eb8dcaebd71cp+44, 0x1.8e170e7b1c2e2p-539, INIT_U128( 0x0000000000000000, 0x000015eb8dcaebd7 ) }, + { 0x1.893b63631276cp+44, 0x1.9447ca53288f9p-539, INIT_U128( 0x0000000000000000, 0x00001893b6363127 ) }, + { 0x1.4e089b389c114p+44, 0x1.d191b053a3236p-539, INIT_U128( 0x0000000000000000, 0x000014e089b389c1 ) }, + { 0x1.2e36d90e5c6dbp+45, 0x1.314d394c629a7p-889, INIT_U128( 0x0000000000000000, 0x000025c6db21cb8d ) }, + { 0x1.7f784de4fef0ap+45, 0x1.5413e986a827dp-889, INIT_U128( 0x0000000000000000, 0x00002fef09bc9fde ) }, + { 0x1.74448388e889p+45, 0x1.752c3c2cea588p-889, INIT_U128( 0x0000000000000000, 0x00002e8890711d11 ) }, + { 0x1.ebb20c51d7641p+45, 0x1.50a52f7ca14a6p-889, INIT_U128( 0x0000000000000000, 0x00003d76418a3aec ) }, + { 0x1.4b51066896a21p+46, 0x1.d43cc973a8799p-550, INIT_U128( 0x0000000000000000, 0x000052d4419a25a8 ) }, + { 0x1.070f0d280e1e2p+46, 0x1.c25aa6dd84b55p-550, INIT_U128( 0x0000000000000000, 0x000041c3c34a0387 ) }, + { 0x1.7f735ca4fee6cp+46, 0x1.a92889d752511p-550, INIT_U128( 0x0000000000000000, 0x00005fdcd7293fb9 ) }, + { 0x1.72ed987ae5db3p+46, 0x1.fae14a03f5c29p-550, INIT_U128( 0x0000000000000000, 0x00005cbb661eb976 ) }, + { 0x1.7352fdf0e6a6p+47, 0x1.1a64275034c85p-857, INIT_U128( 0x0000000000000000, 0x0000b9a97ef87353 ) }, + { 0x1.9f4b98f33e973p+47, 0x1.657b10c0caf62p-857, INIT_U128( 0x0000000000000000, 0x0000cfa5cc799f4b ) }, + { 0x1.b12eb79b625d7p+47, 0x1.4826ca96904dap-857, INIT_U128( 0x0000000000000000, 0x0000d8975bcdb12e ) }, + { 0x1.6148cbcac291ap+47, 0x1.8672a1ad0ce54p-857, INIT_U128( 0x0000000000000000, 0x0000b0a465e56148 ) }, + { 0x1.1df8159e3bf02p+48, 0x1.7c6dbd68f8db8p-407, INIT_U128( 0x0000000000000000, 0x00011df8159e3bf0 ) }, + { 0x1.d8e17545b1c2ep+48, 0x1.959fcc5f2b3fap-407, INIT_U128( 0x0000000000000000, 0x0001d8e17545b1c2 ) }, + { 0x1.ea57e075d4afcp+48, 0x1.56705400ace0ap-407, INIT_U128( 0x0000000000000000, 0x0001ea57e075d4af ) }, + { 0x1.d2aa9e99a5554p+48, 0x1.9ebcab993d796p-407, INIT_U128( 0x0000000000000000, 0x0001d2aa9e99a555 ) }, + { 0x1.4fe075a49fc0ep+49, 0x1.e950f533d2a1ep-694, INIT_U128( 0x0000000000000000, 0x00029fc0eb493f81 ) }, + { 0x1.a936db51526dcp+49, 0x1.8a1397df14273p-694, INIT_U128( 0x0000000000000000, 0x0003526db6a2a4db ) }, + { 0x1.138ce7682719dp+49, 0x1.7f879c76ff0f4p-694, INIT_U128( 0x0000000000000000, 0x00022719ced04e33 ) }, + { 0x1.21e981b043d3p+49, 0x1.eaefe1f3d5dfcp-694, INIT_U128( 0x0000000000000000, 0x000243d3036087a6 ) }, + { 0x1.793e9a3cf27d4p+50, 0x1.40169b90802d4p-934, INIT_U128( 0x0000000000000000, 0x0005e4fa68f3c9f5 ) }, + { 0x1.7e1caadcfc396p+50, 0x1.371020466e204p-934, INIT_U128( 0x0000000000000000, 0x0005f872ab73f0e5 ) }, + { 0x1.33a019d667403p+50, 0x1.9c77f7cb38effp-934, INIT_U128( 0x0000000000000000, 0x0004ce8067599d00 ) }, + { 0x1.b4966ecb692cep+50, 0x1.c4dd0f8989ba2p-934, INIT_U128( 0x0000000000000000, 0x0006d259bb2da4b3 ) }, + { 0x1.822ad9630455bp+51, 0x1.3fade6a07f5bdp-561, INIT_U128( 0x0000000000000000, 0x000c1156cb1822ad ) }, + { 0x1.3a77dd3c74efcp+51, 0x1.55dd3018abba6p-561, INIT_U128( 0x0000000000000000, 0x0009d3bee9e3a77e ) }, + { 0x1.d375773da6eafp+51, 0x1.ad40b9955a817p-561, INIT_U128( 0x0000000000000000, 0x000e9babb9ed3757 ) }, + { 0x1.16059bfe2c0b4p+51, 0x1.ff801c63ff003p-561, INIT_U128( 0x0000000000000000, 0x0008b02cdff1605a ) }, + { 0x1.af8f1e955f1e4p+52, 0x1.2c4cc4fa58998p-237, INIT_U128( 0x0000000000000000, 0x001af8f1e955f1e4 ) }, + { 0x1.579e5322af3cap+52, 0x1.e9974457d32e8p-237, INIT_U128( 0x0000000000000000, 0x001579e5322af3ca ) }, + { 0x1.2b9d921a573b2p+52, 0x1.d8798265b0f3p-237, INIT_U128( 0x0000000000000000, 0x0012b9d921a573b2 ) }, + { 0x1.b746d5596e8dbp+52, 0x1.a75bfc954eb8p-237, INIT_U128( 0x0000000000000000, 0x001b746d5596e8db ) }, + { 0x1.497ec4f092fd8p+53, 0x1.5c597ab2b8b3p-364, INIT_U128( 0x0000000000000000, 0x00292fd89e125fb0 ) }, + { 0x1.8a65536914caap+53, 0x1.958565492b0adp-364, INIT_U128( 0x0000000000000000, 0x00314caa6d229954 ) }, + { 0x1.11b7146c236e2p+53, 0x1.3154f5b662a9ep-364, INIT_U128( 0x0000000000000000, 0x002236e28d846dc4 ) }, + { 0x1.f71b5e7bee36cp+53, 0x1.efc7aa5ddf8f6p-364, INIT_U128( 0x0000000000000000, 0x003ee36bcf7dc6d8 ) }, + { 0x1.5a71157ab4e22p+54, 0x1.b4fd1c6b69fa4p-39, INIT_U128( 0x0000000000000000, 0x00569c455ead3888 ) }, + { 0x1.4ab52e26956a6p+54, 0x1.204833ee40906p-39, INIT_U128( 0x0000000000000000, 0x0052ad4b89a55a98 ) }, + { 0x1.7b9298b4f7253p+54, 0x1.084ca6f410995p-39, INIT_U128( 0x0000000000000000, 0x005ee4a62d3dc94c ) }, + { 0x1.8be06c0317c0ep+54, 0x1.9677f6df2ceffp-39, INIT_U128( 0x0000000000000000, 0x0062f81b00c5f038 ) }, + { 0x1.53534daca6a6ap+55, 0x1.af26be6f5e4d8p-905, INIT_U128( 0x0000000000000000, 0x00a9a9a6d6535350 ) }, + { 0x1.ee7424c1dce84p+55, 0x1.38a375387146ep-905, INIT_U128( 0x0000000000000000, 0x00f73a1260ee7420 ) }, + { 0x1.4275718484eaep+55, 0x1.693f342ed27e6p-905, INIT_U128( 0x0000000000000000, 0x00a13ab8c2427570 ) }, + { 0x1.4e48bc049c918p+55, 0x1.30d3b39661a76p-905, INIT_U128( 0x0000000000000000, 0x00a7245e024e48c0 ) }, + { 0x1.6fcb01f0df96p+56, 0x1.f3322f93e6646p-339, INIT_U128( 0x0000000000000000, 0x016fcb01f0df9600 ) }, + { 0x1.6f16f2e4de2dep+56, 0x1.b50cb2d16a196p-339, INIT_U128( 0x0000000000000000, 0x016f16f2e4de2de0 ) }, + { 0x1.6fcb3cb2df968p+56, 0x1.f7623e45eec48p-339, INIT_U128( 0x0000000000000000, 0x016fcb3cb2df9680 ) }, + { 0x1.a41a78314834fp+56, 0x1.ee812a93dd026p-339, INIT_U128( 0x0000000000000000, 0x01a41a78314834f0 ) }, + { 0x1.73544f7ce6a8ap+57, 0x1.fbf6a069f7ed4p-786, INIT_U128( 0x0000000000000000, 0x02e6a89ef9cd5140 ) }, + { 0x1.8d4beb3f1a97ep+57, 0x1.6f6e15a0dedc2p-786, INIT_U128( 0x0000000000000000, 0x031a97d67e352fc0 ) }, + { 0x1.70dfc328e1bf8p+57, 0x1.56963a34ad2c8p-786, INIT_U128( 0x0000000000000000, 0x02e1bf8651c37f00 ) }, + { 0x1.6e5e39acdcbc7p+57, 0x1.62dfb7d4c5bf7p-786, INIT_U128( 0x0000000000000000, 0x02dcbc7359b978e0 ) }, + { 0x1.10a375142146ep+58, 0x1.dde963f1bbd2cp-687, INIT_U128( 0x0000000000000000, 0x04428dd450851b80 ) }, + { 0x1.7eacb1acfd596p+58, 0x1.e59952a9cb32bp-687, INIT_U128( 0x0000000000000000, 0x05fab2c6b3f56580 ) }, + { 0x1.3f2bac4a7e576p+58, 0x1.d21ee367a43ddp-687, INIT_U128( 0x0000000000000000, 0x04fcaeb129f95d80 ) }, + { 0x1.be738acb7ce71p+58, 0x1.d4b6334fa96c7p-687, INIT_U128( 0x0000000000000000, 0x06f9ce2b2df39c40 ) }, + { 0x1.b322eff56645ep+59, 0x0.00000014b8158p-1022, INIT_U128( 0x0000000000000000, 0x0d99177fab322f00 ) }, + { 0x1.b8dfbdbd71bf8p+59, 0x0.00000010ac2d6p-1022, INIT_U128( 0x0000000000000000, 0x0dc6fdedeb8dfc00 ) }, + { 0x1.e45f6d33c8bedp+59, 0x0.0000001c79003p-1022, INIT_U128( 0x0000000000000000, 0x0f22fb699e45f680 ) }, + { 0x1.10c7106e218e2p+59, 0x0.0000001ea2457p-1022, INIT_U128( 0x0000000000000000, 0x08863883710c7100 ) }, + { 0x1.c48c230989185p+60, 0x1.a60d3fb34c1a8p-116, INIT_U128( 0x0000000000000000, 0x1c48c23098918500 ) }, + { 0x1.5e9345fabd268p+60, 0x1.4898e6d49131dp-116, INIT_U128( 0x0000000000000000, 0x15e9345fabd26800 ) }, + { 0x1.b56942576ad28p+60, 0x1.aff4a0655fe94p-116, INIT_U128( 0x0000000000000000, 0x1b56942576ad2800 ) }, + { 0x1.7f865930ff0cbp+60, 0x1.13a0876e27411p-116, INIT_U128( 0x0000000000000000, 0x17f865930ff0cb00 ) }, + { 0x1.ef482c31de906p+61, 0x1.43e655d887ccap-501, INIT_U128( 0x0000000000000000, 0x3de905863bd20c00 ) }, + { 0x1.9fa15a7d3f42bp+61, 0x1.b00fcc55601fap-501, INIT_U128( 0x0000000000000000, 0x33f42b4fa7e85600 ) }, + { 0x1.d2c465fda588dp+61, 0x1.98c2f6e73185fp-501, INIT_U128( 0x0000000000000000, 0x3a588cbfb4b11a00 ) }, + { 0x1.f038608de070cp+61, 0x1.7b4fa8a0f69f5p-501, INIT_U128( 0x0000000000000000, 0x3e070c11bc0e1800 ) }, + { 0x1.adfb2db35bf66p+62, 0x1.38efaf6271df6p+8, INIT_U128( 0x0000000000000000, 0x6b7ecb6cd6fd9938 ) }, + { 0x1.1679474c2cf29p+62, 0x1.ae04d7f95c09bp+8, INIT_U128( 0x0000000000000000, 0x459e51d30b3ca5ae ) }, + { 0x1.890c63b91218cp+62, 0x1.133030ac26606p+8, INIT_U128( 0x0000000000000000, 0x624318ee44863113 ) }, + { 0x1.08fc576811f8bp+62, 0x1.521d194ea43a3p+8, INIT_U128( 0x0000000000000000, 0x423f15da047e2d52 ) }, + { 0x1.5c2e1ea2b85c4p+63, 0x1.bbf1e79d77e3dp-836, INIT_U128( 0x0000000000000000, 0xae170f515c2e2000 ) }, + { 0x1.3a1d0742743a1p+63, 0x1.849ecbad093dap-836, INIT_U128( 0x0000000000000000, 0x9d0e83a13a1d0800 ) }, + { 0x1.ac698c2758d32p+63, 0x1.7a316edaf462ep-836, INIT_U128( 0x0000000000000000, 0xd634c613ac699000 ) }, + { 0x1.8542412f0a848p+63, 0x1.a53fa9cd4a7f5p-836, INIT_U128( 0x0000000000000000, 0xc2a1209785424000 ) }, + { 0x1.f526fb77ea4ep+64, 0x1.170327882e065p-848, INIT_U128( 0x0000000000000001, 0xf526fb77ea4e0000 ) }, + { 0x1.acca54155994ap+64, 0x1.4c44fdb4988ap-848, INIT_U128( 0x0000000000000001, 0xacca54155994a000 ) }, + { 0x1.b47ed77768fdbp+64, 0x1.e6883245cd107p-848, INIT_U128( 0x0000000000000001, 0xb47ed77768fdb000 ) }, + { 0x1.bf32165b7e643p+64, 0x1.7da93100fb526p-848, INIT_U128( 0x0000000000000001, 0xbf32165b7e643000 ) }, + { 0x1.c6aa72a58d54fp+65, 0x1.700d04ece01ap-810, INIT_U128( 0x0000000000000003, 0x8d54e54b1aa9e000 ) }, + { 0x1.651ffffcca4p+65, 0x1.b6e3b8e56dc77p-810, INIT_U128( 0x0000000000000002, 0xca3ffff994800000 ) }, + { 0x1.f59076c9eb20fp+65, 0x1.41622b1082c46p-810, INIT_U128( 0x0000000000000003, 0xeb20ed93d641e000 ) }, + { 0x1.2362224a46c44p+65, 0x1.0fe4f0321fc9ep-810, INIT_U128( 0x0000000000000002, 0x46c444948d888000 ) }, + { 0x1.96643d852cc88p+66, 0x1.5aadaff0b55b6p-820, INIT_U128( 0x0000000000000006, 0x5990f614b3220000 ) }, + { 0x1.38a95f0e7152cp+66, 0x1.8432d89b0865bp-820, INIT_U128( 0x0000000000000004, 0xe2a57c39c54b0000 ) }, + { 0x1.b674a85b6ce95p+66, 0x1.3adbee1a75b7ep-820, INIT_U128( 0x0000000000000006, 0xd9d2a16db3a54000 ) }, + { 0x1.81b2bc3303658p+66, 0x1.0e771c4e1cee4p-820, INIT_U128( 0x0000000000000006, 0x06caf0cc0d960000 ) }, + { 0x1.017e066002fc1p+67, 0x1.69eb9d80d3d74p-860, INIT_U128( 0x0000000000000008, 0x0bf0330017e08000 ) }, + { 0x1.b75b9b136eb74p+67, 0x1.ddf2ec69bbe5ep-860, INIT_U128( 0x000000000000000d, 0xbadcd89b75ba0000 ) }, + { 0x1.71432fe4e2866p+67, 0x1.cbea0a3797d41p-860, INIT_U128( 0x000000000000000b, 0x8a197f2714330000 ) }, + { 0x1.65e3ce88cbc7ap+67, 0x1.dd466e4dba8cep-860, INIT_U128( 0x000000000000000b, 0x2f1e74465e3d0000 ) }, + { 0x1.d76842dfaed09p+68, 0x1.d4739f6ba8e74p-740, INIT_U128( 0x000000000000001d, 0x76842dfaed090000 ) }, + { 0x1.9180cb312301ap+68, 0x1.5961b442b2c36p-740, INIT_U128( 0x0000000000000019, 0x180cb312301a0000 ) }, + { 0x1.5ea7abd8bd4f6p+68, 0x1.0afd825415fbp-740, INIT_U128( 0x0000000000000015, 0xea7abd8bd4f60000 ) }, + { 0x1.bcf6493f79ec9p+68, 0x1.39f6643a73eccp-740, INIT_U128( 0x000000000000001b, 0xcf6493f79ec90000 ) }, + { 0x1.6c264bbad84cap+69, 0x1.3d2b92de7a572p-358, INIT_U128( 0x000000000000002d, 0x84c9775b09940000 ) }, + { 0x1.13b3e09a2767cp+69, 0x1.a3ead92f47d5bp-358, INIT_U128( 0x0000000000000022, 0x767c1344ecf80000 ) }, + { 0x1.8518219d0a304p+69, 0x1.c9a99edf93534p-358, INIT_U128( 0x0000000000000030, 0xa30433a146080000 ) }, + { 0x1.afa032e75f406p+69, 0x1.76f3e70cede7dp-358, INIT_U128( 0x0000000000000035, 0xf4065cebe80c0000 ) }, + { 0x1.1aa2f5343545ep+70, 0x1.cd612ccd9ac25p-491, INIT_U128( 0x0000000000000046, 0xa8bd4d0d51780000 ) }, + { 0x1.2c8c2e1a59186p+70, 0x1.53ac1260a7582p-491, INIT_U128( 0x000000000000004b, 0x230b869646180000 ) }, + { 0x1.b92d16ef725a3p+70, 0x1.05faddde0bf5cp-491, INIT_U128( 0x000000000000006e, 0x4b45bbdc968c0000 ) }, + { 0x1.9fc802a33f9p+70, 0x1.203a627a4074cp-491, INIT_U128( 0x0000000000000067, 0xf200a8cfe4000000 ) }, + { 0x1.240746b6480e9p+71, 0x1.78c39518f1872p-676, INIT_U128( 0x0000000000000092, 0x03a35b2407480000 ) }, + { 0x1.863a24750c744p+71, 0x1.96d2b31d2da56p-676, INIT_U128( 0x00000000000000c3, 0x1d123a863a200000 ) }, + { 0x1.597fbe8ab2ff8p+71, 0x1.93afb023275f6p-676, INIT_U128( 0x00000000000000ac, 0xbfdf45597fc00000 ) }, + { 0x1.e1080a67c2102p+71, 0x1.b5c9f2a36b93ep-676, INIT_U128( 0x00000000000000f0, 0x840533e108100000 ) }, + { 0x1.5c1897a6b8313p+72, 0x1.e08b1a6fc1164p-272, INIT_U128( 0x000000000000015c, 0x1897a6b831300000 ) }, + { 0x1.9ba232cf37446p+72, 0x1.5f66bf90becd8p-272, INIT_U128( 0x000000000000019b, 0xa232cf3744600000 ) }, + { 0x1.595f744cb2beep+72, 0x1.f7a95a67ef52cp-272, INIT_U128( 0x0000000000000159, 0x5f744cb2bee00000 ) }, + { 0x1.a763ae594ec76p+72, 0x1.c295524f852aap-272, INIT_U128( 0x00000000000001a7, 0x63ae594ec7600000 ) }, + { 0x1.06eca6c40dd95p+73, 0x1.f918431ff2309p-572, INIT_U128( 0x000000000000020d, 0xd94d881bb2a00000 ) }, + { 0x1.4f9fc82a9f3f9p+73, 0x1.257089f24ae11p-572, INIT_U128( 0x000000000000029f, 0x3f90553e7f200000 ) }, + { 0x1.0fa3bdc41f478p+73, 0x1.1ca9162039523p-572, INIT_U128( 0x000000000000021f, 0x477b883e8f000000 ) }, + { 0x1.be3be7ef7c77dp+73, 0x1.ae73d50d5ce7bp-572, INIT_U128( 0x000000000000037c, 0x77cfdef8efa00000 ) }, + { 0x1.da6d4389b4da8p+74, 0x1.1806570a300cbp-230, INIT_U128( 0x0000000000000769, 0xb50e26d36a000000 ) }, + { 0x1.55276624aa4edp+74, 0x1.004fb390009f6p-230, INIT_U128( 0x0000000000000554, 0x9d9892a93b400000 ) }, + { 0x1.aeab3c995d568p+74, 0x1.08d9156011b22p-230, INIT_U128( 0x00000000000006ba, 0xacf265755a000000 ) }, + { 0x1.a281549f4502ap+74, 0x1.cb98cbdf9731ap-230, INIT_U128( 0x000000000000068a, 0x05527d140a800000 ) }, + { 0x1.35dae4746bb5cp+75, 0x1.492edd3c925dcp-684, INIT_U128( 0x00000000000009ae, 0xd723a35dae000000 ) }, + { 0x1.e6b8db83cd71cp+75, 0x1.e8282f8fd0506p-684, INIT_U128( 0x0000000000000f35, 0xc6dc1e6b8e000000 ) }, + { 0x1.17587f082eb1p+75, 0x1.45ebb9f28bd77p-684, INIT_U128( 0x00000000000008ba, 0xc3f8417588000000 ) }, + { 0x1.957ac7292af59p+75, 0x1.35b408566b681p-684, INIT_U128( 0x0000000000000cab, 0xd6394957ac800000 ) }, + { 0x1.6e0e0850dc1c1p+76, 0x1.9e623e393cc48p-1002, INIT_U128( 0x00000000000016e0, 0xe0850dc1c1000000 ) }, + { 0x1.90fee6ff21fddp+76, 0x1.7ceca2caf9d94p-1002, INIT_U128( 0x000000000000190f, 0xee6ff21fdd000000 ) }, + { 0x1.5798708eaf30ep+76, 0x1.d3322f4fa6646p-1002, INIT_U128( 0x0000000000001579, 0x8708eaf30e000000 ) }, + { 0x1.c2ef5f4185decp+76, 0x1.96ad4d692d5aap-1002, INIT_U128( 0x0000000000001c2e, 0xf5f4185dec000000 ) }, + { 0x1.ae14b81f5c297p+77, 0x1.062f208c0c5e4p-169, INIT_U128( 0x00000000000035c2, 0x9703eb852e000000 ) }, + { 0x1.1f2ef58a3e5dep+77, 0x1.97a029192f405p-169, INIT_U128( 0x00000000000023e5, 0xdeb147cbbc000000 ) }, + { 0x1.74861d64e90c4p+77, 0x1.fb289c69f6513p-169, INIT_U128( 0x0000000000002e90, 0xc3ac9d2188000000 ) }, + { 0x1.11782bc422f06p+77, 0x1.fe294db5fc529p-169, INIT_U128( 0x000000000000222f, 0x0578845e0c000000 ) }, + { 0x1.3af34bd275e6ap+78, 0x1.ba66054574cc1p-910, INIT_U128( 0x0000000000004ebc, 0xd2f49d79a8000000 ) }, + { 0x1.0708e3fc0e11cp+78, 0x1.09ae142c135c2p-910, INIT_U128( 0x00000000000041c2, 0x38ff038470000000 ) }, + { 0x1.c313a69786275p+78, 0x1.fc165a27f82ccp-910, INIT_U128( 0x00000000000070c4, 0xe9a5e189d4000000 ) }, + { 0x1.990c9ad532193p+78, 0x1.072499060e493p-910, INIT_U128( 0x0000000000006643, 0x26b54c864c000000 ) }, + { 0x1.dd2363c1ba46cp+79, 0x1.d163c99ba2c79p-815, INIT_U128( 0x000000000000ee91, 0xb1e0dd2360000000 ) }, + { 0x1.b0ae4ad1615c9p+79, 0x1.8f2f90f91e5f2p-815, INIT_U128( 0x000000000000d857, 0x2568b0ae48000000 ) }, + { 0x1.9a26bbb7344d8p+79, 0x1.ed90d6d9db21bp-815, INIT_U128( 0x000000000000cd13, 0x5ddb9a26c0000000 ) }, + { 0x1.71ec17ace3d83p+79, 0x1.ec2b79cfd856fp-815, INIT_U128( 0x000000000000b8f6, 0x0bd671ec18000000 ) }, + { 0x1.689f9cb2d13f4p+80, 0x1.adfbd9175bf7bp-935, INIT_U128( 0x000000000001689f, 0x9cb2d13f40000000 ) }, + { 0x1.cde2888d9bc51p+80, 0x1.0d3598f01a6b3p-935, INIT_U128( 0x000000000001cde2, 0x888d9bc510000000 ) }, + { 0x1.6866c948d0cd9p+80, 0x1.0d9da3cc1b3b4p-935, INIT_U128( 0x0000000000016866, 0xc948d0cd90000000 ) }, + { 0x1.eee79cbdddcf3p+80, 0x1.a60bf9374c17fp-935, INIT_U128( 0x000000000001eee7, 0x9cbdddcf30000000 ) }, + { 0x1.3a27b29c744f6p+81, 0x1.1270039224ep-231, INIT_U128( 0x000000000002744f, 0x6538e89ec0000000 ) }, + { 0x1.608a6c38c114ep+81, 0x1.a6ff1b154dfe4p-231, INIT_U128( 0x000000000002c114, 0xd8718229c0000000 ) }, + { 0x1.b8ddf2c971bbep+81, 0x1.7a6c452cf4d88p-231, INIT_U128( 0x00000000000371bb, 0xe592e377c0000000 ) }, + { 0x1.34056f04680aep+81, 0x1.3aa39ba075474p-231, INIT_U128( 0x000000000002680a, 0xde08d015c0000000 ) }, + { 0x1.df36567dbe6cbp+82, 0x1.948aa54b29155p-104, INIT_U128( 0x0000000000077cd9, 0x59f6f9b2c0000000 ) }, + { 0x1.00c5bf20018b8p+82, 0x1.0354f44e06a9ep-104, INIT_U128( 0x0000000000040316, 0xfc80062e00000000 ) }, + { 0x1.5a6d471ab4da9p+82, 0x1.ea755ca5d4eabp-104, INIT_U128( 0x00000000000569b5, 0x1c6ad36a40000000 ) }, + { 0x1.58acff6eb15ap+82, 0x1.f6c3b1b9ed876p-104, INIT_U128( 0x00000000000562b3, 0xfdbac56800000000 ) }, + { 0x1.9288c20b25118p+83, 0x1.477be5208ef7cp-445, INIT_U128( 0x00000000000c9446, 0x1059288c00000000 ) }, + { 0x1.3556fa5c6aaep+83, 0x1.f200a591e4014p-445, INIT_U128( 0x000000000009aab7, 0xd2e3557000000000 ) }, + { 0x1.88dec0dd11bd8p+83, 0x1.a1ceac19439d6p-445, INIT_U128( 0x00000000000c46f6, 0x06e88dec00000000 ) }, + { 0x1.603498e4c0693p+83, 0x1.94ccf0d52999ep-445, INIT_U128( 0x00000000000b01a4, 0xc726034980000000 ) }, + { 0x1.1dfbb7a43bf77p+84, 0x1.d7dd8bdbafbb2p-926, INIT_U128( 0x000000000011dfbb, 0x7a43bf7700000000 ) }, + { 0x1.5f5d18b8beba3p+84, 0x1.ac1b923558372p-926, INIT_U128( 0x000000000015f5d1, 0x8b8beba300000000 ) }, + { 0x1.8b32b85d16657p+84, 0x1.37ae11cc6f5c2p-926, INIT_U128( 0x000000000018b32b, 0x85d1665700000000 ) }, + { 0x1.506f56eca0debp+84, 0x1.185445da30a88p-926, INIT_U128( 0x00000000001506f5, 0x6eca0deb00000000 ) }, + { 0x1.506cf3dea0d9ep+85, 0x1.2e68e2945cd1cp-635, INIT_U128( 0x00000000002a0d9e, 0x7bd41b3c00000000 ) }, + { 0x1.99ef268733de5p+85, 0x1.2ce0960e59c13p-635, INIT_U128( 0x0000000000333de4, 0xd0e67bca00000000 ) }, + { 0x1.d46cd273a8d9ap+85, 0x1.fb0bae61f6176p-635, INIT_U128( 0x00000000003a8d9a, 0x4e751b3400000000 ) }, + { 0x1.31deaa8263bd6p+85, 0x1.8a752b4514ea6p-635, INIT_U128( 0x0000000000263bd5, 0x504c77ac00000000 ) }, + { 0x1.95956f032b2aep+86, 0x1.ddd18753bba31p-535, INIT_U128( 0x000000000065655b, 0xc0cacab800000000 ) }, + { 0x1.db4b6705b696dp+86, 0x1.fc438061f887p-535, INIT_U128( 0x000000000076d2d9, 0xc16da5b400000000 ) }, + { 0x1.42c9320885926p+86, 0x1.9258f3ab24b1ep-535, INIT_U128( 0x000000000050b24c, 0x8221649800000000 ) }, + { 0x1.08ca2a0e11946p+86, 0x1.1c860974390c1p-535, INIT_U128( 0x000000000042328a, 0x8384651800000000 ) }, + { 0x1.ddf27f51bbe5p+87, 0x1.a776e8c94eeddp-479, INIT_U128( 0x0000000000eef93f, 0xa8ddf28000000000 ) }, + { 0x1.3f5b6af47eb6ep+87, 0x1.cf47dd9d9e8fcp-479, INIT_U128( 0x00000000009fadb5, 0x7a3f5b7000000000 ) }, + { 0x1.4b9d6480973acp+87, 0x1.c249100d84922p-479, INIT_U128( 0x0000000000a5ceb2, 0x404b9d6000000000 ) }, + { 0x1.eea053a5dd40bp+87, 0x1.26e6f8d24dcdfp-479, INIT_U128( 0x0000000000f75029, 0xd2eea05800000000 ) }, + { 0x1.4e0a84329c15p+88, 0x1.b969043772d2p-931, INIT_U128( 0x00000000014e0a84, 0x329c150000000000 ) }, + { 0x1.20fcf75c41f9fp+88, 0x1.a487f5bf490ffp-931, INIT_U128( 0x000000000120fcf7, 0x5c41f9f000000000 ) }, + { 0x1.0937a468126f4p+88, 0x1.dd15685bba2adp-931, INIT_U128( 0x00000000010937a4, 0x68126f4000000000 ) }, + { 0x1.3a1b94d674372p+88, 0x1.0e98a7441d315p-931, INIT_U128( 0x00000000013a1b94, 0xd674372000000000 ) }, + { 0x1.b9b702f1736ep+89, 0x1.afdf8f8b5fbf2p-758, INIT_U128( 0x0000000003736e05, 0xe2e6dc0000000000 ) }, + { 0x1.f93973b7f272fp+89, 0x1.77696130eed2cp-758, INIT_U128( 0x0000000003f272e7, 0x6fe4e5e000000000 ) }, + { 0x1.85595b3b0ab2cp+89, 0x1.4c1c459298388p-758, INIT_U128( 0x00000000030ab2b6, 0x7615658000000000 ) }, + { 0x1.89e4ed0b13c9ep+89, 0x1.4c88ddd89911cp-758, INIT_U128( 0x000000000313c9da, 0x162793c000000000 ) }, + { 0x1.6d0dfe6ada1cp+90, 0x1.0873b16610e76p+20, INIT_U128( 0x0000000005b437f9, 0xab6870000010873b ) }, + { 0x1.403e37e4807c7p+90, 0x1.630feeecc61fep+20, INIT_U128( 0x000000000500f8df, 0x9201f1c0001630fe ) }, + { 0x1.1d3cdade3a79cp+90, 0x1.ecceb30bd99d7p+20, INIT_U128( 0x000000000474f36b, 0x78e9e700001ecceb ) }, + { 0x1.f50698adea0d3p+90, 0x1.4ed5f3749dabep+20, INIT_U128( 0x0000000007d41a62, 0xb7a834c00014ed5f ) }, + { 0x1.d869b87fb0d37p+91, 0x1.53d108a0a7a21p-525, INIT_U128( 0x000000000ec34dc3, 0xfd869b8000000000 ) }, + { 0x1.cd078fb39a0f2p+91, 0x1.228b56084516bp-525, INIT_U128( 0x000000000e683c7d, 0x9cd0790000000000 ) }, + { 0x1.c67dbd798cfb7p+91, 0x1.65e1ed28cbc3ep-525, INIT_U128( 0x000000000e33edeb, 0xcc67db8000000000 ) }, + { 0x1.c41a2ed388346p+91, 0x1.4799717a8f32ep-525, INIT_U128( 0x000000000e20d176, 0x9c41a30000000000 ) }, + { 0x1.db416739b682dp+92, 0x1.fea650affd4cap-706, INIT_U128( 0x000000001db41673, 0x9b682d0000000000 ) }, + { 0x1.872189f10e431p+92, 0x1.e1de445fc3bc8p-706, INIT_U128( 0x000000001872189f, 0x10e4310000000000 ) }, + { 0x1.d2ad0fd1a55a2p+92, 0x1.0a06ac7e140d6p-706, INIT_U128( 0x000000001d2ad0fd, 0x1a55a20000000000 ) }, + { 0x1.2535c3a84a6b8p+92, 0x1.65205312ca40ap-706, INIT_U128( 0x0000000012535c3a, 0x84a6b80000000000 ) }, + { 0x1.dd518ce9baa31p+93, 0x1.b123211362464p-663, INIT_U128( 0x000000003baa319d, 0x3754620000000000 ) }, + { 0x1.9a89da733513bp+93, 0x1.8c0a0b2b18142p-663, INIT_U128( 0x0000000033513b4e, 0x66a2760000000000 ) }, + { 0x1.01fc693203f8dp+93, 0x1.81040a6d02081p-663, INIT_U128( 0x00000000203f8d26, 0x407f1a0000000000 ) }, + { 0x1.1d9ae72e3b35dp+93, 0x1.fb816ce9f702dp-663, INIT_U128( 0x0000000023b35ce5, 0xc766ba0000000000 ) }, + { 0x1.1b8311c037062p+94, 0x1.3b413a6c76828p-946, INIT_U128( 0x0000000046e0c470, 0x0dc1880000000000 ) }, + { 0x1.e7c1239fcf825p+94, 0x1.e89cbe61d1398p-946, INIT_U128( 0x0000000079f048e7, 0xf3e0940000000000 ) }, + { 0x1.3ba2c92677459p+94, 0x1.4c19bb4098338p-946, INIT_U128( 0x000000004ee8b249, 0x9dd1640000000000 ) }, + { 0x1.e81787a3d02f1p+94, 0x1.21981a6a43304p-946, INIT_U128( 0x000000007a05e1e8, 0xf40bc40000000000 ) }, + { 0x1.e18ca9a3c3195p+95, 0x1.d2ce473ba59c9p-353, INIT_U128( 0x00000000f0c654d1, 0xe18ca80000000000 ) }, + { 0x1.ec1a5457d834ap+95, 0x1.673af5f4ce75ep-353, INIT_U128( 0x00000000f60d2a2b, 0xec1a500000000000 ) }, + { 0x1.3d4fcc727a9fap+95, 0x1.d577142daaee2p-353, INIT_U128( 0x000000009ea7e639, 0x3d4fd00000000000 ) }, + { 0x1.6b318358d663p+95, 0x1.d96b9445b2d72p-353, INIT_U128( 0x00000000b598c1ac, 0x6b31800000000000 ) }, + { 0x1.f8fedfa1f1fdcp+96, 0x1.6e54dd28dca9cp-828, INIT_U128( 0x00000001f8fedfa1, 0xf1fdc00000000000 ) }, + { 0x1.4b5ec85896bd9p+96, 0x1.e4251105c84a2p-828, INIT_U128( 0x000000014b5ec858, 0x96bd900000000000 ) }, + { 0x1.bc8f0397791ep+96, 0x1.b514998d6a293p-828, INIT_U128( 0x00000001bc8f0397, 0x791e000000000000 ) }, + { 0x1.056a2dfe0ad46p+96, 0x1.c98d1a15931a3p-828, INIT_U128( 0x00000001056a2dfe, 0x0ad4600000000000 ) }, + { 0x1.21192da842326p+97, 0x1.64dbdea4c9b7cp-314, INIT_U128( 0x0000000242325b50, 0x8464c00000000000 ) }, + { 0x1.95c269f12b84dp+97, 0x1.31bfb62e637f7p-314, INIT_U128( 0x000000032b84d3e2, 0x5709a00000000000 ) }, + { 0x1.f4a37e69e947p+97, 0x1.2c5cc8d658b99p-314, INIT_U128( 0x00000003e946fcd3, 0xd28e000000000000 ) }, + { 0x1.73c765e6e78ecp+97, 0x1.34b3a3f469674p-314, INIT_U128( 0x00000002e78ecbcd, 0xcf1d800000000000 ) }, + { 0x1.cafa773f95f4fp+98, 0x1.28d3338851a66p-207, INIT_U128( 0x000000072be9dcfe, 0x57d3c00000000000 ) }, + { 0x1.7b7b6aa4f6f6ep+98, 0x1.2c99252259324p-207, INIT_U128( 0x00000005ededaa93, 0xdbdb800000000000 ) }, + { 0x1.8c39a15918734p+98, 0x1.cdcd60b79b9acp-207, INIT_U128( 0x0000000630e68564, 0x61cd000000000000 ) }, + { 0x1.da220eb5b4442p+98, 0x1.cd0b52b19a16bp-207, INIT_U128( 0x0000000768883ad6, 0xd110800000000000 ) }, + { 0x1.0f34e6fa1e69dp+99, 0x1.596be5d4b2d7cp-575, INIT_U128( 0x0000000879a737d0, 0xf34e800000000000 ) }, + { 0x1.5318af1aa6316p+99, 0x1.b2d7a70f65af5p-575, INIT_U128( 0x0000000a98c578d5, 0x318b000000000000 ) }, + { 0x1.2f3f14005e7e2p+99, 0x1.bf1a11977e342p-575, INIT_U128( 0x0000000979f8a002, 0xf3f1000000000000 ) }, + { 0x1.c95da71792bb5p+99, 0x1.b673d5896ce7bp-575, INIT_U128( 0x0000000e4aed38bc, 0x95da800000000000 ) }, + { 0x1.fdead1dffbd5ap+100, 0x1.5a750c74b4ea2p-189, INIT_U128( 0x0000001fdead1dff, 0xbd5a000000000000 ) }, + { 0x1.fe8116bbfd023p+100, 0x1.c0314d4580629p-189, INIT_U128( 0x0000001fe8116bbf, 0xd023000000000000 ) }, + { 0x1.9177917922ef2p+100, 0x1.b5d94c0f6bb2ap-189, INIT_U128( 0x0000001917791792, 0x2ef2000000000000 ) }, + { 0x1.39ab1bf273564p+100, 0x1.4de96f889bd2ep-189, INIT_U128( 0x000000139ab1bf27, 0x3564000000000000 ) }, + { 0x1.52e21a8aa5c44p+101, 0x0.0000075bfbb25p-1022, INIT_U128( 0x0000002a5c435154, 0xb888000000000000 ) }, + { 0x1.c362c16186c58p+101, 0x0.00000417370ap-1022, INIT_U128( 0x000000386c582c30, 0xd8b0000000000000 ) }, + { 0x1.dcbb50a5b976ap+101, 0x0.000005dcb4b01p-1022, INIT_U128( 0x0000003b976a14b7, 0x2ed4000000000000 ) }, + { 0x1.fae77febf5cfp+101, 0x0.00000567e1492p-1022, INIT_U128( 0x0000003f5ceffd7e, 0xb9e0000000000000 ) }, + { 0x1.b94feaf3729fdp+102, 0x1.eb191b6bd6324p-32, INIT_U128( 0x0000006e53fabcdc, 0xa7f4000000000000 ) }, + { 0x1.ffcd483fff9a9p+102, 0x1.f6c951e5ed92ap-32, INIT_U128( 0x0000007ff3520fff, 0xe6a4000000000000 ) }, + { 0x1.f4a75991e94ebp+102, 0x1.5d81e52ebb03cp-32, INIT_U128( 0x0000007d29d6647a, 0x53ac000000000000 ) }, + { 0x1.d9014a81b202ap+102, 0x1.1d1a5c4c3a34cp-32, INIT_U128( 0x000000764052a06c, 0x80a8000000000000 ) }, + { 0x1.d33430cda6686p+103, 0x1.58855d10b10acp-383, INIT_U128( 0x000000e99a1866d3, 0x3430000000000000 ) }, + { 0x1.5e801048bd002p+103, 0x1.54a52a72a94a6p-383, INIT_U128( 0x000000af4008245e, 0x8010000000000000 ) }, + { 0x1.590a254ab2144p+103, 0x1.0307881c060f1p-383, INIT_U128( 0x000000ac8512a559, 0x0a20000000000000 ) }, + { 0x1.6dfaecf0dbf5ep+103, 0x1.54a4b130a9496p-383, INIT_U128( 0x000000b6fd76786d, 0xfaf0000000000000 ) }, + { 0x1.011eb1b0023d6p+104, 0x1.39df71da73beep-20, INIT_U128( 0x000001011eb1b002, 0x3d60000000000000 ) }, + { 0x1.5ee2142ebdc42p+104, 0x1.43553d9086aa8p-20, INIT_U128( 0x0000015ee2142ebd, 0xc420000000000000 ) }, + { 0x1.100502e4200ap+104, 0x1.534d9720a69b3p-20, INIT_U128( 0x000001100502e420, 0x0a00000000000000 ) }, + { 0x1.2aefc5ac55df8p+104, 0x1.f553d14beaa7ap-20, INIT_U128( 0x0000012aefc5ac55, 0xdf80000000000000 ) }, + { 0x1.d0559891a0ab3p+105, 0x1.87b2239d0f644p-316, INIT_U128( 0x000003a0ab312341, 0x5660000000000000 ) }, + { 0x1.0929084e12521p+105, 0x1.e345fe55c68cp-316, INIT_U128( 0x0000021252109c24, 0xa420000000000000 ) }, + { 0x1.70c26be4e184ep+105, 0x1.7a6011c6f4c02p-316, INIT_U128( 0x000002e184d7c9c3, 0x09c0000000000000 ) }, + { 0x1.8c345d471868cp+105, 0x1.b4a5d903694bbp-316, INIT_U128( 0x0000031868ba8e30, 0xd180000000000000 ) }, + { 0x1.66bf48cecd7e9p+106, 0x1.d926e3a9b24dcp-461, INIT_U128( 0x0000059afd233b35, 0xfa40000000000000 ) }, + { 0x1.caf9648595f2cp+106, 0x1.3edd8e587dbb2p-461, INIT_U128( 0x0000072be5921657, 0xcb00000000000000 ) }, + { 0x1.0ff9c5341ff38p+106, 0x1.5ecf4954bd9e9p-461, INIT_U128( 0x0000043fe714d07f, 0xce00000000000000 ) }, + { 0x1.010bbf3602178p+106, 0x1.90183dfb20308p-461, INIT_U128( 0x000004042efcd808, 0x5e00000000000000 ) }, + { 0x1.90f1198321e23p+107, 0x1.18ec849e31d9p-508, INIT_U128( 0x00000c8788cc190f, 0x1180000000000000 ) }, + { 0x1.88876447110ecp+107, 0x1.3dbc4a967b78ap-508, INIT_U128( 0x00000c443b223888, 0x7600000000000000 ) }, + { 0x1.e955d221d2abap+107, 0x1.1f1f0f983e3e2p-508, INIT_U128( 0x00000f4aae910e95, 0x5d00000000000000 ) }, + { 0x1.79931aacf3264p+107, 0x1.5c6d47c2b8da9p-508, INIT_U128( 0x00000bcc98d56799, 0x3200000000000000 ) }, + { 0x1.49a28e4c93452p+108, 0x1.0819b1c610336p-949, INIT_U128( 0x0000149a28e4c934, 0x5200000000000000 ) }, + { 0x1.b61387f56c271p+108, 0x1.fda021a7fb404p-949, INIT_U128( 0x00001b61387f56c2, 0x7100000000000000 ) }, + { 0x1.8364b71506c97p+108, 0x1.972f04852e5ep-949, INIT_U128( 0x000018364b71506c, 0x9700000000000000 ) }, + { 0x1.a902b10952056p+108, 0x1.aee9cfcf5dd3ap-949, INIT_U128( 0x00001a902b109520, 0x5600000000000000 ) }, + { 0x1.d96f1c29b2de4p+109, 0x1.8415bcdf082b8p-695, INIT_U128( 0x00003b2de385365b, 0xc800000000000000 ) }, + { 0x1.e8dfe3f9d1bfcp+109, 0x1.c31bb2ed86377p-695, INIT_U128( 0x00003d1bfc7f3a37, 0xf800000000000000 ) }, + { 0x1.3a0cc61474199p+109, 0x1.06f2795a0de4fp-695, INIT_U128( 0x0000274198c28e83, 0x3200000000000000 ) }, + { 0x1.1f3e5f4a3e7ccp+109, 0x1.d7cc8b85af992p-695, INIT_U128( 0x000023e7cbe947cf, 0x9800000000000000 ) }, + { 0x1.dc6af865b8d5fp+110, 0x1.b5d225136ba45p-22, INIT_U128( 0x0000771abe196e35, 0x7c00000000000000 ) }, + { 0x1.4ca9fcc69954p+110, 0x1.eaa024f7d5404p-22, INIT_U128( 0x0000532a7f31a655, 0x0000000000000000 ) }, + { 0x1.414c72988298ep+110, 0x1.a488753b4910fp-22, INIT_U128( 0x000050531ca620a6, 0x3800000000000000 ) }, + { 0x1.dc6b39dbb8d67p+110, 0x1.068d04580d1ap-22, INIT_U128( 0x0000771ace76ee35, 0x9c00000000000000 ) }, + { 0x1.74e50e90e9ca2p+111, 0x1.3f289f007e514p-487, INIT_U128( 0x0000ba72874874e5, 0x1000000000000000 ) }, + { 0x1.5f0a2632be145p+111, 0x1.f790c8d9ef219p-487, INIT_U128( 0x0000af8513195f0a, 0x2800000000000000 ) }, + { 0x1.d422bf03a8458p+111, 0x1.fbacd695f759bp-487, INIT_U128( 0x0000ea115f81d422, 0xc000000000000000 ) }, + { 0x1.d9b5cefdb36bap+111, 0x1.c968397b92d07p-487, INIT_U128( 0x0000ecdae77ed9b5, 0xd000000000000000 ) }, + { 0x1.f3e78001e7cfp+112, 0x1.4b4970649692ep-744, INIT_U128( 0x0001f3e78001e7cf, 0x0000000000000000 ) }, + { 0x1.17c200042f84p+112, 0x1.8d8e8a711b1d1p-744, INIT_U128( 0x000117c200042f84, 0x0000000000000000 ) }, + { 0x1.0fe4fde81fcap+112, 0x1.256616f84acc3p-744, INIT_U128( 0x00010fe4fde81fca, 0x0000000000000000 ) }, + { 0x1.f2773487e4ee6p+112, 0x1.075dd87a0ebbbp-744, INIT_U128( 0x0001f2773487e4ee, 0x6000000000000000 ) }, + { 0x1.7f2646f4fe4c9p+113, 0x1.bde0f7d57bc1fp-552, INIT_U128( 0x0002fe4c8de9fc99, 0x2000000000000000 ) }, + { 0x1.552a71c4aa54ep+113, 0x1.5f75cb84beebap-552, INIT_U128( 0x0002aa54e38954a9, 0xc000000000000000 ) }, + { 0x1.016211fe02c42p+113, 0x1.755a3ebeeab48p-552, INIT_U128( 0x000202c423fc0588, 0x4000000000000000 ) }, + { 0x1.2da4a1405b494p+113, 0x1.c7b5a5b78f6b5p-552, INIT_U128( 0x00025b494280b692, 0x8000000000000000 ) }, + { 0x1.454dcac88a9bap+114, 0x1.39e2f64073c5fp-541, INIT_U128( 0x000515372b222a6e, 0x8000000000000000 ) }, + { 0x1.f5769ad1eaed4p+114, 0x1.273e2b1a4e7c6p-541, INIT_U128( 0x0007d5da6b47abb5, 0x0000000000000000 ) }, + { 0x1.52bf04cca57ep+114, 0x1.2d92613e5b24cp-541, INIT_U128( 0x00054afc133295f8, 0x0000000000000000 ) }, + { 0x1.1b84a7fc37095p+114, 0x1.8b3360311666cp-541, INIT_U128( 0x00046e129ff0dc25, 0x4000000000000000 ) }, + { 0x1.82ef082b05de1p+115, 0x1.5205f44aa40bep-62, INIT_U128( 0x000c177841582ef0, 0x8000000000000000 ) }, + { 0x1.bafcbdf175f98p+115, 0x1.a9ea203153d44p-62, INIT_U128( 0x000dd7e5ef8bafcc, 0x0000000000000000 ) }, + { 0x1.64b56bd8c96aep+115, 0x1.42c3a3da85874p-62, INIT_U128( 0x000b25ab5ec64b57, 0x0000000000000000 ) }, + { 0x1.55c9b3b6ab936p+115, 0x1.48f9d11a91f3ap-62, INIT_U128( 0x000aae4d9db55c9b, 0x0000000000000000 ) }, + { 0x1.5321473ca6429p+116, 0x1.181db1c6303b6p-92, INIT_U128( 0x0015321473ca6429, 0x0000000000000000 ) }, + { 0x1.cdc20a3f9b841p+116, 0x1.50077ebca00fp-92, INIT_U128( 0x001cdc20a3f9b841, 0x0000000000000000 ) }, + { 0x1.92fee4f925fdcp+116, 0x1.028f8f16051f2p-92, INIT_U128( 0x00192fee4f925fdc, 0x0000000000000000 ) }, + { 0x1.1bab55e43756ap+116, 0x1.40855e9c810acp-92, INIT_U128( 0x0011bab55e43756a, 0x0000000000000000 ) }, + { 0x1.db43e365b687dp+117, 0x1.41baf8828375fp-732, INIT_U128( 0x003b687c6cb6d0fa, 0x0000000000000000 ) }, + { 0x1.a552a1674aa54p+117, 0x1.baa689f9754d1p-732, INIT_U128( 0x0034aa542ce954a8, 0x0000000000000000 ) }, + { 0x1.fe56ea4dfcadep+117, 0x1.5684197ead083p-732, INIT_U128( 0x003fcadd49bf95bc, 0x0000000000000000 ) }, + { 0x1.6c9b7a08d937p+117, 0x1.2337f65a466ffp-732, INIT_U128( 0x002d936f411b26e0, 0x0000000000000000 ) }, + { 0x1.076705de0ecep+118, 0x1.98bce7cb3179dp-844, INIT_U128( 0x0041d9c17783b380, 0x0000000000000000 ) }, + { 0x1.9b22f3533645ep+118, 0x1.74f31c32e9e64p-844, INIT_U128( 0x0066c8bcd4cd9178, 0x0000000000000000 ) }, + { 0x1.c1d136e583a27p+118, 0x1.767b76ceecf6fp-844, INIT_U128( 0x0070744db960e89c, 0x0000000000000000 ) }, + { 0x1.c885934b910b3p+118, 0x1.cd65a24d9acb4p-844, INIT_U128( 0x00722164d2e442cc, 0x0000000000000000 ) }, + { 0x1.fb2c8085f659p+119, 0x1.4485cbfc890bap-269, INIT_U128( 0x00fd964042fb2c80, 0x0000000000000000 ) }, + { 0x1.78eebbd0f1dd8p+119, 0x1.373c5ea66e78cp-269, INIT_U128( 0x00bc775de878eec0, 0x0000000000000000 ) }, + { 0x1.1cbf9dfc397f4p+119, 0x1.3a787bfa74f1p-269, INIT_U128( 0x008e5fcefe1cbfa0, 0x0000000000000000 ) }, + { 0x1.0b37d4fc166fap+119, 0x1.3ec2f1ca7d85ep-269, INIT_U128( 0x00859bea7e0b37d0, 0x0000000000000000 ) }, + { 0x1.f7d41d9befa83p+119, 0x1.737e360ee6fc7p+45, INIT_U128( 0x00fbea0ecdf7d418, 0x00002e6fc6c1dcdf ) }, + { 0x1.5f9adea4bf35cp+119, 0x1.f2a34d73e5469p+45, INIT_U128( 0x00afcd6f525f9ae0, 0x00003e5469ae7ca8 ) }, + { 0x1.1625a2842c4b4p+119, 0x1.dffa968fbff53p+45, INIT_U128( 0x008b12d1421625a0, 0x00003bff52d1f7fe ) }, + { 0x1.77b9ea5cef73ep+119, 0x1.03d8c57207b18p+45, INIT_U128( 0x00bbdcf52e77b9f0, 0x0000207b18ae40f6 ) }, + { 0x1.80c91d3d01924p+119, 0x1.dc2e84abb85dp+45, INIT_U128( 0x00c0648e9e80c920, 0x00003b85d095770b ) }, + { 0x1.a13e2abb427c5p+119, 0x1.be5baad37cb75p+45, INIT_U128( 0x00d09f155da13e28, 0x000037cb755a6f96 ) }, + { 0x1.3d0a39607a147p+119, 0x1.5d047beeba09p+45, INIT_U128( 0x009e851cb03d0a38, 0x00002ba08f7dd741 ) }, + { 0x1.e914f2edd229fp+119, 0x1.a87d6b5150faep+45, INIT_U128( 0x00f48a7976e914f8, 0x0000350fad6a2a1f ) }, + { 0x1.1bfba16037f74p+119, 0x1.f1667f23e2cdp+45, INIT_U128( 0x008dfdd0b01bfba0, 0x00003e2ccfe47c59 ) }, + { 0x1.e409cc97c8139p+119, 0x1.760ec180ec1d8p+45, INIT_U128( 0x00f204e64be409c8, 0x00002ec1d8301d83 ) }, + { 0x1.56095810ac12bp+119, 0x1.fd72c88bfae59p+45, INIT_U128( 0x00ab04ac08560958, 0x00003fae59117f5c ) }, + { 0x1.014b8dfe02972p+119, 0x1.5051ec7ca0a3ep+45, INIT_U128( 0x0080a5c6ff014b90, 0x00002a0a3d8f9414 ) }, + { 0x1.2c8071285900ep+119, 0x1.2df331a65be66p+45, INIT_U128( 0x00964038942c8070, 0x000025be6634cb7c ) }, + { 0x1.ec4edc7bd89dbp+119, 0x1.5689910cad132p+45, INIT_U128( 0x00f6276e3dec4ed8, 0x00002ad1322195a2 ) }, + { 0x1.acab22af59564p+120, 0x1.4302395486047p-789, INIT_U128( 0x01acab22af595640, 0x0000000000000000 ) }, + { 0x1.6d777264daeeep+120, 0x1.a94793a7528f2p-789, INIT_U128( 0x016d777264daeee0, 0x0000000000000000 ) }, + { 0x1.179807f22f301p+120, 0x1.f73f61cbee7ecp-789, INIT_U128( 0x01179807f22f3010, 0x0000000000000000 ) }, + { 0x1.2306ea1a460dep+120, 0x1.7f322c14fe646p-789, INIT_U128( 0x012306ea1a460de0, 0x0000000000000000 ) }, + { 0x1.4b89313897126p+121, 0x1.24f0cf5649e1ap-97, INIT_U128( 0x02971262712e24c0, 0x0000000000000000 ) }, + { 0x1.977d3ba32efa8p+121, 0x1.8d5ae3291ab5cp-97, INIT_U128( 0x032efa77465df500, 0x0000000000000000 ) }, + { 0x1.4951cf1a92a3ap+121, 0x1.ff3e4eaffe7cap-97, INIT_U128( 0x0292a39e35254740, 0x0000000000000000 ) }, + { 0x1.6487918ac90f2p+121, 0x1.8e5a3b671cb48p-97, INIT_U128( 0x02c90f2315921e40, 0x0000000000000000 ) }, + { 0x1.a71b395f4e367p+122, 0x1.4851ea7e90a3ep-824, INIT_U128( 0x069c6ce57d38d9c0, 0x0000000000000000 ) }, + { 0x1.58097738b012fp+122, 0x1.a4e92d4749d26p-824, INIT_U128( 0x056025dce2c04bc0, 0x0000000000000000 ) }, + { 0x1.431d2f4a863a6p+122, 0x1.ff84386fff087p-824, INIT_U128( 0x050c74bd2a18e980, 0x0000000000000000 ) }, + { 0x1.9f1393ad3e272p+122, 0x1.d7c0a6ddaf815p-824, INIT_U128( 0x067c4e4eb4f89c80, 0x0000000000000000 ) }, + { 0x1.8983ab7913076p+123, 0x1.fa01bdc9f4037p-825, INIT_U128( 0x0c4c1d5bc8983b00, 0x0000000000000000 ) }, + { 0x1.f3551e67e6aa4p+123, 0x1.029c51f00538ap-825, INIT_U128( 0x0f9aa8f33f355200, 0x0000000000000000 ) }, + { 0x1.a9da0d1d53b42p+123, 0x1.b5c718d36b8e3p-825, INIT_U128( 0x0d4ed068ea9da100, 0x0000000000000000 ) }, + { 0x1.95c79e2b2b8f4p+123, 0x1.384e4c32709cap-825, INIT_U128( 0x0cae3cf1595c7a00, 0x0000000000000000 ) }, + { 0x1.73af4650e75e9p+124, 0x1.ec4b7265d896fp-92, INIT_U128( 0x173af4650e75e900, 0x0000000000000000 ) }, + { 0x1.5e15a3a0bc2b4p+124, 0x1.2ff859825ff0bp-92, INIT_U128( 0x15e15a3a0bc2b400, 0x0000000000000000 ) }, + { 0x1.4dbe24a69b7c4p+124, 0x1.f5b685e5eb6d1p-92, INIT_U128( 0x14dbe24a69b7c400, 0x0000000000000000 ) }, + { 0x1.cd65ac439acb6p+124, 0x1.164d910a2c9b2p-92, INIT_U128( 0x1cd65ac439acb600, 0x0000000000000000 ) }, + { 0x1.f5bbadd5eb775p+125, 0x1.b16aeddb62d5ep-83, INIT_U128( 0x3eb775babd6eea00, 0x0000000000000000 ) }, + { 0x1.b66841396cd08p+125, 0x1.f9957d69f32afp-83, INIT_U128( 0x36cd08272d9a1000, 0x0000000000000000 ) }, + { 0x1.05be50760b7cap+125, 0x1.f9ebf8ddf3d7fp-83, INIT_U128( 0x20b7ca0ec16f9400, 0x0000000000000000 ) }, + { 0x1.51312262a2624p+125, 0x1.11c69084238d2p-83, INIT_U128( 0x2a26244c544c4800, 0x0000000000000000 ) }, + { 0x1.30eab12c61d56p+126, 0x1.f1e0e851e3c1dp-773, INIT_U128( 0x4c3aac4b18755800, 0x0000000000000000 ) }, + { 0x1.ac34bcf158698p+126, 0x1.a55b126f4ab62p-773, INIT_U128( 0x6b0d2f3c561a6000, 0x0000000000000000 ) }, + { 0x1.02246a040448ep+126, 0x1.61a83652c3507p-773, INIT_U128( 0x40891a8101123800, 0x0000000000000000 ) }, + { 0x1.ae881f955d104p+126, 0x1.c694aaa18d296p-773, INIT_U128( 0x6ba207e557441000, 0x0000000000000000 ) }, + { 0x1.08016b641002ep+127, 0x1.23a890d047512p-406, INIT_U128( 0x8400b5b208017000, 0x0000000000000000 ) }, + { 0x1.3d90e7327b21dp+127, 0x1.0aa664c0154ccp-406, INIT_U128( 0x9ec873993d90e800, 0x0000000000000000 ) }, + { 0x1.ff931617ff263p+127, 0x1.47d5e2a08fabcp-406, INIT_U128( 0xffc98b0bff931800, 0x0000000000000000 ) }, + { 0x1.f565d1dfeacbap+127, 0x1.827bc0c304f78p-406, INIT_U128( 0xfab2e8eff565d000, 0x0000000000000000 ) }, + { 0x1.fe1985fbfc33p+128, 0x1.a6e724cd4dce4p-1021, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.54709ed6a8e14p+128, 0x1.74a32d1ce9466p-1021, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.a8407dcf5081p+128, 0x1.ffb065f3ff60cp-1021, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.7a1cfcf2f43ap+130, 0x1.84bb5ea30976cp-548, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.6bddaae8d7bb6p+194, 0x1.de64c609bcc99p-754, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.5c6c29d4b8d85p+146, 0x1.0644f6d60c89fp-345, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.c6ce8bcf8d9d2p+158, 0x1.443b2e7088766p-26, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.747f6aa0e8feep+168, 0x1.fe663ae9fccc8p-143, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.26ee550a4ddcap+173, 0x1.951f708f2a3eep-45, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.3ecfe0ea7d9fcp+189, 0x1.9cb53593396a7p-619, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.9d394a313a729p+190, 0x1.9ecfff853dap-150, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.244a568a4894bp+241, 0x1.e23f42d7c47e9p-956, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.b564bb276ac98p+398, 0x1.7af8d1ccf5f1ap+215, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.ee06b389dc0d7p+468, 0x1.b54fa74f6a9f5p+322, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.ac0045bd58009p+588, 0x1.ba99775b7532fp-365, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.692078cad240fp+661, 0x1.bc4a88a978951p+356, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.be1e09dd7c3c1p+765, 0x1.428bc5dc85178p-848, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.5f5554c4beaaap+853, 0x1.a9e23bdd53c48p-807, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.748e96ace91d3p+993, 0x1.ab54ab4b56a96p-22, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { 0x1.0629e7380c53dp+1023, 0x1.c0b4b15581696p+323, INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ) }, + { INFINITY, 0x1.21bff4bc437fep-333, ((__uint128_t) 0xffffffffffffffff << 64) | 0xffffffffffffffff }, + { INFINITY, 0x1.47e9a0228fd34p-333, ((__uint128_t) 0xffffffffffffffff << 64) | 0xffffffffffffffff } +}; + +static const int numTests = sizeof(testList) / sizeof(struct testCase); + diff --git a/test/builtins/Unit/ppc/floatditf_test.c b/test/builtins/Unit/ppc/floatditf_test.c index 5c08ade4b..e9b945834 100644 --- a/test/builtins/Unit/ppc/floatditf_test.c +++ b/test/builtins/Unit/ppc/floatditf_test.c @@ -1,7 +1,8 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdint.h> #include <stdio.h> +#include "int_lib.h" COMPILER_RT_ABI long double __floatditf(int64_t); diff --git a/test/builtins/Unit/ppc/floattitf_test.c b/test/builtins/Unit/ppc/floattitf_test.c new file mode 100644 index 000000000..e89e5d946 --- /dev/null +++ b/test/builtins/Unit/ppc/floattitf_test.c @@ -0,0 +1,59 @@ +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t + +/* + * Test case execution for: long double __floattitf (__int128_t) + * Conversion from 128 bit integer to long double (IBM double-double). + */ + +#include <stdint.h> +#include <stdio.h> + +#include "floattitf_test.h" + +/* The long double representation, with the high and low portions of + * the long double, and the corresponding bit patterns of each double. */ +typedef union { + long double ld; + double d[2]; /* [0] is the high double, [1] is the low double. */ + unsigned long long ull[2]; /* High and low doubles as 64-bit integers. */ +} ldUnion; + +long double __floattitf(__int128_t); + +int main(int argc, char *argv[]) { + /* Necessary long double and 128 bit integer declarations used to + * compare computed and expected high and low portions of the + * IBM double-double. */ + ldUnion expectedLongDouble; + ldUnion computedLongDouble; + __int128_t result128; + + for (int i = 0; i < numTests; ++i) { + /* Set the expected high and low values of the long double, + * and the 128 bit integer input to be converted. */ + expectedLongDouble.d[0] = tests[i].hi; + expectedLongDouble.d[1] = tests[i].lo; + result128 = tests[i].input128; + + /* Get the computed long double from the int128->long double conversion + * and check for errors between high and low portions. */ + computedLongDouble.ld = __floattitf(result128); + + if ((computedLongDouble.d[0] != expectedLongDouble.d[0]) || + (computedLongDouble.d[1] != expectedLongDouble.d[1])) { + + printf("Error on __floattitf( 0x%016llx 0x%016llx ):\n", + (long long)(tests[i].input128 >> 64), + (long long)tests[i].input128); + printf("\tExpected value - %La = ( %a, %a )\n", expectedLongDouble.ld, + expectedLongDouble.d[0], expectedLongDouble.d[1]); + printf("\tComputed value - %La = ( %a, %a )\n\n", computedLongDouble.ld, + computedLongDouble.d[0], computedLongDouble.d[1]); + + return 1; + } + } + + return 0; +} diff --git a/test/builtins/Unit/ppc/floattitf_test.h b/test/builtins/Unit/ppc/floattitf_test.h new file mode 100644 index 000000000..1da8a6b52 --- /dev/null +++ b/test/builtins/Unit/ppc/floattitf_test.h @@ -0,0 +1,197 @@ +/* +* Test case inputs for: long double __floattitf (__int128_t) +* Conversion from 128 bit integer to long double (IBM double-double). +*/ + +#define INIT_U128(HI, LO) (((__uint128_t) (HI) << 64) | (LO)) + +struct testCase { + __int128_t input128; + double hi; + double lo; +}; + +struct testCase tests[] = { + { INIT_U128( 0x0000000000000000, 0x0000000000000000 ), 0x0p+0, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000001 ), 0x1p+0, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x1000000000000000 ), 0x1p+60, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xffffffffffffffff ), 0x1p+64, -0x1p+0 }, + { INIT_U128( 0x0000000000000000, 0x7fffffffffffffff ), 0x1p+63, -0x1p+0 }, + { INIT_U128( 0x0000000000000001, 0x0000000000000000 ), 0x1p+64, 0x0p+0 }, + { INIT_U128( 0x0000000000000001, 0x0000000000000001 ), 0x1p+64, 0x1p+0 }, + { INIT_U128( 0x0000000000000001, 0x7fffffffffffffff ), 0x1.8p+64, -0x1p+0 }, + { INIT_U128( 0x0000000000000001, 0x1000000000000000 ), 0x1.1p+64, 0x0p+0 }, + { INIT_U128( 0x0000000000000001, 0xffffffffffffffff ), 0x1p+65, -0x1p+0 }, + { INIT_U128( 0x7fffffffffffffff, 0x0000000000000000 ), 0x1p+127, -0x1p+64 }, + { INIT_U128( 0x7fffffffffffffff, 0x0000000000000001 ), 0x1p+127, -0x1p+64 }, + { INIT_U128( 0x7fffffffffffffff, 0x7fffffffffffffff ), 0x1p+127, -0x1p+63 }, + { INIT_U128( 0x7fffffffffffffff, 0x1000000000000000 ), 0x1p+127, -0x1.ep+63 }, + { INIT_U128( 0x7fffffffffffffff, 0xffffffffffffffff ), 0x1p+127, -0x1p+0 }, + { INIT_U128( 0x1000000000000000, 0x0000000000000000 ), 0x1p+124, 0x0p+0 }, + { INIT_U128( 0x1000000000000000, 0x0000000000000001 ), 0x1p+124, 0x1p+0 }, + { INIT_U128( 0x1000000000000000, 0x7fffffffffffffff ), 0x1p+124, 0x1p+63 }, + { INIT_U128( 0x1000000000000000, 0x1000000000000000 ), 0x1p+124, 0x1p+60 }, + { INIT_U128( 0x1000000000000000, 0xffffffffffffffff ), 0x1p+124, 0x1p+64 }, + { INIT_U128( 0xffffffffffffffff, 0x0000000000000000 ), -0x1p+64, 0x0p+0 }, + { INIT_U128( 0xffffffffffffffff, 0x0000000000000001 ), -0x1p+64, 0x1p+0 }, + { INIT_U128( 0xffffffffffffffff, 0x7fffffffffffffff ), -0x1p+63, -0x1p+0 }, + { INIT_U128( 0xffffffffffffffff, 0x1000000000000000 ), -0x1.ep+63, 0x0p+0 }, + { INIT_U128( 0xffffffffffffffff, 0xffffffffffffffff ), -0x1p+0, 0x0p+0 }, + { INIT_U128( 0x0000000000000061, 0x0000000000000061 ), 0x1.84p+70, 0x1.84p+6 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000057 ), 0x1.5cp+6, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xffffffffffffff9e ), 0x1p+64, -0x1.88p+6 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000062 ), 0x1.88p+6, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000403 ), 0x1.00cp+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffffffffbfc ), 0x1.fffffffffffffp+63, 0x1.fep+9 }, + { INIT_U128( 0x0000000000000000, 0x000000000000040a ), 0x1.028p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x000000000000040c ), 0x1.03p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x000000000000041a ), 0x1.068p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000510 ), 0x1.44p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000518 ), 0x1.46p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffffffffae7 ), 0x1.fffffffffffffp+63, 0x1.738p+9 }, + { INIT_U128( 0x0000000000000000, 0x0000000000000602 ), 0x1.808p+10, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffffffff9fd ), 0x1.fffffffffffffp+63, 0x1.fdp+8 }, + { INIT_U128( 0x0000000000000000, 0x0000000000002090 ), 0x1.048p+13, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xffffffffffffdbdb ), 0x1.ffffffffffffbp+63, 0x1.ed8p+9 }, + { INIT_U128( 0x0000000000000000, 0x0000000000002430 ), 0x1.218p+13, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000000020202 ), 0x1.0101p+17, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffffffdeef7 ), 0x1.fffffffffffbep+63, -0x1.09p+8 }, + { INIT_U128( 0x0000000000000000, 0x0000000000032004 ), 0x1.9002p+17, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffffffcdffb ), 0x1.fffffffffff9cp+63, -0x1.4p+2 }, + { INIT_U128( 0x0000000000000000, 0x0000000000032040 ), 0x1.902p+17, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xffffffffffbfdfbb ), 0x1.ffffffffff7fcp+63, -0x1.14p+6 }, + { INIT_U128( 0x0000000000000000, 0x0000000000402088 ), 0x1.00822p+22, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000000080080088 ), 0x1.0010011p+31, 0x0p+0 }, + { INIT_U128( 0xffffffff7ff7ff77, 0xffffffff7ff7ff77 ), -0x1.0010011p+95, -0x1.00100112p+31 }, + { INIT_U128( 0x0000000000000000, 0x0000000850000008 ), 0x1.0a000001p+35, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x0000002000000448 ), 0x1.000000224p+37, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xffffffdfff7dbfff ), 0x1.ffffffbffefb8p+63, -0x1p+0 }, + { INIT_U128( 0x0000004002001100, 0x0000004002001100 ), 0x1.00080044p+102, 0x1.00080044p+38 }, + { INIT_U128( 0x000008020000000c, 0x000008020000000c ), 0x1.00400000018p+107, 0x1.00400000018p+43 }, + { INIT_U128( 0x0000000000000000, 0xfffff7fdfffffff3 ), 0x1.ffffeffcp+63, -0x1.ap+3 }, + { INIT_U128( 0x0000000000000000, 0x0000800000000824 ), 0x1.000000001048p+47, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffdffffff7ffcff ), 0x1.fffbffffffp+63, -0x1.808p+9 }, + { INIT_U128( 0x0000000000000000, 0x4002040010000000 ), 0x1.000810004p+62, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xbffdfbffefffffff ), 0x1.7ffbf7ffep+63, -0x1p+0 }, + { INIT_U128( 0x0000000000000000, 0x8000000000000000 ), 0x1p+63, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xfffffffff418c5c1 ), 0x1.ffffffffe8319p+63, -0x1.1f8p+9 }, + { INIT_U128( 0x000000000000000f, 0xffffffffffffffff ), 0x1p+68, -0x1p+0 }, + { INIT_U128( 0x00000000000000ff, 0xffffffffffffffff ), 0x1p+72, -0x1p+0 }, + { INIT_U128( 0x0000000000000fff, 0xffffffffffffffff ), 0x1p+76, -0x1p+0 }, + { INIT_U128( 0x000000000000ffff, 0xffffffffffffffff ), 0x1p+80, -0x1p+0 }, + { INIT_U128( 0x00000000000fffff, 0xffffffffffffffff ), 0x1p+84, -0x1p+0 }, + { INIT_U128( 0x0000000000ffffff, 0xffffffffffffffff ), 0x1p+88, -0x1p+0 }, + { INIT_U128( 0x000000000fffffff, 0xffffffffffffffff ), 0x1p+92, -0x1p+0 }, + { INIT_U128( 0x00000000ffffffff, 0xffffffffffffffff ), 0x1p+96, -0x1p+0 }, + { INIT_U128( 0x0000000fffffffff, 0xffffffffffffffff ), 0x1p+100, -0x1p+0 }, + { INIT_U128( 0x000000ffffffffff, 0xffffffffffffffff ), 0x1p+104, -0x1p+0 }, + { INIT_U128( 0x00000fffffffffff, 0xffffffffffffffff ), 0x1p+108, -0x1p+0 }, + { INIT_U128( 0x0000ffffffffffff, 0xffffffffffffffff ), 0x1p+112, -0x1p+0 }, + { INIT_U128( 0x000fffffffffffff, 0xffffffffffffffff ), 0x1p+116, -0x1p+0 }, + { INIT_U128( 0x00ffffffffffffff, 0xffffffffffffffff ), 0x1p+120, -0x1p+0 }, + { INIT_U128( 0x0fffffffffffffff, 0xffffffffffffffff ), 0x1p+124, -0x1p+0 }, + { INIT_U128( 0x1000000000000000, 0x0000000000000000 ), 0x1p+124, 0x0p+0 }, + { INIT_U128( 0x1000000000000000, 0x0000000000000011 ), 0x1p+124, 0x1.1p+4 }, + { INIT_U128( 0x1000000000000000, 0x0000000000000111 ), 0x1p+124, 0x1.11p+8 }, + { INIT_U128( 0x1000000000000000, 0x0000000000001111 ), 0x1p+124, 0x1.111p+12 }, + { INIT_U128( 0x1000000000000000, 0x0000000000011111 ), 0x1p+124, 0x1.1111p+16 }, + { INIT_U128( 0x1000000000000000, 0x0000000000111111 ), 0x1p+124, 0x1.11111p+20 }, + { INIT_U128( 0x1000000000000000, 0x0000000001111111 ), 0x1p+124, 0x1.111111p+24 }, + { INIT_U128( 0x1000000000000000, 0x0000000011111111 ), 0x1p+124, 0x1.1111111p+28 }, + { INIT_U128( 0x1000000000000000, 0x0000000111111111 ), 0x1p+124, 0x1.11111111p+32 }, + { INIT_U128( 0x1000000000000000, 0x0000001111111111 ), 0x1p+124, 0x1.111111111p+36 }, + { INIT_U128( 0x1000000000000000, 0x0000011111111111 ), 0x1p+124, 0x1.1111111111p+40 }, + { INIT_U128( 0x1000000000000000, 0x0000111111111111 ), 0x1p+124, 0x1.11111111111p+44 }, + { INIT_U128( 0x1000000000000000, 0x0001111111111111 ), 0x1p+124, 0x1.111111111111p+48 }, + { INIT_U128( 0x1000000000000000, 0x0011111111111111 ), 0x1p+124, 0x1.1111111111111p+52 }, + { INIT_U128( 0x1000000000000000, 0x0111111111111111 ), 0x1p+124, 0x1.11111111111111p+56 }, + { INIT_U128( 0x1000000000000000, 0x1111111111111111 ), 0x1p+124, 0x1.111111111111111p+60 }, + { INIT_U128( 0xffffffffffffffff, 0xf000000000000000 ), -0x1p+60, 0x0p+0 }, + { INIT_U128( 0xffffffffffffffff, 0xff00000000000000 ), -0x1p+56, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xb7ffffff77ffffff ), 0x1.6ffffffefp+63, -0x1p+0 }, + { INIT_U128( 0xb7ffffff3fffffff, 0xb7ffffff3fffffff ), -0x1.20000003p+126, -0x1.20000003p+62 }, + { INIT_U128( 0xb7fffffefffffffe, 0xb7fffffefffffffe ), -0x1.20000004p+126, -0x1.48000001p+64 }, + { INIT_U128( 0xb7fffffeffffefff, 0xb7fffffeffffefff ), -0x1.2000000400004p+126, -0x1.2000000400004p+62 }, + { INIT_U128( 0x0000040000000000, 0x0000000000000000 ), 0x1p+106, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x000000003ff00000 ), 0x1.ff8p+29, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xb7fbffffffffdfff ), 0x1.6ff7ffffffffcp+63, -0x1p+0 }, + { INIT_U128( 0x0000000000000000, 0x4804000000010000 ), 0x1.201000000004p+62, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0x4900000000001000 ), 0x1.2400000000004p+62, 0x0p+0 }, + { INIT_U128( 0x0000000000000000, 0xb6ffffffffffefff ), 0x1.6dffffffffffep+63, -0x1p+0 }, + { INIT_U128( 0x0000000000000000, 0x4900000000008000 ), 0x1.240000000002p+62, 0x0p+0 }, + { INIT_U128( 0xb6ffffffffff7fff, 0xb6ffffffffff7fff ), -0x1.240000000002p+126, -0x1.240000000002p+62 }, + { INIT_U128( 0x4900000000040000, 0x4900000000040000 ), 0x1.24000000001p+126, 0x1.24000000001p+62 }, + { INIT_U128( 0xb6fffffffffbffff, 0xb6fffffffffbffff ), -0x1.24000000001p+126, -0x1.24000000001p+62 }, + { INIT_U128( 0x4900000000200000, 0x4900000000200000 ), 0x1.24000000008p+126, 0x1.24000000008p+62 }, + { INIT_U128( 0xb6ffffffffdfffff, 0xb6ffffffffdfffff ), -0x1.24000000008p+126, -0x1.24000000008p+62 }, + { INIT_U128( 0x4900000000800000, 0x4900000000800000 ), 0x1.2400000002p+126, 0x1.2400000002p+62 }, + { INIT_U128( 0xb6ffffffff7fffff, 0xb6ffffffff7fffff ), -0x1.2400000002p+126, -0x1.2400000002p+62 }, + { INIT_U128( 0x4900000008000000, 0x4900000008000000 ), 0x1.240000002p+126, 0x1.240000002p+62 }, + { INIT_U128( 0xb6fffffff7ffffff, 0xb6fffffff7ffffff ), -0x1.240000002p+126, -0x1.240000002p+62 }, + { INIT_U128( 0x4900000040000000, 0x4900000040000000 ), 0x1.24000001p+126, 0x1.24000001p+62 }, + { INIT_U128( 0xb6ffffffbfffffff, 0xb6ffffffbfffffff ), -0x1.24000001p+126, -0x1.24000001p+62 }, + { INIT_U128( 0x4900000080000000, 0x4900000080000000 ), 0x1.24000002p+126, 0x1.24000002p+62 }, + { INIT_U128( 0xb6ffffff7fffffff, 0xb6ffffff7fffffff ), -0x1.24000002p+126, -0x1.24000002p+62 }, + { INIT_U128( 0x4900000400000000, 0x4900000400000000 ), 0x1.2400001p+126, 0x1.2400001p+62 }, + { INIT_U128( 0xb6fffffbffffffff, 0xb6fffffbffffffff ), -0x1.2400001p+126, -0x1.2400001p+62 }, + { INIT_U128( 0x4900001000000000, 0x4900001000000000 ), 0x1.2400004p+126, 0x1.2400004p+62 }, + { INIT_U128( 0xb6ffffefffffffff, 0xb6ffffefffffffff ), -0x1.2400004p+126, -0x1.2400004p+62 }, + { INIT_U128( 0x4900004000000000, 0x4900004000000000 ), 0x1.240001p+126, 0x1.240001p+62 }, + { INIT_U128( 0xb6ffffbfffffffff, 0xb6ffffbfffffffff ), -0x1.240001p+126, -0x1.240001p+62 }, + { INIT_U128( 0x4900040000000000, 0x4900040000000000 ), 0x1.24001p+126, 0x1.24001p+62 }, + { INIT_U128( 0xb6fffbffffffffff, 0xb6fffbffffffffff ), -0x1.24001p+126, -0x1.24001p+62 }, + { INIT_U128( 0x4900200000000000, 0x4900200000000000 ), 0x1.24008p+126, 0x1.24008p+62 }, + { INIT_U128( 0xb6ffdfffffffffff, 0xb6ffdfffffffffff ), -0x1.24008p+126, -0x1.24008p+62 }, + { INIT_U128( 0x4901000000000000, 0x4901000000000000 ), 0x1.2404p+126, 0x1.2404p+62 }, + { INIT_U128( 0xb6feffffffffffff, 0xb6feffffffffffff ), -0x1.2404p+126, -0x1.2404p+62 }, + { INIT_U128( 0x4910000000000000, 0x4910000000000000 ), 0x1.244p+126, 0x1.244p+62 }, + { INIT_U128( 0xb6efffffffffffff, 0xb6efffffffffffff ), -0x1.244p+126, -0x1.244p+62 }, + { INIT_U128( 0x4980000000000000, 0x4980000000000000 ), 0x1.26p+126, 0x1.26p+62 }, + { INIT_U128( 0xb67fffffffffffff, 0xb67fffffffffffff ), -0x1.26p+126, -0x1.26p+62 }, + { INIT_U128( 0x4c00000000000000, 0x4c00000000000000 ), 0x1.3p+126, 0x1.3p+62 }, + { INIT_U128( 0xb3ffffffffffffff, 0xb3ffffffffffffff ), -0x1.3p+126, -0x1.3p+62 }, + { INIT_U128( 0x9fffffffffffbfff, 0x9fffffffffffbfff ), -0x1.800000000001p+126, -0x1.800000000001p+62 }, + { INIT_U128( 0x6000000000004001, 0x6000000000004001 ), 0x1.800000000001p+126, 0x1.6000000000004p+64 }, + { INIT_U128( 0x8fffffffffffffbf, 0x8fffffffffffffbf ), -0x1.cp+126, -0x1.01cp+70 }, + { INIT_U128( 0x7000000000000080, 0x7000000000000080 ), 0x1.cp+126, 0x1.00ep+71 }, + { INIT_U128( 0x8fffffffffffff7f, 0x8fffffffffffff7f ), -0x1.cp+126, -0x1.00ep+71 }, + { INIT_U128( 0x7000000000000800, 0x7000000000000800 ), 0x1.c000000000002p+126, 0x1.c000000000002p+62 }, + { INIT_U128( 0x8ffffffffffff7ff, 0x8ffffffffffff7ff ), -0x1.c000000000002p+126, -0x1.c000000000002p+62 }, + { INIT_U128( 0x7000000000002000, 0x7000000000002000 ), 0x1.c000000000008p+126, 0x1.c000000000008p+62 }, + { INIT_U128( 0x8fffffffffffdfff, 0x8fffffffffffdfff ), -0x1.c000000000008p+126, -0x1.c000000000008p+62 }, + { INIT_U128( 0x7000000000010000, 0x7000000000010000 ), 0x1.c00000000004p+126, 0x1.c00000000004p+62 }, + { INIT_U128( 0x8ffffffffffeffff, 0x8ffffffffffeffff ), -0x1.c00000000004p+126, -0x1.c00000000004p+62 }, + { INIT_U128( 0x7000000000040000, 0x7000000000040000 ), 0x1.c0000000001p+126, 0x1.c0000000001p+62 }, + { INIT_U128( 0x8ffffffffffbffff, 0x8ffffffffffbffff ), -0x1.c0000000001p+126, -0x1.c0000000001p+62 }, + { INIT_U128( 0x7000000000080000, 0x7000000000080000 ), 0x1.c0000000002p+126, 0x1.c0000000002p+62 }, + { INIT_U128( 0x8ffffffffff7ffff, 0x8ffffffffff7ffff ), -0x1.c0000000002p+126, -0x1.c0000000002p+62 }, + { INIT_U128( 0x7000000000800000, 0x7000000000800000 ), 0x1.c000000002p+126, 0x1.c000000002p+62 }, + { INIT_U128( 0x8fffffffff7fffff, 0x8fffffffff7fffff ), -0x1.c000000002p+126, -0x1.c000000002p+62 }, + { INIT_U128( 0x7000000008000000, 0x7000000008000000 ), 0x1.c00000002p+126, 0x1.c00000002p+62 }, + { INIT_U128( 0x8ffffffff7ffffff, 0x8ffffffff7ffffff ), -0x1.c00000002p+126, -0x1.c00000002p+62 }, + { INIT_U128( 0x7000000010000000, 0x7000000010000000 ), 0x1.c00000004p+126, 0x1.c00000004p+62 }, + { INIT_U128( 0x8fffffffefffffff, 0x8fffffffefffffff ), -0x1.c00000004p+126, -0x1.c00000004p+62 }, + { INIT_U128( 0x7000000100000000, 0x7000000100000000 ), 0x1.c0000004p+126, 0x1.c0000004p+62 }, + { INIT_U128( 0x8ffffffeffffffff, 0x8ffffffeffffffff ), -0x1.c0000004p+126, -0x1.c0000004p+62 }, + { INIT_U128( 0x7000000200000000, 0x7000000200000000 ), 0x1.c0000008p+126, 0x1.c0000008p+62 }, + { INIT_U128( 0x8ffffffdffffffff, 0x8ffffffdffffffff ), -0x1.c0000008p+126, -0x1.c0000008p+62 }, + { INIT_U128( 0x7000000800000000, 0x7000000800000000 ), 0x1.c000002p+126, 0x1.c000002p+62 }, + { INIT_U128( 0x8ffffff7ffffffff, 0x8ffffff7ffffffff ), -0x1.c000002p+126, -0x1.c000002p+62 }, + { INIT_U128( 0x7000008000000000, 0x7000008000000000 ), 0x1.c00002p+126, 0x1.c00002p+62 }, + { INIT_U128( 0x8fffff7fffffffff, 0x8fffff7fffffffff ), -0x1.c00002p+126, -0x1.c00002p+62 }, + { INIT_U128( 0x7000010000000000, 0x7000010000000000 ), 0x1.c00004p+126, 0x1.c00004p+62 }, + { INIT_U128( 0x8ffffeffffffffff, 0x8ffffeffffffffff ), -0x1.c00004p+126, -0x1.c00004p+62 }, + { INIT_U128( 0x7000080000000000, 0x7000080000000000 ), 0x1.c0002p+126, 0x1.c0002p+62 }, + { INIT_U128( 0x8ffff7ffffffffff, 0x8ffff7ffffffffff ), -0x1.c0002p+126, -0x1.c0002p+62 }, + { INIT_U128( 0x7000800000000000, 0x7000800000000000 ), 0x1.c002p+126, 0x1.c002p+62 }, + { INIT_U128( 0x8fff7fffffffffff, 0x8fff7fffffffffff ), -0x1.c002p+126, -0x1.c002p+62 }, + { INIT_U128( 0x7002000000000000, 0x7002000000000000 ), 0x1.c008p+126, 0x1.c008p+62 }, + { INIT_U128( 0x8ffdffffffffffff, 0x8ffdffffffffffff ), -0x1.c008p+126, -0x1.c008p+62 }, + { INIT_U128( 0x7008000000000000, 0x7008000000000000 ), 0x1.c02p+126, 0x1.c02p+62 }, + { INIT_U128( 0x8ff7ffffffffffff, 0x8ff7ffffffffffff ), -0x1.c02p+126, -0x1.c02p+62 }, + { INIT_U128( 0x7080000000000000, 0x7080000000000000 ), 0x1.c2p+126, 0x1.c2p+62 }, + { INIT_U128( 0x8f7fffffffffffff, 0x8f7fffffffffffff ), -0x1.c2p+126, -0x1.c2p+62 }, + { INIT_U128( 0x7400000000000000, 0x7400000000000000 ), 0x1.dp+126, 0x1.dp+62 } +}; + +static const int numTests = sizeof(tests) / sizeof(struct testCase); diff --git a/test/builtins/Unit/ppc/floatunditf_test.c b/test/builtins/Unit/ppc/floatunditf_test.c index 3e5012857..fc6090be1 100644 --- a/test/builtins/Unit/ppc/floatunditf_test.c +++ b/test/builtins/Unit/ppc/floatunditf_test.c @@ -1,7 +1,8 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdint.h> #include <stdio.h> +#include "int_lib.h" COMPILER_RT_ABI long double __floatunditf(uint64_t); diff --git a/test/builtins/Unit/ppc/qadd_test.c b/test/builtins/Unit/ppc/qadd_test.c index 327fd21e8..242850fff 100644 --- a/test/builtins/Unit/ppc/qadd_test.c +++ b/test/builtins/Unit/ppc/qadd_test.c @@ -1,5 +1,5 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdio.h> #include "DD.h" diff --git a/test/builtins/Unit/ppc/qdiv_test.c b/test/builtins/Unit/ppc/qdiv_test.c index 7530e428f..15990f0c3 100644 --- a/test/builtins/Unit/ppc/qdiv_test.c +++ b/test/builtins/Unit/ppc/qdiv_test.c @@ -1,5 +1,5 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdio.h> #include "DD.h" diff --git a/test/builtins/Unit/ppc/qmul_test.c b/test/builtins/Unit/ppc/qmul_test.c index dbe3536f3..c8e5bb096 100644 --- a/test/builtins/Unit/ppc/qmul_test.c +++ b/test/builtins/Unit/ppc/qmul_test.c @@ -1,5 +1,5 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdio.h> #include "DD.h" diff --git a/test/builtins/Unit/ppc/qsub_test.c b/test/builtins/Unit/ppc/qsub_test.c index e21224096..1e456f83a 100644 --- a/test/builtins/Unit/ppc/qsub_test.c +++ b/test/builtins/Unit/ppc/qsub_test.c @@ -1,5 +1,5 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_builtins %s -o %t && %run %t +// REQUIRES: target-is-powerpc64le +// RUN: %clang_builtins %s %librt -o %t && %run %t #include <stdio.h> #include "DD.h" diff --git a/test/fuzzer/AlignmentAssumptionTest.cpp b/test/fuzzer/AlignmentAssumptionTest.cpp new file mode 100644 index 000000000..be51d37e8 --- /dev/null +++ b/test/fuzzer/AlignmentAssumptionTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test for alignment assumption failure. + +#include <assert.h> +#include <climits> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> + +static volatile int32_t Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + __builtin_assume_aligned(Data + 1, 0x8000); + } + } + } + return 0; +} diff --git a/test/fuzzer/PrintUnstableStatsTest.cpp b/test/fuzzer/PrintUnstableStatsTest.cpp deleted file mode 100644 index 2b9de88d7..000000000 --- a/test/fuzzer/PrintUnstableStatsTest.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include <assert.h> -#include <cstdint> -#include <cstdio> -#include <cstdlib> - -int x = 0; -bool skip0 = false; -bool skip1 = false; -bool skip2 = false; - -__attribute__((noinline)) void det0() { x++; } -__attribute__((noinline)) void det1() { x++; } -__attribute__((noinline)) void det2() { x++; } -__attribute__((noinline)) void det3() { x++; } -__attribute__((noinline)) void det4() { x++; } - -__attribute__((noinline)) void ini0() { x++; } -__attribute__((noinline)) void ini1() { x++; } -__attribute__((noinline)) void ini2() { x++; } - -__attribute__((noinline)) void t0(int a) { x += a; } -__attribute__((noinline)) void t1() { x++; } -__attribute__((noinline)) void t2(int a, int b) { x += a + b; } -__attribute__((noinline)) void t3() { x++; } -__attribute__((noinline)) void t4(int a, int b, int c) { x += a + b +c; } - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size == 1 && Data[0] == 'A' && !skip0) { - skip0 = true; - ini0(); - } - if (Size == 1 && Data[0] == 'B' && !skip1) { - skip1 = true; - ini1(); - } - if (Size == 1 && Data[0] == 'C' && !skip2) { - skip2 = true; - ini2(); - } - - det0(); - det1(); - int a = rand(); - det2(); - - switch (a % 5) { - case 0: - t0(a); - break; - case 1: - t1(); - break; - case 2: - t2(a, a); - break; - case 3: - t3(); - break; - case 4: - t4(a, a, a); - break; - default: - assert(false); - } - - det3(); - det4(); - return 0; -} diff --git a/test/fuzzer/fuzzer-alignment-assumption.test b/test/fuzzer/fuzzer-alignment-assumption.test new file mode 100644 index 000000000..6db77e19c --- /dev/null +++ b/test/fuzzer/fuzzer-alignment-assumption.test @@ -0,0 +1,7 @@ +RUN: rm -f %t-AlignmentAssumptionTest-Ubsan +RUN: %cpp_compiler -fsanitize=alignment -fno-sanitize-recover=all %S/AlignmentAssumptionTest.cpp -o %t-AlignmentAssumptionTest-Ubsan +RUN: not %run %t-AlignmentAssumptionTest-Ubsan 2>&1 | FileCheck %s +CHECK: AlignmentAssumptionTest.cpp:22:39: runtime error: assumption of 32768 byte alignment for pointer of type 'const {{.*}} *' (aka 'const unsigned char *') failed +CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + +CHECK: Test unit written to ./crash- diff --git a/test/fuzzer/handle-unstable.test b/test/fuzzer/handle-unstable.test deleted file mode 100644 index d20224689..000000000 --- a/test/fuzzer/handle-unstable.test +++ /dev/null @@ -1,43 +0,0 @@ -# Tests -handle_unstable -# FIXME: Disabled on Windows until symbolization works properly. -UNSUPPORTED: windows - -RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-HandleUnstableTest - -; Normal -RUN: %run %t-HandleUnstableTest -print_coverage=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=NORMAL -NORMAL-DAG: det0() -NORMAL-DAG: det1() -NORMAL-DAG: det2() -NORMAL-DAG: det3() -NORMAL-DAG: det4() -NORMAL-DAG: ini0() -NORMAL-DAG: ini1() -NORMAL-DAG: ini2() -NORMAL-DAG: t0(int) -NORMAL-DAG: t1() -NORMAL-DAG: t2(int, int) -NORMAL-DAG: t3() -NORMAL-DAG: t4(int, int, int) - -; MinUnstable -RUN: %run %t-HandleUnstableTest -print_coverage=1 -handle_unstable=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=MIN -MIN-NOT: ini0() -MIN-NOT: ini1() -MIN-NOT: ini2() -MIN: det0() -MIN: det1() -MIN: det2() -MIN: det3() -MIN: det4() - -; ZeroUnstable -RUN: %run %t-HandleUnstableTest -print_coverage=1 -handle_unstable=2 -runs=1 2>&1 | FileCheck %s --check-prefix=ZERO -ZERO-NOT: ini0() -ZERO-NOT: ini1() -ZERO-NOT: ini2() -ZERO: det0() -ZERO: det1() -ZERO: det2() -ZERO: det3() -ZERO: det4() diff --git a/test/fuzzer/print_unstable_stats.test b/test/fuzzer/print_unstable_stats.test deleted file mode 100644 index 41b279130..000000000 --- a/test/fuzzer/print_unstable_stats.test +++ /dev/null @@ -1,24 +0,0 @@ -# Tests -print_unstable_stats -# Disabled on Windows because of differences symbolizing and flakiness. -UNSUPPORTED: aarch64, windows - -RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-PrintUnstableStatsTest - -RUN: %run %t-PrintUnstableStatsTest -print_unstable_stats=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=LONG -# We do not observe ini functions since we take the minimum hit counts, and minimum hit counts for ini is 0. -LONG: UNSTABLE_FUNCTIONS: -LONG-NOT: det0() -LONG-NOT: det1() -LONG-NOT: det2() -LONG-NOT: det3() -LONG-NOT: det4() -LONG-NOT: ini0() -LONG-NOT: ini1() -LONG-NOT: ini2() -LONG-DAG: t0(int) -LONG-DAG: t1() -LONG-DAG: t2(int, int) -LONG-DAG: t3() -LONG-DAG: t4(int, int, int) - -LONG-DAG: stat::stability_rate: 27.59 diff --git a/test/hwasan/CMakeLists.txt b/test/hwasan/CMakeLists.txt index 972c73250..3e397ac06 100644 --- a/test/hwasan/CMakeLists.txt +++ b/test/hwasan/CMakeLists.txt @@ -11,6 +11,9 @@ foreach(arch ${HWASAN_TEST_ARCH}) string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME ${ARCH_UPPER_CASE}) + # FIXME: Set this. + set(HWASAN_ANDROID_FILES_TO_PUSH []) + configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) diff --git a/test/hwasan/TestCases/Posix/system-allocator-fallback.cc b/test/hwasan/TestCases/Posix/system-allocator-fallback.cc new file mode 100644 index 000000000..8678d906d --- /dev/null +++ b/test/hwasan/TestCases/Posix/system-allocator-fallback.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx %s -o %t -ldl +// RUN: %clangxx_hwasan -shared %s -o %t.so -DSHARED_LIB -shared-libsan -Wl,-rpath,%compiler_rt_libdir +// RUN: %env_hwasan_opts=disable_allocator_tagging=0 %run %t + +// The dynamic loader on Android O appears to have a bug where it crashes when +// dlopening DF_1_GLOBAL libraries. +// REQUIRES: android-28 + +#include <stddef.h> + +// Test that allocations made by the system allocator can be realloc'd and freed +// by the hwasan allocator. + +typedef void run_test_fn(void *(*system_malloc)(size_t size)); + +#ifdef SHARED_LIB + +// Call the __sanitizer_ versions of these functions so that the test +// doesn't require the Android dynamic loader. +extern "C" void *__sanitizer_realloc(void *ptr, size_t size); +extern "C" void __sanitizer_free(void *ptr); + +extern "C" run_test_fn run_test; +void run_test(void *(*system_malloc)(size_t size)) { + void *mem = system_malloc(64); + mem = __sanitizer_realloc(mem, 128); + __sanitizer_free(mem); +} + +#else + +#include <dlfcn.h> +#include <stdlib.h> +#include <string> + +int main(int argc, char **argv) { + std::string path = argv[0]; + path += ".so"; + void *lib = dlopen(path.c_str(), RTLD_NOW); + if (!lib) { + printf("error in dlopen(): %s\n", dlerror()); + return 1; + } + + auto run_test = reinterpret_cast<run_test_fn *>(dlsym(lib, "run_test")); + if (!run_test) { + printf("failed dlsym\n"); + return 1; + } + + run_test(malloc); +} + +#endif diff --git a/test/hwasan/TestCases/deep-recursion.c b/test/hwasan/TestCases/deep-recursion.c index 1ac0f5b15..2fe77a7bd 100644 --- a/test/hwasan/TestCases/deep-recursion.c +++ b/test/hwasan/TestCases/deep-recursion.c @@ -30,25 +30,25 @@ __attribute__((noinline)) void FUNC10() { int x; USE(&x); FUNC9(); } int main() { FUNC10(); } -// D1: Previosly allocated frames +// D1: Previously allocated frames // D1: in OOB // D1-NOT: in FUNC // D1: Memory tags around the buggy address -// D2: Previosly allocated frames +// D2: Previously allocated frames // D2: in OOB // D2: in FUNC1 // D2-NOT: in FUNC // D2: Memory tags around the buggy address -// D3: Previosly allocated frames +// D3: Previously allocated frames // D3: in OOB // D3: in FUNC1 // D3: in FUNC2 // D3-NOT: in FUNC // D3: Memory tags around the buggy address -// D5: Previosly allocated frames +// D5: Previously allocated frames // D5: in OOB // D5: in FUNC1 // D5: in FUNC2 @@ -57,7 +57,7 @@ int main() { FUNC10(); } // D5-NOT: in FUNC // D5: Memory tags around the buggy address -// DEFAULT: Previosly allocated frames +// DEFAULT: Previously allocated frames // DEFAULT: in OOB // DEFAULT: in FUNC1 // DEFAULT: in FUNC2 diff --git a/test/hwasan/TestCases/heap-buffer-overflow.c b/test/hwasan/TestCases/heap-buffer-overflow.c index bff39d293..9f605b320 100644 --- a/test/hwasan/TestCases/heap-buffer-overflow.c +++ b/test/hwasan/TestCases/heap-buffer-overflow.c @@ -43,7 +43,6 @@ int main(int argc, char **argv) { // CHECK80-RIGHT: allocated heap chunk; size: 32 offset: // CHECK80-RIGHT: is located 50 bytes to the right of 30-byte region // -// CHECKm30: allocated heap chunk; size: 32 offset: 2 // CHECKm30: is located 30 bytes to the left of 30-byte region // // CHECKMm30: is a large allocated heap chunk; size: 1003520 offset: -30 diff --git a/test/hwasan/TestCases/mem-intrinsics-zero-size.c b/test/hwasan/TestCases/mem-intrinsics-zero-size.c new file mode 100644 index 000000000..bcb8e0771 --- /dev/null +++ b/test/hwasan/TestCases/mem-intrinsics-zero-size.c @@ -0,0 +1,10 @@ +// RUN: %clang_hwasan %s -o %t && %run %t + +#include <string.h> + +int main() { + char a[1]; + memset(a, 0, 0); + memmove(a, a, 0); + memcpy(a, a, 0); +} diff --git a/test/hwasan/TestCases/mem-intrinsics.c b/test/hwasan/TestCases/mem-intrinsics.c new file mode 100644 index 000000000..164bc6d93 --- /dev/null +++ b/test/hwasan/TestCases/mem-intrinsics.c @@ -0,0 +1,37 @@ +// RUN: %clang_hwasan %s -DTEST_NO=1 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE +// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=READ +// RUN: %clang_hwasan %s -DTEST_NO=3 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE +// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER + +// REQUIRES: stable-runtime + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int main() { + char Q[16]; + char P[16]; +#if TEST_NO == 1 + memset(Q, 0, 32); +#elif TEST_NO == 2 + memmove(Q, Q + 16, 16); +#elif TEST_NO == 3 + memcpy(Q, P, 32); +#endif + write(STDOUT_FILENO, "recovered\n", 10); + // WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address + // WRITE: WRITE {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) + // WRITE: Memory tags around the buggy address (one tag corresponds to 16 bytes): + // WRITE: =>{{.*}}[[MEM_TAG]] + // WRITE-NOT: recovered + + // READ: ERROR: HWAddressSanitizer: tag-mismatch on address + // READ: READ {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) + // READ: Memory tags around the buggy address (one tag corresponds to 16 bytes): + // READ: =>{{.*}}[[MEM_TAG]] + // READ-NOT: recovered + + // RECOVER: recovered + return 0; +} diff --git a/test/hwasan/TestCases/stack-history-length.c b/test/hwasan/TestCases/stack-history-length.c index c8583c67c..0aefd40be 100644 --- a/test/hwasan/TestCases/stack-history-length.c +++ b/test/hwasan/TestCases/stack-history-length.c @@ -25,12 +25,12 @@ int main(int argc, char **argv) { OOB(); } -// YES: Previosly allocated frames +// YES: Previously allocated frames // YES: OOB // YES: FUNC // YES: FUNC0 -// NO: Previosly allocated frames +// NO: Previously allocated frames // NO: OOB // NO: FUNC // NO-NOT: FUNC0 diff --git a/test/hwasan/TestCases/stack-uar.c b/test/hwasan/TestCases/stack-uar.c index 0b1faf8b5..863a84017 100644 --- a/test/hwasan/TestCases/stack-uar.c +++ b/test/hwasan/TestCases/stack-uar.c @@ -27,7 +27,7 @@ int main() { // CHECK: READ of size 1 at // CHECK: #0 {{.*}} in main{{.*}}stack-uar.c:[[@LINE-2]] // CHECK: is located in stack of thread - // CHECK: Previosly allocated frames: + // CHECK: Previously allocated frames: // CHECK: Unrelated3 // CHECK: 16 CCC // CHECK: Unrelated2 diff --git a/test/hwasan/TestCases/use-after-free.c b/test/hwasan/TestCases/use-after-free.c index fcdd0771c..03a1771c1 100644 --- a/test/hwasan/TestCases/use-after-free.c +++ b/test/hwasan/TestCases/use-after-free.c @@ -23,7 +23,7 @@ int main() { // CHECK: [[TYPE]] of size 1 at {{.*}} tags: [[PTR_TAG:[0-9a-f][0-9a-f]]]/[[MEM_TAG:[0-9a-f][0-9a-f]]] (ptr/mem) // CHECK: #0 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-2]] // Offset is 5 or 11 depending on left/right alignment. - // CHECK: is a small unallocated heap chunk; size: 16 offset: {{5|11}} + // CHECK: is a small unallocated heap chunk; size: 32 offset: {{5|11}} // CHECK: is located 5 bytes inside of 10-byte region // // CHECK: freed by thread {{.*}} here: diff --git a/test/hwasan/lit.cfg b/test/hwasan/lit.cfg index 3ebba51d0..66008a632 100644 --- a/test/hwasan/lit.cfg +++ b/test/hwasan/lit.cfg @@ -9,14 +9,18 @@ config.name = 'HWAddressSanitizer' + getattr(config, 'name_suffix', 'default') config.test_source_root = os.path.dirname(__file__) # Setup default compiler flags used with -fsanitize=memory option. -clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls", config.target_cflags] + config.debug_info_flags +clang_cflags = [config.target_cflags] + config.debug_info_flags +clang_cxxflags = config.cxx_mode_flags + clang_cflags +clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls"] + clang_cflags clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags def build_invocation(compile_flags): return " " + " ".join([config.clang] + compile_flags) + " " +config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) config.substitutions.append( ("%clang_hwasan ", build_invocation(clang_hwasan_cflags)) ) config.substitutions.append( ("%clangxx_hwasan ", build_invocation(clang_hwasan_cxxflags)) ) +config.substitutions.append( ("%compiler_rt_libdir", config.compiler_rt_libdir) ) default_hwasan_opts_str = ':'.join(['disable_allocator_tagging=1', 'random_tags=0'] + config.default_sanitizer_opts) if default_hwasan_opts_str: diff --git a/test/hwasan/lit.site.cfg.in b/test/hwasan/lit.site.cfg.in index 7453d1b74..e95ea92cd 100644 --- a/test/hwasan/lit.site.cfg.in +++ b/test/hwasan/lit.site.cfg.in @@ -4,6 +4,7 @@ config.name_suffix = "@HWASAN_TEST_CONFIG_SUFFIX@" config.target_cflags = "@HWASAN_TEST_TARGET_CFLAGS@" config.target_arch = "@HWASAN_TEST_TARGET_ARCH@" +config.android_files_to_push = @HWASAN_ANDROID_FILES_TO_PUSH@ # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") diff --git a/test/lit.common.cfg b/test/lit.common.cfg index cdcba5fc9..f06658ff2 100644 --- a/test/lit.common.cfg +++ b/test/lit.common.cfg @@ -55,10 +55,11 @@ config.available_features.add(compiler_id) if config.asan_shadow_scale != '': config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale -# BFD linker in 64-bit android toolchains fails to find libm.so, which is a -# transitive shared library dependency (via asan runtime). +# BFD linker in 64-bit android toolchains fails to find libc++_shared.so, which +# is a transitive shared library dependency (via asan runtime). if config.android: - config.target_cflags += " -pie -fuse-ld=gold -Wl,--enable-new-dtags" + # Prepend the flag so that it can be overridden. + config.target_cflags = "-pie -fuse-ld=gold " + config.target_cflags config.cxx_mode_flags.append('-stdlib=libstdc++') # Clear some environment variables that might affect Clang. @@ -275,9 +276,14 @@ else: config.substitutions.append( ("%darwin_min_target_with_full_runtime_arc_support", "") ) if config.android: + env = os.environ.copy() + if config.android_serial: + env['ANDROID_SERIAL'] = config.android_serial + config.environment['ANDROID_SERIAL'] = config.android_serial + adb = os.environ.get('ADB', 'adb') try: - android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"]).rstrip() + android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip() except (subprocess.CalledProcessError, OSError): lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb) try: @@ -286,6 +292,29 @@ if config.android: lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str)) if android_api_level >= 26: config.available_features.add('android-26') + if android_api_level >= 28: + config.available_features.add('android-28') + + # Prepare the device. + android_tmpdir = '/data/local/tmp/Output' + subprocess.check_call([adb, "shell", "mkdir", "-p", android_tmpdir], env=env) + for file in config.android_files_to_push: + subprocess.check_call([adb, "push", file, android_tmpdir], env=env) + +if config.host_os == 'Linux': + # detect whether we are using glibc, and which version + # NB: 'ldd' is just one of the tools commonly installed as part of glibc + ldd_ver_cmd = subprocess.Popen(['ldd', '--version'], + stdout=subprocess.PIPE, + env={'LANG': 'C'}) + sout, _ = ldd_ver_cmd.communicate() + ver_line = sout.splitlines()[0] + if ver_line.startswith(b"ldd "): + from distutils.version import LooseVersion + ver = LooseVersion(ver_line.split()[-1].decode()) + # 2.27 introduced some incompatibilities + if ver >= LooseVersion("2.27"): + config.available_features.add("glibc-2.27") sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov") if os.path.exists(sancovcc_path): @@ -342,6 +371,9 @@ if config.lto_supported: if config.use_newpm: config.lto_flags += ["-fexperimental-new-pass-manager"] +if config.have_rpc_xdr_h: + config.available_features.add('sunrpc') + # Ask llvm-config about assertion mode. try: llvm_config_cmd = subprocess.Popen( diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in index 63d55bfde..4994ca69b 100644 --- a/test/lit.common.configured.in +++ b/test/lit.common.configured.in @@ -36,6 +36,9 @@ set_default("use_thinlto", False) set_default("use_lto", config.use_thinlto) set_default("use_newpm", False) set_default("android", @ANDROID_PYBOOL@) +set_default("android_serial", "@ANDROID_SERIAL_FOR_TESTING@") +set_default("android_files_to_push", []) +set_default("have_rpc_xdr_h", @HAVE_RPC_XDR_H@) config.available_features.add('target-is-%s' % config.target_arch) if config.enable_per_target_runtime_dir: diff --git a/test/lsan/TestCases/Linux/use_tls_dynamic.cc b/test/lsan/TestCases/Linux/use_tls_dynamic.cc index 4d70a46f8..8093d6f0e 100644 --- a/test/lsan/TestCases/Linux/use_tls_dynamic.cc +++ b/test/lsan/TestCases/Linux/use_tls_dynamic.cc @@ -1,4 +1,9 @@ // Test that dynamically allocated TLS space is included in the root set. + +// This is known to be broken with glibc-2.27+ +// https://bugs.llvm.org/show_bug.cgi?id=37804 +// XFAIL: glibc-2.27 + // RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0" // RUN: %clangxx %s -DBUILD_DSO -fPIC -shared -o %t-so.so // RUN: %clangxx_lsan %s -o %t diff --git a/test/msan/Linux/sunrpc.cc b/test/msan/Linux/sunrpc.cc index c92ad632c..edf49c2a5 100644 --- a/test/msan/Linux/sunrpc.cc +++ b/test/msan/Linux/sunrpc.cc @@ -1,3 +1,5 @@ +// REQUIRES: sunrpc + // RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int %s -o %t && \ // RUN: %run %t 2>&1 // RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int -DUNINIT=1 %s -o %t && \ diff --git a/test/msan/Linux/sunrpc_bytes.cc b/test/msan/Linux/sunrpc_bytes.cc index 477637af2..7eb47e178 100644 --- a/test/msan/Linux/sunrpc_bytes.cc +++ b/test/msan/Linux/sunrpc_bytes.cc @@ -1,3 +1,5 @@ +// REQUIRES: sunrpc + // RUN: %clangxx_msan -g -O0 %s -o %t && \ // RUN: %run %t 2>&1 // RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \ diff --git a/test/msan/Linux/sunrpc_string.cc b/test/msan/Linux/sunrpc_string.cc index 350222f5c..723b85592 100644 --- a/test/msan/Linux/sunrpc_string.cc +++ b/test/msan/Linux/sunrpc_string.cc @@ -1,3 +1,5 @@ +// REQUIRES: sunrpc + // RUN: %clangxx_msan -g -O0 %s -o %t && \ // RUN: %run %t 2>&1 // RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \ diff --git a/test/msan/dtls_test.c b/test/msan/dtls_test.c index ee91be2ff..bc1fe609a 100644 --- a/test/msan/dtls_test.c +++ b/test/msan/dtls_test.c @@ -11,6 +11,11 @@ // Reports use-of-uninitialized-value, not analyzed XFAIL: netbsd + + // This is known to be broken with glibc-2.27+ + // https://bugs.llvm.org/show_bug.cgi?id=37804 + XFAIL: glibc-2.27 + */ #ifndef BUILD_SO diff --git a/test/msan/pthread_getname_np.cc b/test/msan/pthread_getname_np.cc index e19b652a7..4827b3a00 100644 --- a/test/msan/pthread_getname_np.cc +++ b/test/msan/pthread_getname_np.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t // The main goal is getting the pthread name back and // FreeBSD based do not support this feature -// UNSUPPORTED: android, netbsd, freebsd +// UNSUPPORTED: android, freebsd // Regression test for a deadlock in pthread_getattr_np @@ -32,7 +32,11 @@ int main(void) { assert(!res); const char *kMyThreadName = "my-thread-name"; +#if defined(__NetBSD__) + res = pthread_setname_np(t, "%s", (void *)kMyThreadName); +#else res = pthread_setname_np(t, kMyThreadName); +#endif assert(!res); char buf[100]; diff --git a/test/profile/instrprof-dlopen-dlclose-gcov.test b/test/profile/instrprof-dlopen-dlclose-gcov.test index 8b1b2e294..36b5dbd26 100644 --- a/test/profile/instrprof-dlopen-dlclose-gcov.test +++ b/test/profile/instrprof-dlopen-dlclose-gcov.test @@ -1,3 +1,6 @@ +# atexit(3) not supported in dlopen(3)ed+dlclose(3)d DSO +XFAIL: netbsd + RUN: mkdir -p %t.d RUN: cd %t.d diff --git a/test/profile/lit.cfg b/test/profile/lit.cfg index 1cd250967..7449650a6 100644 --- a/test/profile/lit.cfg +++ b/test/profile/lit.cfg @@ -67,7 +67,7 @@ config.substitutions.append( ("%clangxx_profuse=", build_invocation(clang_cxxfla config.substitutions.append( ("%clang_lto_profgen=", build_invocation(clang_cflags, True) + " -fprofile-instr-generate=") ) -if config.host_os not in ['Darwin', 'FreeBSD', 'Linux', 'SunOS']: +if config.host_os not in ['Darwin', 'FreeBSD', 'Linux', 'NetBSD', 'SunOS']: config.unsupported = True if config.target_arch in ['armv7l']: diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt index 4e2c80390..23292e548 100644 --- a/test/sanitizer_common/CMakeLists.txt +++ b/test/sanitizer_common/CMakeLists.txt @@ -16,6 +16,13 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID) list(APPEND SUPPORTED_TOOLS lsan) endif() +# FIXME(dliew): Remove this. +# Temporary helper for https://reviews.llvm.org/D55740 +message( + STATUS + "sanitizer_common tests on \"${CMAKE_SYSTEM_NAME}\" will run against " + "\"${SUPPORTED_TOOLS}\"") + # Create a separate config for each tool we support. foreach(tool ${SUPPORTED_TOOLS}) string(TOUPPER ${tool} tool_toupper) diff --git a/test/sanitizer_common/TestCases/FreeBSD/capsicum.cc b/test/sanitizer_common/TestCases/FreeBSD/capsicum.cc index d17f27b38..1bfb6f8d9 100644 --- a/test/sanitizer_common/TestCases/FreeBSD/capsicum.cc +++ b/test/sanitizer_common/TestCases/FreeBSD/capsicum.cc @@ -49,6 +49,12 @@ void test_cap_rights() { rv = cap_rights_get(STDIN_FILENO, &grights); assert(rv == 0); assert(memcmp(&grights, &rights, sizeof(grights)) == 0); + cap_rights_t *iptr = cap_rights_set(&rights, CAP_IOCTL); + assert(iptr); + cap_rights_t *eptr = cap_rights_clear(&rights, CAP_READ); + assert(eptr); + hasit = cap_rights_is_set(&rights, CAP_IOCTL); + assert(hasit == true); printf("rights test: %d\n", rv); } diff --git a/test/sanitizer_common/TestCases/FreeBSD/fdevname.cc b/test/sanitizer_common/TestCases/FreeBSD/fdevname.cc new file mode 100644 index 000000000..252335e9a --- /dev/null +++ b/test/sanitizer_common/TestCases/FreeBSD/fdevname.cc @@ -0,0 +1,44 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <assert.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> + +void test_fdevname() { + int fd = open("/dev/null", O_RDONLY); + char *name; + + printf("test_fdevname\n"); + assert(fd != -1); + assert((name = fdevname(fd))); + close(fd); + + printf("%s\n", name); +} + +void test_fdevname_r() { + int fd = open("/dev/null", O_RDONLY); + char *name; + char buf[5]; + + printf("test_fdevname_r\n"); + assert(fd != -1); + assert((name = fdevname_r(fd, buf, sizeof(buf)))); + close(fd); + + printf("%s\n", name); +} + +int main(void) { + test_fdevname(); + test_fdevname_r(); + // CHECK: test_fdevname + // CHECK: null + // CHECK: test_fdevname_r + // CHECK: null + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/funopen2.cc b/test/sanitizer_common/TestCases/NetBSD/funopen2.cc new file mode 100644 index 000000000..181ad03c9 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/funopen2.cc @@ -0,0 +1,110 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s + +// CHECK: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: CLOSE CALLED +// CHECK-NEXT: SEEK CALLED; off=100, whence=0 +// CHECK-NEXT: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: FLUSH CALLED +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: FLUSH CALLED + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int cookie_var; + +ssize_t f_read(void *cookie, void *buf, size_t len) { + assert(cookie == &cookie_var); + assert(len >= 6); + printf("READ CALLED; len=%zd\n", len); + return strlcpy((char*)buf, "test\n", len); +} + +ssize_t f_write(void *cookie, const void *buf, size_t len) { + assert(cookie == &cookie_var); + char *data = strndup((char*)buf, len); + assert(data); + printf("WRITE CALLED: %s\n", data); + free(data); + return len; +} + +off_t f_seek(void *cookie, off_t off, int whence) { + assert(cookie == &cookie_var); + assert(whence == SEEK_SET); + printf("SEEK CALLED; off=%d, whence=%d\n", (int)off, whence); + return off; +} + +int f_flush(void *cookie) { + assert(cookie == &cookie_var); + printf("FLUSH CALLED\n"); + return 0; +} + +int f_close(void *cookie) { + assert(cookie == &cookie_var); + printf("CLOSE CALLED\n"); + return 0; +} + +int main(void) { + FILE *fp; + char buf[10]; + + // 1. read-only variant + fp = fropen2(&cookie_var, f_read); + assert(fp); + // verify that fileno() does not crash or report nonsense + assert(fileno(fp) == -1); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(!fclose(fp)); + + // 2. write-only variant + fp = fwopen2(&cookie_var, f_write); + assert(fp); + assert(fileno(fp) == -1); + assert(fputs("test", fp) >= 0); + assert(!fclose(fp)); + + // 3. read+write+close + fp = funopen2(&cookie_var, f_read, f_write, NULL, NULL, f_close); + assert(fp); + assert(fileno(fp) == -1); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(fputs("test", fp) >= 0); + assert(!fflush(fp)); + assert(!fclose(fp)); + + // 4. read+seek + fp = funopen2(&cookie_var, f_read, NULL, f_seek, NULL, NULL); + assert(fp); + assert(fileno(fp) == -1); + assert(fseek(fp, 100, SEEK_SET) == 0); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(!fclose(fp)); + + // 5. write+flush + fp = funopen2(&cookie_var, NULL, f_write, NULL, f_flush, NULL); + assert(fp); + assert(fileno(fp) == -1); + assert(fputs("test", fp) >= 0); + assert(!fflush(fp)); + assert(fputs("test", fp) >= 0); + // NB: fclose() also implicitly calls flush + assert(!fclose(fp)); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/md2.cc b/test/sanitizer_common/TestCases/NetBSD/md2.cc index f76a35aac..7738aecdf 100644 --- a/test/sanitizer_common/TestCases/NetBSD/md2.cc +++ b/test/sanitizer_common/TestCases/NetBSD/md2.cc @@ -105,10 +105,10 @@ int main(void) { // CHECK: test1: 'e303e49b34f981c2740cdf809200d51b' // CHECK: test2: 'e303e49b34f981c2740cdf809200d51b' // CHECK: test3: 'e303e49b34f981c2740cdf809200d51b' - // CHECK: test4: 'a409cff8627afa00f3b563cf5f09af05' - // CHECK: test5: 'a409cff8627afa00f3b563cf5f09af05' - // CHECK: test6: '{{.*}}' - // CHECK: test7: '{{.*}}' + // CHECK: test4: '{{.*}}' + // CHECK: test5: '{{.*}}' + // CHECK: test6: 'e303e49b34f981c2740cdf809200d51b' + // CHECK: test7: 'e303e49b34f981c2740cdf809200d51b' return 0; } diff --git a/test/sanitizer_common/TestCases/NetBSD/md4.cc b/test/sanitizer_common/TestCases/NetBSD/md4.cc index 831832691..a319e89a3 100644 --- a/test/sanitizer_common/TestCases/NetBSD/md4.cc +++ b/test/sanitizer_common/TestCases/NetBSD/md4.cc @@ -105,10 +105,10 @@ int main(void) { // CHECK: test1: 'bf78fda2ca35eb7a026bfcdd3d17283d' // CHECK: test2: 'bf78fda2ca35eb7a026bfcdd3d17283d' // CHECK: test3: 'bf78fda2ca35eb7a026bfcdd3d17283d' - // CHECK: test4: '85b3d78ce68be51f710272728fe606af' - // CHECK: test5: '85b3d78ce68be51f710272728fe606af' - // CHECK: test6: '{{.*}}' - // CHECK: test7: '{{.*}}' + // CHECK: test4: '{{.*}}' + // CHECK: test5: '{{.*}}' + // CHECK: test6: 'bf78fda2ca35eb7a026bfcdd3d17283d' + // CHECK: test7: 'bf78fda2ca35eb7a026bfcdd3d17283d' return 0; } diff --git a/test/sanitizer_common/TestCases/NetBSD/md5.cc b/test/sanitizer_common/TestCases/NetBSD/md5.cc index e27997906..aee216818 100644 --- a/test/sanitizer_common/TestCases/NetBSD/md5.cc +++ b/test/sanitizer_common/TestCases/NetBSD/md5.cc @@ -105,8 +105,8 @@ int main(void) { // CHECK: test1: '86e65b1ef4a830af347ac05ab4f0e999' // CHECK: test2: '86e65b1ef4a830af347ac05ab4f0e999' // CHECK: test3: '86e65b1ef4a830af347ac05ab4f0e999' - // CHECK: test4: 'd6798ca88175b5feece4dda691a5b9b5' - // CHECK: test5: 'd6798ca88175b5feece4dda691a5b9b5' + // CHECK: test4: '{{.*}}' + // CHECK: test5: '{{.*}}' // CHECK: test6: '86e65b1ef4a830af347ac05ab4f0e999' // CHECK: test7: '86e65b1ef4a830af347ac05ab4f0e999' diff --git a/test/sanitizer_common/TestCases/NetBSD/sha2.cc b/test/sanitizer_common/TestCases/NetBSD/sha2.cc index 4c9066db8..e905e3b61 100644 --- a/test/sanitizer_common/TestCases/NetBSD/sha2.cc +++ b/test/sanitizer_common/TestCases/NetBSD/sha2.cc @@ -173,10 +173,10 @@ int main(void) { // CHECK-256: test1: 'bb000ddd92a0a2a346f0b531f278af06e370f86932ccafccc892d68d350f80f8' // CHECK-256: test2: 'bb000ddd92a0a2a346f0b531f278af06e370f86932ccafccc892d68d350f80f8' // CHECK-256: test3: 'bb000ddd92a0a2a346f0b531f278af06e370f86932ccafccc892d68d350f80f8' - // CHECK-256: test4: 'bb058583870ed830d9b74b4c24af7fa2ab5684f4d88158a8094a68bcf908dc48' - // CHECK-256: test5: 'bb058583870ed830d9b74b4c24af7fa2ab5684f4d88158a8094a68bcf908dc48' - // CHECK-256: test6: 'cc1c596e07913a44fe35a4d4fd76b4bd6313604fa4264e2e6fbae1db78c24b22' - // CHECK-256: test7: 'cc1c596e07913a44fe35a4d4fd76b4bd6313604fa4264e2e6fbae1db78c24b22' + // CHECK-256: test4: '{{.*}}' + // CHECK-256: test5: '{{.*}}' + // CHECK-256: test6: '{{.*}}' + // CHECK-256: test7: '{{.*}}' // CHECK-256: test8: 'bb000ddd92a0a2a346f0b531f278af06e370f86932ccafccc892d68d350f80f8' // CHECK-256: test9: 'bb000ddd92a0a2a346f0b531f278af06e370f86932ccafccc892d68d350f80f8' @@ -184,10 +184,10 @@ int main(void) { // CHECK-384: test1: 'f450c023b168ebd56ff916ca9b1f1f0010b8c592d28205cc91fa3056f629eed108e8bac864f01ca37a3edee596739e12' // CHECK-384: test2: 'f450c023b168ebd56ff916ca9b1f1f0010b8c592d28205cc91fa3056f629eed108e8bac864f01ca37a3edee596739e12' // CHECK-384: test3: 'f450c023b168ebd56ff916ca9b1f1f0010b8c592d28205cc91fa3056f629eed108e8bac864f01ca37a3edee596739e12' - // CHECK-384: test4: '330d1528c9828d46e200fbfe05cac41717bed2e5f87ba10d47c9d6098e94f5e902ad90d4dd9be0f4347bc026e1206abd' - // CHECK-384: test5: '330d1528c9828d46e200fbfe05cac41717bed2e5f87ba10d47c9d6098e94f5e902ad90d4dd9be0f4347bc026e1206abd' - // CHECK-384: test6: '60686e8385598c69a2309483b91c04a1e0deeef1201730607a1818d097e726a9cbde8f8b8de7ab76c1d347def17f5ab5' - // CHECK-384: test7: '60686e8385598c69a2309483b91c04a1e0deeef1201730607a1818d097e726a9cbde8f8b8de7ab76c1d347def17f5ab5' + // CHECK-384: test4: '{{.*}}' + // CHECK-384: test5: '{{.*}}' + // CHECK-384: test6: '{{.*}}' + // CHECK-384: test7: '{{.*}}' // CHECK-384: test8: 'f450c023b168ebd56ff916ca9b1f1f0010b8c592d28205cc91fa3056f629eed108e8bac864f01ca37a3edee596739e12' // CHECK-384: test9: 'f450c023b168ebd56ff916ca9b1f1f0010b8c592d28205cc91fa3056f629eed108e8bac864f01ca37a3edee596739e12' @@ -195,10 +195,10 @@ int main(void) { // CHECK-512: test1: '0e3f68731c0e2a6a4eab5d713c9a80dc78086b5fa7d2b5ab127277958e68d1b1dee1882b083b0106cd4319de42c0c8f452871364f5baa8a6379690612c6b844e' // CHECK-512: test2: '0e3f68731c0e2a6a4eab5d713c9a80dc78086b5fa7d2b5ab127277958e68d1b1dee1882b083b0106cd4319de42c0c8f452871364f5baa8a6379690612c6b844e' // CHECK-512: test3: '0e3f68731c0e2a6a4eab5d713c9a80dc78086b5fa7d2b5ab127277958e68d1b1dee1882b083b0106cd4319de42c0c8f452871364f5baa8a6379690612c6b844e' - // CHECK-512: test4: '56b925cd62d73643e0f5ab821e062be9157035652cfb6396cb08d84f88981b1a9dae79f3d2707ad4f821d86b5608ae93f71788724328bb6e4ed1704a985d07a7' - // CHECK-512: test5: '56b925cd62d73643e0f5ab821e062be9157035652cfb6396cb08d84f88981b1a9dae79f3d2707ad4f821d86b5608ae93f71788724328bb6e4ed1704a985d07a7' - // CHECK-512: test6: '273b577200f95cfcb1627d94c0e6f3dd1682f63b4dfcc315355a7b90586e4cfd8f65c7cb315bd2b29c7ec0942510ffaceb1f02c7041f45528a6357fd38f2fe39' - // CHECK-512: test7: '273b577200f95cfcb1627d94c0e6f3dd1682f63b4dfcc315355a7b90586e4cfd8f65c7cb315bd2b29c7ec0942510ffaceb1f02c7041f45528a6357fd38f2fe39' + // CHECK-512: test4: '{{.*}}' + // CHECK-512: test5: '{{.*}}' + // CHECK-512: test6: '{{.*}}' + // CHECK-512: test7: '{{.*}}' // CHECK-512: test8: '0e3f68731c0e2a6a4eab5d713c9a80dc78086b5fa7d2b5ab127277958e68d1b1dee1882b083b0106cd4319de42c0c8f452871364f5baa8a6379690612c6b844e' // CHECK-512: test9: '0e3f68731c0e2a6a4eab5d713c9a80dc78086b5fa7d2b5ab127277958e68d1b1dee1882b083b0106cd4319de42c0c8f452871364f5baa8a6379690612c6b844e' diff --git a/test/sanitizer_common/TestCases/Posix/arc4random.cc b/test/sanitizer_common/TestCases/Posix/arc4random.cc new file mode 100644 index 000000000..0a983b58f --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/arc4random.cc @@ -0,0 +1,71 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, darwin, solaris + +#include <cstdlib> +#include <ctime> +#include <cstdio> +#include <inttypes.h> + +void print_buf(unsigned char *buf, size_t buflen) { + printf("buf '"); + for (auto i = 0; i < buflen; i ++) + printf("%" PRIx8, buf[i]); + printf("'\n"); +} + +void test_seed() { +#ifdef __NetBSD__ + time_t now = ::time(nullptr); + arc4random_addrandom((unsigned char *)&now, sizeof(now)); +#endif +} + +void test_arc4random() { + printf("test_arc4random\n"); + auto i = arc4random(); + print_buf((unsigned char *)&i, sizeof(i)); +} + +void test_arc4random_uniform() { + printf("test_arc4random_uniform\n"); + auto i = arc4random_uniform(1024); + print_buf((unsigned char *)&i, sizeof(i)); +} + +void test_arc4random_buf10() { + printf("test_arc4random_buf10\n"); + char buf[10]; +#ifdef __NetBSD__ + arc4random_stir(); +#endif + arc4random_buf(buf, sizeof(buf)); + print_buf((unsigned char *)buf, sizeof(buf)); +} + +void test_arc4random_buf256() { + printf("test_arc4random_buf256\n"); + char buf[256]; +#ifdef __NetBSD__ + arc4random_stir(); +#endif + arc4random_buf(buf, sizeof(buf)); + print_buf((unsigned char *)buf, sizeof(buf)); +} + +int main(void) { + test_seed(); + test_arc4random(); + test_arc4random_uniform(); + test_arc4random_buf10(); + test_arc4random_buf256(); + return 0; + // CHECK: test_arc4random + // CHECK: buf '{{.*}}' + // CHECK: test_arc4random_uniform + // CHECK: buf '{{.*}}' + // CHECK: test_arc4random_buf10 + // CHECK: buf '{{.*}}' + // CHECK: test_arc4random_buf256 + // CHECK: buf '{{.*}}' +} diff --git a/test/sanitizer_common/TestCases/Posix/devname.cc b/test/sanitizer_common/TestCases/Posix/devname.cc index da4bb8853..1495f7d9d 100644 --- a/test/sanitizer_common/TestCases/Posix/devname.cc +++ b/test/sanitizer_common/TestCases/Posix/devname.cc @@ -1,6 +1,7 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s // UNSUPPORTED: linux, solaris +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> @@ -9,11 +10,8 @@ int main(void) { struct stat st; char *name; - if (stat("/dev/null", &st)) - exit(1); - - if (!(name = devname(st.st_rdev, S_ISCHR(st.st_mode) ? S_IFCHR : S_IFBLK))) - exit(1); + assert(!stat("/dev/null", &st)); + assert((name = devname(st.st_rdev, S_ISCHR(st.st_mode) ? S_IFCHR : S_IFBLK))); printf("%s\n", name); diff --git a/test/sanitizer_common/TestCases/Posix/devname_r.cc b/test/sanitizer_common/TestCases/Posix/devname_r.cc index 3a05dae72..ae10a7662 100644 --- a/test/sanitizer_common/TestCases/Posix/devname_r.cc +++ b/test/sanitizer_common/TestCases/Posix/devname_r.cc @@ -4,6 +4,7 @@ #include <sys/cdefs.h> #include <sys/stat.h> +#include <assert.h> #include <stdio.h> #include <stdlib.h> @@ -12,17 +13,14 @@ int main(void) { char name[100]; mode_t type; - if (stat("/dev/null", &st)) - exit(1); + assert(!stat("/dev/null", &st)); type = S_ISCHR(st.st_mode) ? S_IFCHR : S_IFBLK; #if defined(__NetBSD__) - if (devname_r(st.st_rdev, type, name, sizeof(name))) - exit(1); + assert(!devname_r(st.st_rdev, type, name, sizeof(name))); #else - if (!devname_r(st.st_rdev, type, name, sizeof(name))) - exit(1); + assert(devname_r(st.st_rdev, type, name, sizeof(name))); #endif printf("%s\n", name); diff --git a/test/sanitizer_common/TestCases/Posix/feof_fileno_ferror.cc b/test/sanitizer_common/TestCases/Posix/feof_fileno_ferror.cc new file mode 100644 index 000000000..cfcf0e397 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/feof_fileno_ferror.cc @@ -0,0 +1,41 @@ +// RUN: %clangxx -g %s -o %t && %run %t + +#include <assert.h> +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char **argv) { + FILE *fp = fopen(argv[0], "r"); + assert(fp); + + // file should be good upon opening + assert(!feof(fp) && !ferror(fp)); + + // read until EOF + char buf[BUFSIZ]; + while (fread(buf, 1, sizeof buf, fp) != 0) {} + assert(feof(fp)); + + // clear EOF + clearerr(fp); + assert(!feof(fp) && !ferror(fp)); + + // get file descriptor + int fd = fileno(fp); + assert(fd != -1); + + // break the file by closing underlying descriptor + assert(close(fd) != -1); + + // verify that an error is signalled + assert(fread(buf, 1, sizeof buf, fp) == 0); + assert(ferror(fp)); + + // clear error + clearerr(fp); + assert(!feof(fp) && !ferror(fp)); + + // fclose() will return EBADF because of closed fd + assert(fclose(fp) == -1); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fgetc_ungetc_getc.cc b/test/sanitizer_common/TestCases/Posix/fgetc_ungetc_getc.cc new file mode 100644 index 000000000..f895cf194 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/fgetc_ungetc_getc.cc @@ -0,0 +1,19 @@ +// RUN: %clangxx -g %s -o %t && %run %t + +#include <assert.h> +#include <stdio.h> + +int main(int argc, char **argv) { + FILE *fp = fopen(argv[0], "r"); + assert(fp); + + // the file should be at least one character long, always + assert(fgetc(fp) != EOF); + // POSIX guarantees being able to ungetc() at least one character + assert(ungetc('X', fp) != EOF); + // check whether ungetc() worked + assert(getc(fp) == 'X'); + + assert(!fclose(fp)); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fgetln.cc b/test/sanitizer_common/TestCases/Posix/fgetln.cc index e98cf449a..b1b466538 100644 --- a/test/sanitizer_common/TestCases/Posix/fgetln.cc +++ b/test/sanitizer_common/TestCases/Posix/fgetln.cc @@ -1,24 +1,20 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t // UNSUPPORTED: linux +#include <assert.h> #include <stdio.h> #include <stdlib.h> int main(void) { - FILE *fp; - size_t len; - char *s; - - fp = fopen("/etc/hosts", "r"); - if (!fp) - exit(1); + FILE *fp = fopen("/etc/hosts", "r"); + assert(fp); - s = fgetln(fp, &len); + size_t len; + char *s = fgetln(fp, &len); printf("%.*s\n", (int)len, s); - if (fclose(fp) == EOF) - exit(1); + assert(!fclose(fp)); return 0; } diff --git a/test/sanitizer_common/TestCases/Posix/fgets.cc b/test/sanitizer_common/TestCases/Posix/fgets.cc index 8dde5cd1a..6a639f804 100644 --- a/test/sanitizer_common/TestCases/Posix/fgets.cc +++ b/test/sanitizer_common/TestCases/Posix/fgets.cc @@ -1,20 +1,16 @@ // RUN: %clangxx -g %s -o %t && %run %t +#include <assert.h> #include <stdio.h> int main(int argc, char **argv) { - FILE *fp; - char buf[2]; - char *s; - - fp = fopen(argv[0], "r"); - if (!fp) - return 1; + FILE *fp = fopen(argv[0], "r"); + assert(fp); - s = fgets(buf, sizeof(buf), fp); - if (!s) - return 2; + char buf[2]; + char *s = fgets(buf, sizeof(buf), fp); + assert(s); - fclose(fp); + assert(!fclose(fp)); return 0; } diff --git a/test/sanitizer_common/TestCases/Posix/fputc_putc_putchar.cc b/test/sanitizer_common/TestCases/Posix/fputc_putc_putchar.cc new file mode 100644 index 000000000..7e786cd9e --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/fputc_putc_putchar.cc @@ -0,0 +1,13 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s +// CHECK: abc + +#include <assert.h> +#include <stdio.h> + +int main(void) { + assert(fputc('a', stdout) != EOF); + assert(putc('b', stdout) != EOF); + assert(putchar('c') != EOF); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fputs_puts.cc b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc index 8e8f7d384..21bb93aa4 100644 --- a/test/sanitizer_common/TestCases/Posix/fputs_puts.cc +++ b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc @@ -1,18 +1,12 @@ // RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s // CHECK: {{^foobar$}} +#include <assert.h> #include <stdio.h> int main(void) { - int r; - - r = fputs("foo", stdout); - if (r < 0) - return 1; - - r = puts("bar"); - if (r < 0) - return 1; + assert(fputs("foo", stdout) >= 0); + assert(puts("bar") >= 0); return 0; } diff --git a/test/sanitizer_common/TestCases/NetBSD/fts.cc b/test/sanitizer_common/TestCases/Posix/fts.cc index 1461005ef..79c41f7de 100644 --- a/test/sanitizer_common/TestCases/NetBSD/fts.cc +++ b/test/sanitizer_common/TestCases/Posix/fts.cc @@ -1,4 +1,6 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, darwin, solaris #include <sys/param.h> #include <sys/types.h> diff --git a/test/sanitizer_common/TestCases/Posix/funopen.cc b/test/sanitizer_common/TestCases/Posix/funopen.cc new file mode 100644 index 000000000..7d3192488 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/funopen.cc @@ -0,0 +1,91 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s + +// CHECK: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// CHECK-NEXT: WRITE CALLED: test +// CHECK-NEXT: CLOSE CALLED +// CHECK-NEXT: SEEK CALLED; off=100, whence=0 +// CHECK-NEXT: READ CALLED; len={{[0-9]*}} +// CHECK-NEXT: READ: test +// +// UNSUPPORTED: linux, darwin, solaris + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int cookie_var; + +int f_read(void *cookie, char *buf, int len) { + assert(cookie == &cookie_var); + assert(len >= 6); + printf("READ CALLED; len=%d\n", len); + return strlcpy(buf, "test\n", len); +} + +int f_write(void *cookie, const char *buf, int len) { + assert(cookie == &cookie_var); + char *data = strndup(buf, len); + assert(data); + printf("WRITE CALLED: %s\n", data); + free(data); + return len; +} + +off_t f_seek(void *cookie, off_t off, int whence) { + assert(cookie == &cookie_var); + assert(whence == SEEK_SET); + printf("SEEK CALLED; off=%d, whence=%d\n", (int)off, whence); + return off; +} + +int f_close(void *cookie) { + assert(cookie == &cookie_var); + printf("CLOSE CALLED\n"); + return 0; +} + +int main(void) { + FILE *fp; + char buf[10]; + + // 1. read-only variant + fp = fropen(&cookie_var, f_read); + assert(fp); + // verify that fileno() does not crash or report nonsense + assert(fileno(fp) == -1); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(!fclose(fp)); + + // 2. write-only variant + fp = fwopen(&cookie_var, f_write); + assert(fp); + assert(fileno(fp) == -1); + assert(fputs("test", fp) >= 0); + assert(!fclose(fp)); + + // 3. read+write+close + fp = funopen(&cookie_var, f_read, f_write, NULL, f_close); + assert(fp); + assert(fileno(fp) == -1); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(fputs("test", fp) >= 0); + assert(!fclose(fp)); + + // 4. read+seek + fp = funopen(&cookie_var, f_read, NULL, f_seek, NULL); + assert(fp); + assert(fileno(fp) == -1); + assert(fseek(fp, 100, SEEK_SET) == 0); + assert(fgets(buf, sizeof(buf), fp)); + printf("READ: %s", buf); + assert(!fclose(fp)); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/getc_unlocked.cc b/test/sanitizer_common/TestCases/Posix/getc_unlocked.cc new file mode 100644 index 000000000..c4257d130 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/getc_unlocked.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx -g %s -o %t && %run %t + +#include <assert.h> +#include <stdio.h> + +int main(int argc, char **argv) { + FILE *fp = fopen(argv[0], "r"); + assert(fp); + + // the file should be at least one character long, always + assert(getc_unlocked(fp) != EOF); + // POSIX guarantees being able to ungetc() at least one character + // NB: ungetc_unlocked is apparently not present + assert(ungetc('X', fp) != EOF); + // check whether ungetc() works with getc_unlocked() + assert(getc_unlocked(fp) == 'X'); + + assert(!fclose(fp)); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/getfsent.cc b/test/sanitizer_common/TestCases/Posix/getfsent.cc new file mode 100644 index 000000000..687a7a7d4 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/getfsent.cc @@ -0,0 +1,36 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, darwin, solaris + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <fstab.h> + +int main(void) { + printf("getfsent\n"); + + setfsent(); + struct fstab *fentry = getfsent(); + + assert(fentry); + + setfsent(); + struct fstab *pentry = getfsspec(fentry->fs_spec); + assert(pentry); + setfsent(); + struct fstab *wentry = getfsfile(fentry->fs_file); + assert(wentry); + assert(!memcmp(fentry, wentry, sizeof(*wentry))); + assert(!memcmp(pentry, wentry, sizeof(*pentry))); + + printf("First entry: device block '%s', mounted with '%s'\n", + fentry->fs_spec, fentry->fs_mntops); + + endfsent(); + + return 0; + // CHECK: getfsent + // CHECK: First entry: device block '{{.*}}', mounted with '{{.*}}' +} diff --git a/test/sanitizer_common/TestCases/Posix/getusershell.cc b/test/sanitizer_common/TestCases/Posix/getusershell.cc new file mode 100644 index 000000000..c00d75f11 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/getusershell.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +// UNSUPPORTED: android + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +int main(void) { + printf("getusershell\n"); + + setusershell(); + char *fentry = getusershell(); + + printf("First entry: '%s'\n", fentry); + + endusershell(); + + return 0; + // CHECK: getusershell + // CHECK: First entry: '{{.*}}' +} diff --git a/test/sanitizer_common/TestCases/Posix/lstat.cc b/test/sanitizer_common/TestCases/Posix/lstat.cc index 37237d821..01c2ea83d 100644 --- a/test/sanitizer_common/TestCases/Posix/lstat.cc +++ b/test/sanitizer_common/TestCases/Posix/lstat.cc @@ -1,16 +1,14 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t +#include <assert.h> #include <stdlib.h> #include <sys/stat.h> int main(void) { struct stat st; - if (lstat("/dev/null", &st)) - exit(1); - - if (!S_ISCHR(st.st_mode)) - exit(1); + assert(!lstat("/dev/null", &st)); + assert(S_ISCHR(st.st_mode)); return 0; } diff --git a/test/sanitizer_common/TestCases/Posix/popen.cc b/test/sanitizer_common/TestCases/Posix/popen.cc new file mode 100644 index 000000000..6bf6255a6 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/popen.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s +// CHECK: 1 +// CHECK-NEXT: 2 + +#include <assert.h> +#include <stdio.h> + +int main(void) { + // use a tool that produces different output than input to verify + // that everything worked correctly + FILE *fp = popen("sort", "w"); + assert(fp); + + // verify that fileno() returns a meaningful descriptor (needed + // for the implementation of TSan) + assert(fileno(fp) != -1); + + assert(fputs("2\n", fp) >= 0); + assert(fputs("1\n", fp) >= 0); + assert(pclose(fp) == 0); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/putc_putchar_unlocked.cc b/test/sanitizer_common/TestCases/Posix/putc_putchar_unlocked.cc new file mode 100644 index 000000000..12c35c220 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/putc_putchar_unlocked.cc @@ -0,0 +1,12 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s +// CHECK: bc + +#include <assert.h> +#include <stdio.h> + +int main(void) { + assert(putc_unlocked('b', stdout) != EOF); + assert(putchar_unlocked('c') != EOF); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/regex.cc b/test/sanitizer_common/TestCases/Posix/regex.cc index 8a4fb3885..3727f0132 100644 --- a/test/sanitizer_common/TestCases/NetBSD/regex.cc +++ b/test/sanitizer_common/TestCases/Posix/regex.cc @@ -1,10 +1,16 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: darwin, solaris #include <assert.h> #include <regex.h> #include <stdio.h> #include <stdlib.h> +#ifndef __arraycount +#define __arraycount(a) ((sizeof(a) / sizeof(a[0]))) +#endif + void test_matched(const regex_t *preg, const char *string) { int rv = regexec(preg, string, 0, NULL, 0); if (!rv) @@ -33,37 +39,6 @@ void test_print_matches(const regex_t *preg, const char *string) { abort(); } -void test_nsub(const regex_t *preg, const char *string) { - regmatch_t rm[10]; - int rv = regexec(preg, string, __arraycount(rm), rm, 0); - if (!rv) { - char buf[1024]; - ssize_t ss = regnsub(buf, __arraycount(buf), "\\1xyz", rm, string); - assert(ss != -1); - - printf("'%s' -> '%s'\n", string, buf); - } else if (rv == REG_NOMATCH) - printf("%s: not-matched\n", string); - else - abort(); -} - -void test_asub(const regex_t *preg, const char *string) { - regmatch_t rm[10]; - int rv = regexec(preg, string, __arraycount(rm), rm, 0); - if (!rv) { - char *buf; - ssize_t ss = regasub(&buf, "\\1xyz", rm, string); - assert(ss != -1); - - printf("'%s' -> '%s'\n", string, buf); - free(buf); - } else if (rv == REG_NOMATCH) - printf("%s: not-matched\n", string); - else - abort(); -} - int main(void) { printf("regex\n"); @@ -76,9 +51,6 @@ int main(void) { test_print_matches(®ex, "ABC"); - test_nsub(®ex, "ABC DEF"); - test_asub(®ex, "GHI JKL"); - regfree(®ex); rv = regcomp(®ex, "[[:upp:]]", 0); @@ -93,8 +65,6 @@ int main(void) { // CHECK: ABC: matched // CHECK: matched[0]='AB' // CHECK: matched[1]='B' - // CHECK: 'ABC DEF' -> 'Bxyz' - // CHECK: 'GHI JKL' -> 'Hxyz' // CHECK: error:{{.*}} return 0; diff --git a/test/sanitizer_common/TestCases/Posix/sl_add.cc b/test/sanitizer_common/TestCases/Posix/sl_add.cc new file mode 100644 index 000000000..4da70c788 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/sl_add.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, darwin, solaris + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stringlist.h> + +int main(void) { + printf("sl_add\n"); + + StringList *sl = sl_init(); + assert(sl); + char *p = strdup("entry"); + assert(!sl_add(sl, p)); + char *entry = sl_find(sl, "entry"); + assert(!strcmp(entry, p)); + printf("Found '%s'\n", entry); + sl_free(sl, 1); + + return 0; + // CHECK: sl_add + // CHECK: Found '{{.*}}' +} diff --git a/test/sanitizer_common/TestCases/NetBSD/strtonum.cc b/test/sanitizer_common/TestCases/Posix/strtonum.cc index 2f47a3030..22346b2e1 100644 --- a/test/sanitizer_common/TestCases/NetBSD/strtonum.cc +++ b/test/sanitizer_common/TestCases/Posix/strtonum.cc @@ -1,4 +1,6 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, darwin, solaris #define _OPENBSD_SOURCE diff --git a/test/sanitizer_common/TestCases/NetBSD/vis.cc b/test/sanitizer_common/TestCases/Posix/vis.cc index 89ea259e5..15f1bc949 100644 --- a/test/sanitizer_common/TestCases/NetBSD/vis.cc +++ b/test/sanitizer_common/TestCases/Posix/vis.cc @@ -1,4 +1,6 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// +// UNSUPPORTED: linux, solaris, darwin #include <ctype.h> #include <err.h> diff --git a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/hard_rss_limit_mb_test.cc index 3013a3c3f..e01d416cb 100644 --- a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc +++ b/test/sanitizer_common/TestCases/hard_rss_limit_mb_test.cc @@ -16,8 +16,7 @@ // XFAIL: msan // XFAIL: ubsan -// https://github.com/google/sanitizers/issues/981 -// UNSUPPORTED: android-26 +// UNSUPPORTED: freebsd, solaris, darwin #include <string.h> #include <stdio.h> diff --git a/test/tsan/Darwin/ignore-noninstrumented.mm b/test/tsan/Darwin/ignore-noninstrumented.mm index 668a76a46..88d39268f 100644 --- a/test/tsan/Darwin/ignore-noninstrumented.mm +++ b/test/tsan/Darwin/ignore-noninstrumented.mm @@ -1,4 +1,7 @@ -// Check that ignore_noninstrumented_modules=1 suppresses races from system libraries on OS X. +// Check that ignore_noninstrumented_modules=1 suppresses reporting races from +// system libraries on OS X. There are currently false positives coming from +// libxpc, libdispatch, CoreFoundation and others, because these libraries use +// TSan-invisible atomics as synchronization. // RUN: %clang_tsan %s -o %t -framework Foundation diff --git a/test/tsan/Darwin/ignored-interceptors.mm b/test/tsan/Darwin/ignored-interceptors.mm deleted file mode 100644 index b2e40f07d..000000000 --- a/test/tsan/Darwin/ignored-interceptors.mm +++ /dev/null @@ -1,55 +0,0 @@ -// Check that ignore_interceptors_accesses=1 suppresses reporting races from -// system libraries on OS X. There are currently false positives coming from -// libxpc, libdispatch, CoreFoundation and others, because these libraries use -// TSan-invisible atomics as synchronization. - -// RUN: %clang_tsan %s -o %t -framework Foundation - -// Check that without the flag, there are false positives. -// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0 %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE - -// With ignore_interceptors_accesses=1, no races are reported. -// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0:ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s - -// With ignore_interceptors_accesses=1, races in user's code are still reported. -// RUN: %env_tsan_opts=ignore_noninstrumented_modules=0:ignore_interceptors_accesses=1 %deflake %run %t race 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RACE - -#import <Foundation/Foundation.h> - -#import "../test.h" - -long global; - -void *Thread1(void *x) { - barrier_wait(&barrier); - global = 42; - return NULL; -} - -void *Thread2(void *x) { - global = 43; - barrier_wait(&barrier); - return NULL; -} - -int main(int argc, char *argv[]) { - fprintf(stderr, "Hello world.\n"); - - // NSUserDefaults uses XPC which triggers the false positive. - NSDictionary *d = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; - - if (argc > 1 && strcmp(argv[1], "race") == 0) { - barrier_init(&barrier, 2); - pthread_t t[2]; - pthread_create(&t[0], NULL, Thread1, NULL); - pthread_create(&t[1], NULL, Thread2, NULL); - pthread_join(t[0], NULL); - pthread_join(t[1], NULL); - } - - fprintf(stderr, "Done.\n"); -} - -// CHECK: Hello world. -// CHECK-RACE: SUMMARY: ThreadSanitizer: data race -// CHECK: Done. diff --git a/test/tsan/Darwin/objc-synchronize-cycle-tagged.mm b/test/tsan/Darwin/objc-synchronize-cycle-tagged.mm new file mode 100644 index 000000000..5806e8af9 --- /dev/null +++ b/test/tsan/Darwin/objc-synchronize-cycle-tagged.mm @@ -0,0 +1,42 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -fobjc-arc %darwin_min_target_with_full_runtime_arc_support +// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=SIX +// RUN: not %run %t 7 2>&1 | FileCheck %s --check-prefix=SEVEN + +#import <Foundation/Foundation.h> + +static bool isTaggedPtr(id obj) { + uintptr_t ptr = (uintptr_t) obj; + return (ptr & 0x8000000000000001ull) != 0; +} + +int main(int argc, char* argv[]) { + assert(argc == 2); + int arg = atoi(argv[1]); + + @autoreleasepool { + NSObject* obj = [NSObject new]; + NSObject* num1 = @7; + NSObject* num2 = [NSNumber numberWithInt:arg]; + + assert(!isTaggedPtr(obj)); + assert(isTaggedPtr(num1) && isTaggedPtr(num2)); + + // obj -> num1 (includes num2) + @synchronized(obj) { + @synchronized(num1) { + } + } + + // num2 -> obj1 + @synchronized(num2) { + @synchronized(obj) { +// SEVEN: ThreadSanitizer: lock-order-inversion (potential deadlock) + } + } + } + + NSLog(@"PASS"); +// SIX-NOT: ThreadSanitizer +// SIX: PASS + return 0; +} diff --git a/test/tsan/Darwin/objc-synchronize-cycle.mm b/test/tsan/Darwin/objc-synchronize-cycle.mm new file mode 100644 index 000000000..fb8163115 --- /dev/null +++ b/test/tsan/Darwin/objc-synchronize-cycle.mm @@ -0,0 +1,31 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -fobjc-arc %darwin_min_target_with_full_runtime_arc_support +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED + +#import <Foundation/Foundation.h> + +int main() { + @autoreleasepool { + NSObject* obj1 = [NSObject new]; + NSObject* obj2 = [NSObject new]; + + // obj1 -> obj2 + @synchronized(obj1) { + @synchronized(obj2) { + } + } + + // obj1 -> obj1 + @synchronized(obj2) { + @synchronized(obj1) { +// CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) + } + } + } + + NSLog(@"PASS"); +// DISABLED-NOT: ThreadSanitizer +// DISABLED: PASS + return 0; +} diff --git a/test/tsan/Darwin/objc-synchronize-nested-recursive.mm b/test/tsan/Darwin/objc-synchronize-nested-recursive.mm new file mode 100644 index 000000000..ab6643e5c --- /dev/null +++ b/test/tsan/Darwin/objc-synchronize-nested-recursive.mm @@ -0,0 +1,35 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -fobjc-arc %darwin_min_target_with_full_runtime_arc_support +// RUN: %run %t 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +int main() { + @autoreleasepool { + NSObject* obj1 = [NSObject new]; + NSObject* obj2 = [NSObject new]; + + @synchronized(obj1) { + @synchronized(obj1) { + NSLog(@"nested 1-1"); +// CHECK: nested 1-1 + } + } + + @synchronized(obj1) { + @synchronized(obj2) { + @synchronized(obj1) { + @synchronized(obj2) { + NSLog(@"nested 1-2-1-2"); +// CHECK: nested 1-2-1-2 + } + } + } + } + + } + + NSLog(@"PASS"); +// CHECK-NOT: ThreadSanitizer +// CHECK: PASS + return 0; +} diff --git a/test/tsan/deadlock_detector_stress_test.cc b/test/tsan/deadlock_detector_stress_test.cc index bbaaabbb3..f3d2fc712 100644 --- a/test/tsan/deadlock_detector_stress_test.cc +++ b/test/tsan/deadlock_detector_stress_test.cc @@ -1,12 +1,12 @@ // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex -// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND -// RUN: %env_tsan_opts=detect_deadlocks=1:second_deadlock_stack=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND +// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND +// RUN: %env_tsan_opts=second_deadlock_stack=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock -// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s +// RUN: %deflake %run %t | FileCheck %s // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock -// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD +// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRecursiveMutex -// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC +// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC #include "test.h" #undef NDEBUG #include <assert.h> diff --git a/test/tsan/ignored-interceptors-mmap.cc b/test/tsan/ignored-interceptors-mmap.cc index 4686e8eb3..bb43250a6 100644 --- a/test/tsan/ignored-interceptors-mmap.cc +++ b/test/tsan/ignored-interceptors-mmap.cc @@ -1,10 +1,12 @@ // RUN: %clangxx_tsan -O0 %s -o %t -// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NORMAL -// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE +// RUN: %run %t ignore 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE // XFAIL: freebsd,netbsd -#include <errno.h> #include <sys/mman.h> +#include <string.h> +#include <assert.h> +#include <atomic> #include "test.h" @@ -15,48 +17,45 @@ void AnnotateIgnoreWritesBegin(const char *f, int l); void AnnotateIgnoreWritesEnd(const char *f, int l); } -void *global_p; +// Use atomic to ensure we do not have a race for the pointer value itself. We +// only want to check races in the mmap'd memory to isolate the test that mmap +// respects ignore annotations. +std::atomic<int*> global_p; -int mmap_and_ignore_reads_and_writes() { +void mmap_ignored(bool ignore) { const size_t kSize = sysconf(_SC_PAGESIZE); - void *p = mmap(0, kSize, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANON, -1, 0); - if (p == MAP_FAILED) - return printf("mmap failed with %d\n", errno); - munmap(p, kSize); - - void *new_p = mmap(p, kSize, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANON, -1, 0); - if (p == MAP_FAILED || p != new_p) - return printf("second mmap failed with %d\n", errno); - - AnnotateIgnoreWritesBegin(__FILE__, __LINE__); - global_p = p; - AnnotateIgnoreWritesEnd(__FILE__, __LINE__); + + if (ignore) AnnotateIgnoreWritesBegin(__FILE__, __LINE__); + void *p = mmap(0, kSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + if (ignore) AnnotateIgnoreWritesEnd(__FILE__, __LINE__); + + // Use relaxed to retain the race between the mmap call and the memory write + global_p.store((int *)p, std::memory_order_relaxed); barrier_wait(&barrier); - return 0; } -void *Thread(void *a) { +void *WriteToMemory(void *unused) { barrier_wait(&barrier); - - ((int*)global_p)[1] = 10; - printf("Read the zero value from mmapped memory %d\n", ((int*)global_p)[1]); + global_p[0] = 7; return 0; } -int main() { +// Create race between allocating (mmap) and writing memory +int main(int argc, const char *argv[]) { + bool ignore = (argc > 1) && (strcmp(argv[1], "ignore") == 0); + barrier_init(&barrier, 2); pthread_t t; - pthread_create(&t, 0, Thread, 0); - if (mmap_and_ignore_reads_and_writes()) - return 1; + pthread_create(&t, 0, WriteToMemory, 0); + mmap_ignored(ignore); pthread_join(t, 0); + + assert(global_p[0] == 7); printf("OK\n"); return 0; } -// CHECK-NORMAL: WARNING: ThreadSanitizer: data race -// CHECK-NORMAL: OK -// CHECK-IGNORE_NOT: WARNING: ThreadSanitizer: data race +// CHECK-RACE: WARNING: ThreadSanitizer: data race +// CHECK-RACE: OK +// CHECK-IGNORE-NOT: WARNING: ThreadSanitizer: data race // CHECK-IGNORE: OK diff --git a/test/tsan/mutex_cycle2.c b/test/tsan/mutex_cycle2.c index 32659d4ee..0dc96d07c 100644 --- a/test/tsan/mutex_cycle2.c +++ b/test/tsan/mutex_cycle2.c @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan %s -o %t -// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: not %run %t 2>&1 | FileCheck %s // RUN: %env_tsan_opts=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s // RUN: %env_tsan_opts=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: echo "deadlock:main" > %t.supp diff --git a/test/tsan/sunrpc.cc b/test/tsan/sunrpc.cc index 5cfb5344e..8e32d6d30 100644 --- a/test/tsan/sunrpc.cc +++ b/test/tsan/sunrpc.cc @@ -1,3 +1,5 @@ +// REQUIRES: sunrpc + // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s #include <pthread.h> diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-lvalue.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-lvalue.cpp new file mode 100644 index 000000000..97d4b4623 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-lvalue.cpp @@ -0,0 +1,36 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +typedef char *__attribute__((align_value(0x8000))) aligned_char; + +struct ac_struct { + aligned_char a; +}; + +char *load_from_ac_struct(struct ac_struct *x) { + return x->a; +} + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + struct ac_struct x; + x.a = ptr + 1; // FIXME: it is weird that this does not also have an assumption. + load_from_ac_struct(&x); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-9]]:13: runtime error: assumption of 32768 byte alignment for pointer of type 'aligned_char' (aka 'char *') failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-17]]:30: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-paramvar.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-paramvar.cpp new file mode 100644 index 000000000..774ba90fb --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-align_value-on-paramvar.cpp @@ -0,0 +1,30 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +char *passthrough(__attribute__((align_value(0x8000))) char *x) { + return x; +} + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + passthrough(ptr + 1); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-7]]:10: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-9]]:34: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + // FIXME: shouldn't there be an assumption on the caller's side too? + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function-variable.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function-variable.cpp new file mode 100644 index 000000000..c71cb1e1b --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function-variable.cpp @@ -0,0 +1,33 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +char *__attribute__((alloc_align(2))) +passthrough(char *x, unsigned long alignment) { + return x; +} + +unsigned long alignment; + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + alignment = 0x8000; + + passthrough(ptr + 1, alignment); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:3: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-14]]:22: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function.cpp new file mode 100644 index 000000000..db22e3a8f --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-alloc_align-on-function.cpp @@ -0,0 +1,29 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +char *__attribute__((alloc_align(2))) +passthrough(char *x, unsigned long alignment) { + return x; +} + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + passthrough(ptr + 1, 0x8000); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:3: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-10]]:22: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp new file mode 100644 index 000000000..33aa132f6 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp @@ -0,0 +1,28 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +char *__attribute__((assume_aligned(0x8000, 1))) passthrough(char *x) { + return x; +} + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(3); + + passthrough(ptr + 2); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:3: runtime error: assumption of 32768 byte alignment (with offset of 1 byte) for pointer of type 'char *' failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-9]]:22: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: offset address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function.cpp new file mode 100644 index 000000000..202c0ce00 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-attribute-assume_aligned-on-function.cpp @@ -0,0 +1,28 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +char *__attribute__((assume_aligned(0x8000))) passthrough(char *x) { + return x; +} + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + passthrough(ptr + 1); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:3: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-9]]:22: note: alignment assumption was specified here + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-blacklist.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-blacklist.cpp new file mode 100644 index 000000000..c0c7b373f --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-blacklist.cpp @@ -0,0 +1,20 @@ +// RUN: %clang -fsanitize=alignment -fno-sanitize-recover=alignment -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " + +// RUN: rm -f %tmp +// RUN: echo "[alignment]" >> %tmp +// RUN: echo "fun:main" >> %tmp +// RUN: %clang -fsanitize=alignment -fno-sanitize-recover=alignment -fsanitize-blacklist=%tmp -O0 %s -o %t && %run %t 2>&1 + +#include <stdlib.h> + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + __builtin_assume_aligned(ptr + 1, 0x8000); + // CHECK: {{.*}}alignment-assumption-blacklist.cpp:[[@LINE-1]]:32: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params-variable.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params-variable.cpp new file mode 100644 index 000000000..cc4e1f218 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params-variable.cpp @@ -0,0 +1,27 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +volatile long offset; + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(3); + + offset = 1; + + __builtin_assume_aligned(ptr + 2, 0x8000, offset); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:32: runtime error: assumption of 32768 byte alignment (with offset of 1 byte) for pointer of type 'char *' failed + // CHECK: 0x{{.*}}: note: offset address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params.cpp new file mode 100644 index 000000000..724abd540 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-three-params.cpp @@ -0,0 +1,23 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(3); + + __builtin_assume_aligned(ptr + 2, 0x8000, 1); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:32: runtime error: assumption of 32768 byte alignment (with offset of 1 byte) for pointer of type 'char *' failed + // CHECK: 0x{{.*}}: note: offset address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-two-params.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-two-params.cpp new file mode 100644 index 000000000..2737f3d08 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-builtin_assume_aligned-two-params.cpp @@ -0,0 +1,23 @@ +// RUN: %clang -x c -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + __builtin_assume_aligned(ptr + 1, 0x8000); + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-1]]:32: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-openmp.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-openmp.cpp new file mode 100644 index 000000000..482316ee2 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-openmp.cpp @@ -0,0 +1,28 @@ +// RUN: %clang -x c -fsanitize=alignment -fopenmp-simd -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -fopenmp-simd -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -fopenmp-simd -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c -fsanitize=alignment -fopenmp-simd -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +// RUN: %clang -x c++ -fsanitize=alignment -fopenmp-simd -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -fopenmp-simd -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -fopenmp-simd -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" +// RUN: %clang -x c++ -fsanitize=alignment -fopenmp-simd -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not=" assumption " --implicit-check-not="note:" --implicit-check-not="error:" + +#include <stdlib.h> + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + char *data = ptr + 1; + + data[0] = 0; + +#pragma omp for simd aligned(data : 0x8000) + for(int x = 0; x < 1; x++) + data[x] = data[x]; + // CHECK: {{.*}}alignment-assumption-{{.*}}.cpp:[[@LINE-3]]:30: runtime error: assumption of 32768 byte alignment for pointer of type 'char *' failed + // CHECK: 0x{{.*}}: note: address is {{.*}} aligned, misalignment offset is {{.*}} byte + + free(ptr); + + return 0; +} diff --git a/test/ubsan/TestCases/Pointer/alignment-assumption-summary.cpp b/test/ubsan/TestCases/Pointer/alignment-assumption-summary.cpp new file mode 100644 index 000000000..cc7769a06 --- /dev/null +++ b/test/ubsan/TestCases/Pointer/alignment-assumption-summary.cpp @@ -0,0 +1,17 @@ +// RUN: %clangxx -fsanitize=alignment %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOTYPE +// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TYPE +// REQUIRES: !ubsan-standalone && !ubsan-standalone-static + +#include <stdlib.h> + +int main(int argc, char* argv[]) { + char *ptr = (char *)malloc(2); + + __builtin_assume_aligned(ptr + 1, 0x8000); + // CHECK-NOTYPE: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:32 + // CHECK-TYPE: SUMMARY: UndefinedBehaviorSanitizer: alignment-assumption {{.*}}summary.cpp:[[@LINE-2]]:32 + free(ptr); + + return 0; +} diff --git a/test/ubsan_minimal/TestCases/alignment-assumption.c b/test/ubsan_minimal/TestCases/alignment-assumption.c new file mode 100644 index 000000000..ed6fff359 --- /dev/null +++ b/test/ubsan_minimal/TestCases/alignment-assumption.c @@ -0,0 +1,17 @@ +// RUN: %clang -fsanitize=alignment %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK + +#include <stdlib.h> + +int main(int argc, char* argv[]) { +// CHECK-NOT: alignment-assumption + +char *ptr = (char *)malloc(2); + +__builtin_assume_aligned(ptr + 1, 0x8000); +// CHECK: alignment-assumption +// CHECK-NOT: alignment-assumption + +free(ptr); + +return 0; +} |