diff options
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/CMakeLists.txt | 44 | ||||
-rw-r--r-- | lib/ubsan/Makefile.mk | 5 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/Float/cast-overflow.cpp | 13 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/Misc/bounds.cpp | 15 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/TypeCheck/vptr.cpp | 15 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/lit.cfg | 21 | ||||
-rw-r--r-- | lib/ubsan/lit_tests/lit.site.cfg.in | 1 | ||||
-rw-r--r-- | lib/ubsan/ubsan.syms | 1 | ||||
-rw-r--r-- | lib/ubsan/ubsan_diag.cc | 54 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 18 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.h | 9 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.cc | 1 | ||||
-rw-r--r-- | lib/ubsan/ubsan_type_hash.cc | 2 | ||||
-rw-r--r-- | lib/ubsan/ubsan_value.cc | 36 | ||||
-rw-r--r-- | lib/ubsan/ubsan_value.h | 11 |
16 files changed, 165 insertions, 86 deletions
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt index 40d0e897179d9..c8470bc6d3536 100644 --- a/lib/ubsan/CMakeLists.txt +++ b/lib/ubsan/CMakeLists.txt @@ -3,9 +3,12 @@ set(UBSAN_SOURCES ubsan_diag.cc ubsan_handlers.cc + ubsan_value.cc + ) + +set(UBSAN_CXX_SOURCES ubsan_handlers_cxx.cc ubsan_type_hash.cc - ubsan_value.cc ) include_directories(..) @@ -19,31 +22,30 @@ set(UBSAN_RUNTIME_LIBRARIES) if(APPLE) # Build universal binary on APPLE. - add_library(clang_rt.ubsan_osx STATIC - ${UBSAN_SOURCES} - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - ) - set_target_compile_flags(clang_rt.ubsan_osx ${UBSAN_CFLAGS}) - set_target_properties(clang_rt.ubsan_osx PROPERTIES - OSX_ARCHITECTURES "${UBSAN_SUPPORTED_ARCH}") + add_compiler_rt_osx_static_runtime(clang_rt.ubsan_osx + ARCH ${UBSAN_SUPPORTED_ARCH} + SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES} + $<TARGET_OBJECTS:RTSanitizerCommon.osx> + CFLAGS ${UBSAN_CFLAGS}) list(APPEND UBSAN_RUNTIME_LIBRARIES clang_rt.ubsan_osx) else() # Build separate libraries for each target. foreach(arch ${UBSAN_SUPPORTED_ARCH}) - add_library(clang_rt.ubsan-${arch} STATIC - ${UBSAN_SOURCES} - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - ) - set_target_compile_flags(clang_rt.ubsan-${arch} - ${UBSAN_CFLAGS} ${TARGET_${arch}_CFLAGS} - ) - list(APPEND UBSAN_RUNTIME_LIBRARIES clang_rt.ubsan-${arch}) + # Main UBSan runtime. + add_compiler_rt_static_runtime(clang_rt.ubsan-${arch} ${arch} + SOURCES ${UBSAN_SOURCES} + CFLAGS ${UBSAN_CFLAGS} + SYMS ubsan.syms) + # C++-specific parts of UBSan runtime. Requires a C++ ABI library. + add_compiler_rt_static_runtime(clang_rt.ubsan_cxx-${arch} ${arch} + SOURCES ${UBSAN_CXX_SOURCES} + CFLAGS ${UBSAN_CFLAGS} + SYMS ubsan.syms) + list(APPEND UBSAN_RUNTIME_LIBRARIES + clang_rt.san-${arch} + clang_rt.ubsan-${arch} + clang_rt.ubsan_cxx-${arch}) endforeach() endif() - -set_property(TARGET ${UBSAN_RUNTIME_LIBRARIES} APPEND PROPERTY - COMPILE_DEFINITIONS ${UBSAN_COMMON_DEFINITIONS}) -add_clang_compiler_rt_libraries(${UBSAN_RUNTIME_LIBRARIES}) - add_subdirectory(lit_tests) diff --git a/lib/ubsan/Makefile.mk b/lib/ubsan/Makefile.mk index 5702e0e752d83..d5561f41b1526 100644 --- a/lib/ubsan/Makefile.mk +++ b/lib/ubsan/Makefile.mk @@ -11,6 +11,8 @@ ModuleName := ubsan SubDirs := Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file))) +CXXSources := ubsan_type_hash.cc ubsan_handlers_cxx.cc +CSources := $(filter-out $(CXXSources),$(Sources)) ObjNames := $(Sources:%.cc=%.o) Implementation := Generic @@ -20,4 +22,5 @@ Dependencies := $(wildcard $(Dir)/*.h) Dependencies += $(wildcard $(Dir)/../sanitizer_common/*.h) # Define a convenience variable for all the ubsan functions. -UbsanFunctions := $(Sources:%.cc=%) +UbsanFunctions := $(CSources:%.cc=%) +UbsanCXXFunctions := $(CXXSources:%.cc=%) diff --git a/lib/ubsan/lit_tests/CMakeLists.txt b/lib/ubsan/lit_tests/CMakeLists.txt index 565c523ceb492..7e1a13c782d2f 100644 --- a/lib/ubsan/lit_tests/CMakeLists.txt +++ b/lib/ubsan/lit_tests/CMakeLists.txt @@ -7,9 +7,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) # Run UBSan output tests only if we're sure that clang would produce # working binaries. set(UBSAN_TEST_DEPS - clang clang-headers FileCheck count not - ${UBSAN_RUNTIME_LIBRARIES} - ) + ${SANITIZER_COMMON_LIT_TEST_DEPS} + ${UBSAN_RUNTIME_LIBRARIES}) set(UBSAN_TEST_PARAMS ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ) diff --git a/lib/ubsan/lit_tests/Float/cast-overflow.cpp b/lib/ubsan/lit_tests/Float/cast-overflow.cpp index 63410dc87140e..8d9120d586a16 100644 --- a/lib/ubsan/lit_tests/Float/cast-overflow.cpp +++ b/lib/ubsan/lit_tests/Float/cast-overflow.cpp @@ -9,7 +9,6 @@ // RUN: %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6 // FIXME: %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7 // RUN: %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8 -// RUN: %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9 // This test assumes float and double are IEEE-754 single- and double-precision. @@ -36,6 +35,9 @@ int main(int argc, char **argv) { (void)(float)FloatMaxAsUInt128; // ok #endif + float NearlyMinusOne = -0.99999; + unsigned Zero = NearlyMinusOne; // ok + // Build a '+Inf'. char InfVal[] = { 0x00, 0x00, 0x80, 0x7f }; float Inf; @@ -46,6 +48,8 @@ int main(int argc, char **argv) { float NaN; memcpy(&NaN, NaNVal, 4); + double DblInf = (double)Inf; // ok + switch (argv[1][0]) { // FIXME: Produce a source location for these checks and test for it here. @@ -59,8 +63,8 @@ int main(int argc, char **argv) { // CHECK-1: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int' return MinFloatRepresentableAsInt - 0x100; case '2': - // CHECK-2: runtime error: value -0.001 is outside the range of representable values of type 'unsigned int' - return (unsigned)-0.001; + // CHECK-2: runtime error: value -1 is outside the range of representable values of type 'unsigned int' + return (unsigned)-1.0; case '3': // CHECK-3: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int' return (unsigned)(MaxFloatRepresentableAsUInt + 0x100); @@ -91,8 +95,5 @@ int main(int argc, char **argv) { case '8': // CHECK-8: runtime error: value 1e+39 is outside the range of representable values of type 'float' return (float)1e39; - case '9': - // CHECK-9: runtime error: value {{.*}} is outside the range of representable values of type 'double' - return (double)Inf; } } diff --git a/lib/ubsan/lit_tests/Misc/bounds.cpp b/lib/ubsan/lit_tests/Misc/bounds.cpp new file mode 100644 index 0000000000000..07b30d384df96 --- /dev/null +++ b/lib/ubsan/lit_tests/Misc/bounds.cpp @@ -0,0 +1,15 @@ +// RUN: %clang -fsanitize=bounds %s -O3 -o %T/bounds.exe +// RUN: %T/bounds.exe 0 0 0 +// RUN: %T/bounds.exe 1 2 3 +// RUN: %T/bounds.exe 2 0 0 2>&1 | FileCheck %s --check-prefix=CHECK-A-2 +// RUN: %T/bounds.exe 0 3 0 2>&1 | FileCheck %s --check-prefix=CHECK-B-3 +// RUN: %T/bounds.exe 0 0 4 2>&1 | FileCheck %s --check-prefix=CHECK-C-4 + +int main(int argc, char **argv) { + int arr[2][3][4] = {}; + + return arr[argv[1][0] - '0'][argv[2][0] - '0'][argv[3][0] - '0']; + // CHECK-A-2: bounds.cpp:11:10: runtime error: index 2 out of bounds for type 'int [2][3][4]' + // CHECK-B-3: bounds.cpp:11:10: runtime error: index 3 out of bounds for type 'int [3][4]' + // CHECK-C-4: bounds.cpp:11:10: runtime error: index 4 out of bounds for type 'int [4]' +} diff --git a/lib/ubsan/lit_tests/TypeCheck/vptr.cpp b/lib/ubsan/lit_tests/TypeCheck/vptr.cpp index 574a7bef9622d..109e7a824f58b 100644 --- a/lib/ubsan/lit_tests/TypeCheck/vptr.cpp +++ b/lib/ubsan/lit_tests/TypeCheck/vptr.cpp @@ -1,11 +1,13 @@ // RUN: %clang -ccc-cxx -fsanitize=vptr %s -O3 -o %t -// RUN: %t rT && %t mT && %t fT -// RUN: %t rU && %t mU && %t fU +// RUN: %t rT && %t mT && %t fT && %t cT +// RUN: %t rU && %t mU && %t fU && %t cU // RUN: %t rS && %t rV && %t oV // RUN: %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace // RUN: %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace +// RUN: %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace // RUN: %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace // RUN: %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace +// RUN: %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace // RUN: %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace // RUN: %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace @@ -102,5 +104,14 @@ int main(int, char **argv) { // CHECK-OFFSET-NEXT: {{^ \^ ( ~~~~~~~~~~~~)~~~~~~~~~~~ *$}} // CHECK-OFFSET-NEXT: {{^ ( )?vptr for}} 'T' base class of [[DYN_TYPE]] return reinterpret_cast<U*>(p)->v() - 2; + + case 'c': + // CHECK-DOWNCAST: vptr.cpp:[[@LINE+5]]:5: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T' + // CHECK-DOWNCAST-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']] + // CHECK-DOWNCAST-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }} + // CHECK-DOWNCAST-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}} + // CHECK-DOWNCAST-NEXT: {{^ vptr for}} [[DYN_TYPE]] + static_cast<T*>(reinterpret_cast<S*>(p)); + return 0; } } diff --git a/lib/ubsan/lit_tests/lit.cfg b/lib/ubsan/lit_tests/lit.cfg index 9fd3a1aeaa163..ea6ebdf9001f8 100644 --- a/lib/ubsan/lit_tests/lit.cfg +++ b/lib/ubsan/lit_tests/lit.cfg @@ -2,6 +2,14 @@ import os +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if not attr_value: + lit.fatal("No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg " % attr_name) + return attr_value + # Setup config name. config.name = 'UndefinedBehaviorSanitizer' @@ -30,14 +38,6 @@ if llvm_src_root is None: if not llvm_config: DisplayNoConfigMessage() - # Validate that llvm-config points to the same source tree. - llvm_src_root = lit.util.capture(["llvm-config", "--src-root"]).strip() - ubsan_test_src_root = os.path.join(llvm_src_root, "projects", "compiler-rt", - "lib", "ubsan", "lit_tests") - if (os.path.realpath(ubsan_test_src_root) != - os.path.realpath(config.test_source_root)): - DisplayNoConfigMessage() - # Find out the presumed location of generated site config. llvm_obj_root = lit.util.capture(["llvm-config", "--obj-root"]).strip() ubsan_site_cfg = os.path.join(llvm_obj_root, "projects", "compiler-rt", @@ -49,8 +49,9 @@ if llvm_src_root is None: raise SystemExit # Setup attributes common for all compiler-rt projects. -compiler_rt_lit_cfg = os.path.join(llvm_src_root, "projects", "compiler-rt", - "lib", "lit.common.cfg") +compiler_rt_src_root = get_required_attr(config, 'compiler_rt_src_root') +compiler_rt_lit_cfg = os.path.join(compiler_rt_src_root, "lib", + "lit.common.cfg") if not compiler_rt_lit_cfg or not os.path.exists(compiler_rt_lit_cfg): lit.fatal("Can't find common compiler-rt lit config at: %r" % compiler_rt_lit_cfg) diff --git a/lib/ubsan/lit_tests/lit.site.cfg.in b/lib/ubsan/lit_tests/lit.site.cfg.in index b1c6ccf544ea5..07b521af061f7 100644 --- a/lib/ubsan/lit_tests/lit.site.cfg.in +++ b/lib/ubsan/lit_tests/lit.site.cfg.in @@ -4,6 +4,7 @@ config.clang = "@LLVM_BINARY_DIR@/bin/clang" config.host_os = "@HOST_OS@" config.llvm_src_root = "@LLVM_SOURCE_DIR@" +config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" config.target_triple = "@TARGET_TRIPLE@" diff --git a/lib/ubsan/ubsan.syms b/lib/ubsan/ubsan.syms new file mode 100644 index 0000000000000..e74de33f012ce --- /dev/null +++ b/lib/ubsan/ubsan.syms @@ -0,0 +1 @@ +{ __ubsan_*; }; diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc index 57c98e669e90b..3f92761465dee 100644 --- a/lib/ubsan/ubsan_diag.cc +++ b/lib/ubsan/ubsan_diag.cc @@ -14,6 +14,7 @@ #include "ubsan_diag.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_symbolizer.h" #include <stdio.h> @@ -30,7 +31,7 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) { if (!SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module) return Location(Loc); - if (!Info.function) + if (!Info.file) return ModuleLocation(Info.module, Info.module_offset); return SourceLocation(Info.file, Info.line, Info.column); @@ -70,7 +71,7 @@ static void renderLocation(Location Loc) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); if (SLoc.isInvalid()) - RawWrite("<unknown>:"); + Printf("<unknown>:"); else { Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine()); if (SLoc.getColumn()) @@ -86,7 +87,7 @@ static void renderLocation(Location Loc) { Printf("%p:", Loc.getMemoryLocation()); break; case Location::LK_Null: - RawWrite("<unknown>:"); + Printf("<unknown>:"); break; } } @@ -99,7 +100,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) { for (I = 0; Msg[I] && Msg[I] != '%' && I != 63; ++I) Buffer[I] = Msg[I]; Buffer[I] = '\0'; - RawWrite(Buffer); + Printf(Buffer); Msg += I - 1; } else { const Diag::Arg &A = Args[*++Msg - '0']; @@ -108,9 +109,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) { Printf("%s", A.String); break; case Diag::AK_Mangled: { - RawWrite("'"); - RawWrite(Demangle(A.String)); - RawWrite("'"); + Printf("'%s'", Demangle(A.String)); break; } case Diag::AK_SInt: @@ -156,7 +155,8 @@ static Range *upperBound(MemoryLocation Loc, Range *Ranges, } /// Render a snippet of the address space near a location. -static void renderMemorySnippet(MemoryLocation Loc, +static void renderMemorySnippet(const __sanitizer::AnsiColorDecorator &Decor, + MemoryLocation Loc, Range *Ranges, unsigned NumRanges, const Diag::Arg *Args) { const unsigned BytesToShow = 32; @@ -180,9 +180,10 @@ static void renderMemorySnippet(MemoryLocation Loc, unsigned char C = *reinterpret_cast<const unsigned char*>(P); Printf("%s%02x", (P % 8 == 0) ? " " : " ", C); } - RawWrite("\n"); + Printf("\n"); // Emit highlights. + Printf(Decor.Green()); Range *InRange = upperBound(Min, Ranges, NumRanges); for (uptr P = Min; P != Max; ++P) { char Pad = ' ', Byte = ' '; @@ -195,9 +196,9 @@ static void renderMemorySnippet(MemoryLocation Loc, if (InRange && InRange->getStart().getMemoryLocation() <= P) Byte = '~'; char Buffer[] = { Pad, Pad, P == Loc ? '^' : Byte, Byte, 0 }; - RawWrite((P % 8 == 0) ? Buffer : &Buffer[1]); + Printf((P % 8 == 0) ? Buffer : &Buffer[1]); } - RawWrite("\n"); + Printf("%s\n", Decor.Default()); // Go over the line again, and print names for the ranges. InRange = 0; @@ -212,9 +213,9 @@ static void renderMemorySnippet(MemoryLocation Loc, if (InRange && InRange->getStart().getMemoryLocation() == P) { while (Spaces--) - RawWrite(" "); + Printf(" "); renderText(InRange->getText(), Args); - RawWrite("\n"); + Printf("\n"); // FIXME: We only support naming one range for now! break; } @@ -235,37 +236,28 @@ static void renderMemorySnippet(MemoryLocation Loc, } Diag::~Diag() { - bool UseAnsiColor = PrintsToTty(); - if (UseAnsiColor) - RawWrite("\033[1m"); + __sanitizer::AnsiColorDecorator Decor(PrintsToTty()); + SpinMutexLock l(&CommonSanitizerReportMutex); + Printf(Decor.Bold()); renderLocation(Loc); switch (Level) { case DL_Error: - if (UseAnsiColor) - RawWrite("\033[31m"); - RawWrite(" runtime error: "); - if (UseAnsiColor) - RawWrite("\033[0;1m"); + Printf("%s runtime error: %s%s", + Decor.Red(), Decor.Default(), Decor.Bold()); break; case DL_Note: - if (UseAnsiColor) - RawWrite("\033[30m"); - RawWrite(" note: "); - if (UseAnsiColor) - RawWrite("\033[0m"); + Printf("%s note: %s", Decor.Black(), Decor.Default()); break; } renderText(Message, Args); - if (UseAnsiColor) - RawWrite("\033[0m"); - - RawWrite("\n"); + Printf("%s\n", Decor.Default()); if (Loc.isMemoryLocation()) - renderMemorySnippet(Loc.getMemoryLocation(), Ranges, NumRanges, Args); + renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, + NumRanges, Args); } diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 1b02aa0fadf3e..fa93b095d0bb4 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -22,7 +22,7 @@ using namespace __ubsan; namespace __ubsan { const char *TypeCheckKinds[] = { "load of", "store to", "reference binding to", "member access within", - "member call on", "constructor call on" + "member call on", "constructor call on", "downcast of", "downcast of" }; } @@ -183,6 +183,22 @@ void __ubsan::__ubsan_handle_shift_out_of_bounds_abort( Die(); } +void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data, + ValueHandle Index) { + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Value IndexVal(Data->IndexType, Index); + Diag(Loc, DL_Error, "index %0 out of bounds for type %1") + << IndexVal << Data->ArrayType; +} +void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, + ValueHandle Index) { + __ubsan_handle_out_of_bounds(Data, Index); + Die(); +} + void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); Die(); diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index d6a042481ffab..5e237e1aa2de2 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -67,6 +67,15 @@ struct ShiftOutOfBoundsData { RECOVERABLE(shift_out_of_bounds, ShiftOutOfBoundsData *Data, ValueHandle LHS, ValueHandle RHS) +struct OutOfBoundsData { + SourceLocation Loc; + const TypeDescriptor &ArrayType; + const TypeDescriptor &IndexType; +}; + +/// \brief Handle an array index out of bounds error. +RECOVERABLE(out_of_bounds, OutOfBoundsData *Data, ValueHandle Index) + struct UnreachableData { SourceLocation Loc; }; diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc index dcc1f60078d2a..b6cddefeb4f4a 100644 --- a/lib/ubsan/ubsan_handlers_cxx.cc +++ b/lib/ubsan/ubsan_handlers_cxx.cc @@ -42,7 +42,6 @@ static void HandleDynamicTypeCacheMiss( << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; // If possible, say what type it actually points to. - // FIXME: Demangle the type names. DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer); if (!DTI.isValid()) Diag(Pointer, DL_Note, "object has invalid vptr") diff --git a/lib/ubsan/ubsan_type_hash.cc b/lib/ubsan/ubsan_type_hash.cc index 7a9cd28f6ec07..b27aefc16821d 100644 --- a/lib/ubsan/ubsan_type_hash.cc +++ b/lib/ubsan/ubsan_type_hash.cc @@ -116,7 +116,7 @@ __ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize] = { 1 }; static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived, const abi::__class_type_info *Base, sptr Offset) { - if (Derived == Base) + if (Derived->__type_name == Base->__type_name) return Offset == 0; if (const abi::__si_class_type_info *SI = diff --git a/lib/ubsan/ubsan_value.cc b/lib/ubsan/ubsan_value.cc index f17c58989db9c..5d77350d0c403 100644 --- a/lib/ubsan/ubsan_value.cc +++ b/lib/ubsan/ubsan_value.cc @@ -13,6 +13,8 @@ //===----------------------------------------------------------------------===// #include "ubsan_value.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" using namespace __ubsan; @@ -66,16 +68,34 @@ UIntMax Value::getPositiveIntValue() const { /// them to be passed in floating-point registers, so this has little cost). FloatMax Value::getFloatValue() const { CHECK(getType().isFloatTy()); - switch (getType().getFloatBitWidth()) { + if (isInlineFloat()) { + switch (getType().getFloatBitWidth()) { #if 0 - // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion - // from this to 'long double'. - case 16: return *reinterpret_cast<__fp16*>(Val); + // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion + // from '__fp16' to 'long double'. + case 16: { + __fp16 Value; + internal_memcpy(&Value, &Val, 4); + return Value; + } #endif - case 32: return *reinterpret_cast<float*>(Val); - case 64: return *reinterpret_cast<double*>(Val); - case 80: return *reinterpret_cast<long double*>(Val); - case 128: return *reinterpret_cast<long double*>(Val); + case 32: { + float Value; + internal_memcpy(&Value, &Val, 4); + return Value; + } + case 64: { + double Value; + internal_memcpy(&Value, &Val, 8); + return Value; + } + } + } else { + switch (getType().getFloatBitWidth()) { + case 64: return *reinterpret_cast<double*>(Val); + case 80: return *reinterpret_cast<long double*>(Val); + case 128: return *reinterpret_cast<long double*>(Val); + } } UNREACHABLE("unexpected floating point bit width"); } diff --git a/lib/ubsan/ubsan_value.h b/lib/ubsan/ubsan_value.h index e673f7af1d832..54ed5ad1931fb 100644 --- a/lib/ubsan/ubsan_value.h +++ b/lib/ubsan/ubsan_value.h @@ -108,7 +108,8 @@ public: /// integer otherwise. TK_Integer = 0x0000, /// A floating-point type. Low 16 bits are bit width. The value - /// representation is a pointer to the floating-point value. + /// representation is that of bitcasting the floating-point value to an + /// integer type. TK_Float = 0x0001, /// Any other type. The value representation is unspecified. TK_Unknown = 0xffff @@ -162,6 +163,14 @@ class Value { return Bits <= InlineBits; } + /// Is \c Val a (zero-extended) integer representation of a float? + bool isInlineFloat() const { + CHECK(getType().isFloatTy()); + const unsigned InlineBits = sizeof(ValueHandle) * 8; + const unsigned Bits = getType().getFloatBitWidth(); + return Bits <= InlineBits; + } + public: Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {} |