[libcxx-commits] [libcxx] [libc++] Fix UB in <expected> related to "has value" flag (#68552) (PR #68733)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 27 02:08:00 PDT 2023


Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>,
Jan =?utf-8?q?Kokemüller?= <jan.kokemueller at gmail.com>
Message-ID:
In-Reply-To: <llvm/llvm-project/pull/68733/libcxx at github.com>


================
@@ -102,6 +104,44 @@ struct TrackedMove {
   }
 };
 
+// This type has one byte of tail padding where `std::expected` may put its
+// "has value" flag. The constructor will clobber all bytes including the
+// tail padding. With this type we can check that `std::expected` handles
+// the case where the "has value" flag is an overlapping subobject correctly.
+//
+// See https://github.com/llvm/llvm-project/issues/68552 for details.
+template <int constant>
+struct TailClobberer {
+  constexpr TailClobberer() noexcept {
+    if (!std::is_constant_evaluated()) {
+      std::memset(this, constant, sizeof(*this));
+    }
+    // Always set `b` itself to `false` so that the comparison works.
+    b = false;
+  }
+  constexpr TailClobberer(const TailClobberer&) : TailClobberer() {}
----------------
huixie90 wrote:

Can we make this `=default` (or if you need  non-trivial version as well, let's create a another class with the name `NonTriviallyCopyTailClobberer` or something?) , and add a test for `expected` copy constructor and move constructor to test that `expected<TailClobberer, E>`'s copy/move constructor is still `trivial`

https://github.com/llvm/llvm-project/pull/68733


More information about the libcxx-commits mailing list