Index: lib/ubsan/ubsan_handlers.h =================================================================== --- lib/ubsan/ubsan_handlers.h +++ lib/ubsan/ubsan_handlers.h @@ -97,8 +97,15 @@ /// \brief Handle a VLA with a non-positive bound. RECOVERABLE(vla_bound_not_positive, VLABoundData *Data, ValueHandle Bound) +// Keeping this around for binary compatibility with (sanitized) programs +// compiled with older clangs. struct FloatCastOverflowData { - // FIXME: SourceLocation Loc; + const TypeDescriptor &FromType; + const TypeDescriptor &ToType; +}; + +struct FloatCastOverflowDataV2 { + SourceLocation Loc; const TypeDescriptor &FromType; const TypeDescriptor &ToType; }; Index: lib/ubsan/ubsan_handlers.cc =================================================================== --- lib/ubsan/ubsan_handlers.cc +++ lib/ubsan/ubsan_handlers.cc @@ -290,16 +290,46 @@ Die(); } +static bool looksLikeFloatCastOverflowDataV1(FloatCastOverflowData *Data) { + // First field is either a pointer to filename or a pointer to a + // TypeDescriptor. + u8 *FilenameOrTypeDescriptor = *reinterpret_cast(Data); + + // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer + // (0x0) or TK_Float (0x1). Adding both bytes will be 0 or 1 (for BE or LE). + // If it were a filename, adding two printable characters will not yield such + // a value. + u16 MaybeFromTypeKind = + FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1]; + return MaybeFromTypeKind == 0 || MaybeFromTypeKind == 1; +} + static void handleFloatCastOverflow(FloatCastOverflowData *Data, ValueHandle From, ReportOptions Opts) { - // TODO: Add deduplication once a SourceLocation is generated for this check. - SymbolizedStackHolder CallerLoc(getCallerLocation(Opts.pc)); - Location Loc = CallerLoc; + SymbolizedStackHolder CallerLoc; + Location Loc; + const TypeDescriptor *FromType, *ToType; + + if (looksLikeFloatCastOverflowDataV1(Data)) { + CallerLoc.reset(getCallerLocation(Opts.pc)); + Loc = CallerLoc; + FromType = &Data->FromType; + ToType = &Data->ToType; + } else { + auto DataV2 = reinterpret_cast(Data); + SourceLocation SLoc = DataV2->Loc.acquire(); + if (ignoreReport(SLoc, Opts)) + return; + Loc = SLoc; + FromType = &DataV2->FromType; + ToType = &DataV2->ToType; + } + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") - << Value(Data->FromType, From) << Data->FromType << Data->ToType; + << Value(*FromType, From) << *FromType << *ToType; } void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data, Index: test/ubsan/TestCases/Float/cast-overflow.cpp =================================================================== --- test/ubsan/TestCases/Float/cast-overflow.cpp +++ test/ubsan/TestCases/Float/cast-overflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -fsanitize=float-cast-overflow -g %s -o %t +// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t // RUN: %run %t _ // RUN: env UBSAN_OPTIONS=print_summary=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0 // RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1 @@ -86,42 +86,42 @@ case '0': { // Note that values between 0x7ffffe00 and 0x80000000 may or may not // successfully round-trip, depending on the rounding mode. - // CHECK-0: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int' + // CHECK-0: {{.*}}cast-overflow.cpp:90:27: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int' static int test_int = MaxFloatRepresentableAsInt + 0x80; // CHECK-0: SUMMARY: {{.*}}Sanitizer: undefined-behavior {{.*}}cast-overflow.cpp:[[@LINE-1]] return 0; } case '1': { - // CHECK-1: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int' + // CHECK-1: {{.*}}cast-overflow.cpp:96:27: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int' static int test_int = MinFloatRepresentableAsInt - 0x100; return 0; } case '2': { - // CHECK-2: runtime error: value -1 is outside the range of representable values of type 'unsigned int' + // CHECK-2: {{.*}}cast-overflow.cpp:102:37: runtime error: value -1 is outside the range of representable values of type 'unsigned int' volatile float f = -1.0; volatile unsigned u = (unsigned)f; return 0; } case '3': { - // CHECK-3: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int' + // CHECK-3: {{.*}}cast-overflow.cpp:107:37: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int' static int test_int = (unsigned)(MaxFloatRepresentableAsUInt + 0x100); return 0; } case '4': { - // CHECK-4: runtime error: value {{.*}} is outside the range of representable values of type 'int' + // CHECK-4: {{.*}}cast-overflow.cpp:113:27: runtime error: value {{.*}} is outside the range of representable values of type 'int' static int test_int = Inf; return 0; } case '5': { - // CHECK-5: runtime error: value {{.*}} is outside the range of representable values of type 'int' + // CHECK-5: {{.*}}cast-overflow.cpp:118:27: runtime error: value {{.*}} is outside the range of representable values of type 'int' static int test_int = NaN; return 0; } // Integer -> floating point overflow. case '6': { - // CHECK-6: {{runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'|__int128 not supported}} + // CHECK-6: {{cast-overflow.cpp:126:34: runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'|__int128 not supported}} #if defined(__SIZEOF_INT128__) && !defined(_WIN32) static int test_int = (float)(FloatMaxAsUInt128 + 1); return 0; @@ -138,11 +138,11 @@ // Floating point -> floating point overflow. case '8': - // CHECK-8: runtime error: value 1e+39 is outside the range of representable values of type 'float' + // CHECK-8: {{.*}}cast-overflow.cpp:142:19: runtime error: value 1e+39 is outside the range of representable values of type 'float' return (float)1e39; case '9': volatile long double ld = 300.0; - // CHECK-9: runtime error: value 300 is outside the range of representable values of type 'char' + // CHECK-9: {{.*}}cast-overflow.cpp:146:14: runtime error: value 300 is outside the range of representable values of type 'char' char c = ld; return c; }