summaryrefslogtreecommitdiff
path: root/lib/ubsan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ubsan')
-rw-r--r--lib/ubsan/CMakeLists.txt44
-rw-r--r--lib/ubsan/Makefile.mk5
-rw-r--r--lib/ubsan/lit_tests/CMakeLists.txt5
-rw-r--r--lib/ubsan/lit_tests/Float/cast-overflow.cpp13
-rw-r--r--lib/ubsan/lit_tests/Misc/bounds.cpp15
-rw-r--r--lib/ubsan/lit_tests/TypeCheck/vptr.cpp15
-rw-r--r--lib/ubsan/lit_tests/lit.cfg21
-rw-r--r--lib/ubsan/lit_tests/lit.site.cfg.in1
-rw-r--r--lib/ubsan/ubsan.syms1
-rw-r--r--lib/ubsan/ubsan_diag.cc54
-rw-r--r--lib/ubsan/ubsan_handlers.cc18
-rw-r--r--lib/ubsan/ubsan_handlers.h9
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.cc1
-rw-r--r--lib/ubsan/ubsan_type_hash.cc2
-rw-r--r--lib/ubsan/ubsan_value.cc36
-rw-r--r--lib/ubsan/ubsan_value.h11
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) {}