[libcxx-commits] [libcxx] [libcxx] Poison memory in variant destroy (PR #101048)
Chris Cotter via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jul 29 12:48:24 PDT 2024
https://github.com/ccotter updated https://github.com/llvm/llvm-project/pull/101048
>From fc21bfada7e7b07645b395f88efaa1e586de0d69 Mon Sep 17 00:00:00 2001
From: Chris Cotter <ccotter14 at bloomberg.net>
Date: Mon, 29 Jul 2024 13:25:39 -0400
Subject: [PATCH] [libcxx] Poison memory in variant destroy
In the version of `__destroy` that does not destruct any part of
`__data`, MSAN is unable to see that `__data` is logically
uninitialized. This allows false negatives such as the following to
run without any MSAN diagnostic.
```
std::variant<double, int> v;
v.emplace<double>();
double& d = std::get<double>(v);
v.emplace<int>();
if (d) ...
```
With these changes, MSAN reports uninitialized memory:
```
==32202==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x5557b64820aa in main /home/ccotter/variant_msan.cpp:19:9
#1 0x7fbfacd88554 in __libc_start_main /usr/src/debug/glibc-2.17-c758a686/csu/../csu/libc-start.c:266
#2 0x5557b63ed40d in _start (/home/ccotter/a.out+0x3140d)
```
---
libcxx/include/variant | 8 +++++
.../variant.variant/variant_msan.pass.cpp | 34 +++++++++++++++++++
2 files changed, 42 insertions(+)
create mode 100644 libcxx/test/std/utilities/variant/variant.variant/variant_msan.pass.cpp
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 631ffceab5f68..61834085674fe 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -261,6 +261,10 @@ namespace std {
#include <new>
#include <version>
+#if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+#endif
+
// standard-mandated includes
// [variant.syn]
@@ -781,6 +785,10 @@ _LIBCPP_VARIANT_DESTRUCTOR(
_Trait::_TriviallyAvailable,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__dtor() = default,
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy() noexcept {
+# if __has_feature(memory_sanitizer)
+ if (!std::is_constant_evaluated())
+ __sanitizer_dtor_callback(&this->__data, sizeof(this->__data));
+# endif
this->__index = __variant_npos<__index_t>;
} _LIBCPP_EAT_SEMICOLON);
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant_msan.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant_msan.pass.cpp
new file mode 100644
index 0000000000000..a18a8d1d29391
--- /dev/null
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant_msan.pass.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+#include <variant>
+
+#if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+#endif
+
+int main(int, char**) {
+#if __has_feature(memory_sanitizer)
+ std::variant<double, int> v;
+ v.emplace<double>();
+ double& d = std::get<double>(v);
+ v.emplace<int>();
+ if (__msan_test_shadow(&d, sizeof(d)) == -1) {
+ // Unexpected: The entire range is accessible.
+ return 1;
+ }
+#endif
+
+ return 0;
+}
More information about the libcxx-commits
mailing list