diff options
author | Davide Italiano <davide@freebsd.org> | 2019-02-05 17:30:53 +0000 |
---|---|---|
committer | Davide Italiano <davide@freebsd.org> | 2019-02-05 17:30:53 +0000 |
commit | 0d98b771b0e94bf9e4b95a0b39eded4d45f43742 (patch) | |
tree | 13e3cf81518f0efbafad51e8081c9dd5e4781be9 /lldb/source/Plugins/Language/ObjC/Cocoa.cpp | |
parent | 78dc38ec94229f38c5de74a8930eed623a27350e (diff) | |
download | bcm5719-llvm-0d98b771b0e94bf9e4b95a0b39eded4d45f43742.tar.gz bcm5719-llvm-0d98b771b0e94bf9e4b95a0b39eded4d45f43742.zip |
[Obj-C] Fix undefined behaviour(s) in the new NSTaggedDate formatter.
Type punning through a union -> no good.
double to uint64 to double again -> no good either.
The nice side effect, other than silencing the sanitizer bot
is that it fixes the formatting of some dates, e.g. Jan 1st 1970.
<rdar://problem/47617983>
llvm-svn: 353191
Diffstat (limited to 'lldb/source/Plugins/Language/ObjC/Cocoa.cpp')
-rw-r--r-- | lldb/source/Plugins/Language/ObjC/Cocoa.cpp | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 98fc1afd93e..3720560de59 100644 --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -27,6 +27,7 @@ #include "lldb/Utility/Stream.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/bit.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" @@ -749,24 +750,18 @@ bool lldb_private::formatters::NSURLSummaryProvider( /// distantFuture, except within about 1e-25 second of the reference date. const int TAGGED_DATE_EXPONENT_BIAS = 0x3ef; -typedef union { - struct { - uint64_t fraction:52; // unsigned - uint64_t exponent:11; // signed - uint64_t sign:1; - } repr; - uint64_t i; - double d; -} DoubleBits; -typedef union { - struct { - uint64_t fraction:52; // unsigned - uint64_t exponent:7; // signed - uint64_t sign:1; - uint64_t unused:4; // placeholder for pointer tag bits - } repr; - uint64_t i; -} TaggedDoubleBits; +struct DoubleBits { + uint64_t fraction : 52; // unsigned + uint64_t exponent : 11; // signed + uint64_t sign : 1; +}; + +struct TaggedDoubleBits { + uint64_t fraction : 52; // unsigned + uint64_t exponent : 7; // signed + uint64_t sign : 1; + uint64_t unused : 4; // placeholder for pointer tag bits +}; static uint64_t decodeExponent(uint64_t exp) { // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits @@ -774,24 +769,24 @@ static uint64_t decodeExponent(uint64_t exp) { return llvm::SignExtend64<7>(exp) + TAGGED_DATE_EXPONENT_BIAS; } -static uint64_t decodeTaggedTimeInterval(uint64_t encodedTimeInterval) { +static double decodeTaggedTimeInterval(uint64_t encodedTimeInterval) { if (encodedTimeInterval == 0) return 0.0; if (encodedTimeInterval == std::numeric_limits<uint64_t>::max()) return (uint64_t)-0.0; - TaggedDoubleBits encodedBits = {}; - encodedBits.i = encodedTimeInterval; - DoubleBits decodedBits; + TaggedDoubleBits encodedBits = + llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval); + assert(encodedBits.unused == 0); // Sign and fraction are represented exactly. // Exponent is encoded. - assert(encodedBits.repr.unused == 0); - decodedBits.repr.sign = encodedBits.repr.sign; - decodedBits.repr.fraction = encodedBits.repr.fraction; - decodedBits.repr.exponent = decodeExponent(encodedBits.repr.exponent); + DoubleBits decodedBits; + decodedBits.sign = encodedBits.sign; + decodedBits.fraction = encodedBits.fraction; + decodedBits.exponent = decodeExponent(encodedBits.exponent); - return decodedBits.d; + return llvm::bit_cast<double>(decodedBits); } bool lldb_private::formatters::NSDateSummaryProvider( @@ -868,7 +863,8 @@ bool lldb_private::formatters::NSDateSummaryProvider( // Accomodate for the __NSTaggedDate format introduced in Foundation 1600. if (class_name == g___NSTaggedDate) { - auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); + auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>( + process_sp->GetObjCLanguageRuntime()); if (runtime && runtime->GetFoundationVersion() >= 1600) date_value = decodeTaggedTimeInterval(value_bits << 4); } |