[Lldb-commits] [lldb] r353191 - [Obj-C] Fix undefined behaviour(s) in the new NSTaggedDate formatter.

Davide Italiano via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 5 09:30:54 PST 2019


Author: davide
Date: Tue Feb  5 09:30:53 2019
New Revision: 353191

URL: http://llvm.org/viewvc/llvm-project?rev=353191&view=rev
Log:
[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>

Modified:
    lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp

Modified: lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp?rev=353191&r1=353190&r2=353191&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/Cocoa.cpp Tue Feb  5 09:30:53 2019
@@ -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::NSURLSumm
 ///   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
   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::NSDateSum
 
   // 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);
   }




More information about the lldb-commits mailing list