From: Davide Italiano Date: Tue, 5 Feb 2019 17:30:53 +0000 (+0000) Subject: [Obj-C] Fix undefined behaviour(s) in the new NSTaggedDate formatter. X-Git-Tag: llvmorg-10-init~12757 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0d98b771b0e94bf9e4b95a0b39eded4d45f43742;p=platform%2Fupstream%2Fllvm.git [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. llvm-svn: 353191 --- diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 98fc1af..3720560 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::max()) return (uint64_t)-0.0; - TaggedDoubleBits encodedBits = {}; - encodedBits.i = encodedTimeInterval; - DoubleBits decodedBits; + TaggedDoubleBits encodedBits = + llvm::bit_cast(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(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(process_sp->GetObjCLanguageRuntime()); + auto *runtime = llvm::dyn_cast_or_null( + process_sp->GetObjCLanguageRuntime()); if (runtime && runtime->GetFoundationVersion() >= 1600) date_value = decodeTaggedTimeInterval(value_bits << 4); }