[libcxx-commits] [libcxx] c6d95c4 - [libc++] Fix initialization-order-fiasco with iostream.cpp constructors (#126995)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Feb 15 19:54:26 PST 2025
Author: Vitaly Buka
Date: 2025-02-15T19:54:23-08:00
New Revision: c6d95c441a29a45782ff72d6cb82839b86fd0e4a
URL: https://github.com/llvm/llvm-project/commit/c6d95c441a29a45782ff72d6cb82839b86fd0e4a
DIFF: https://github.com/llvm/llvm-project/commit/c6d95c441a29a45782ff72d6cb82839b86fd0e4a.diff
LOG: [libc++] Fix initialization-order-fiasco with iostream.cpp constructors (#126995)
Asan reports it after #124103.
It's know case of false positive for Asan.
https://github.com/google/sanitizers/wiki/AddressSanitizerInitializationOrderFiasco#false-positives
It's can be avoided with `constexpr` constructors.
In general order global constructors in different
modules is undefined. If global constructor uses
external global, they can be not constructed yet.
However, implementation may contain workaround for
that, or the state of non-constructed global can
be still valid.
Asan will still falsely report such cases, as it
has no machinery to detect correctness of such
cases.
We need to fix/workaround the issue in libc++, as
it will affect many libc++ with Asan users.
Added:
libcxx/test/std/input.output/iostreams.base/ios.base/ios.types/ios_Init/ios_Init.global.pass.cpp
Modified:
libcxx/src/iostream.cpp
Removed:
################################################################################
diff --git a/libcxx/src/iostream.cpp b/libcxx/src/iostream.cpp
index d91f9f0c04826..416725235c340 100644
--- a/libcxx/src/iostream.cpp
+++ b/libcxx/src/iostream.cpp
@@ -18,8 +18,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class StreamT, class BufferT>
union stream_data {
- stream_data() {}
- ~stream_data() {}
+ constexpr stream_data() {}
+ constexpr ~stream_data() {}
struct {
// The stream has to be the first element, since that's referenced by the stream declarations in <iostream>
StreamT stream;
@@ -38,13 +38,19 @@ union stream_data {
#define CHAR_MANGLING_wchar_t "_W"
#define CHAR_MANGLING(CharT) CHAR_MANGLING_##CharT
+#ifdef _LIBCPP_COMPILER_CLANG_BASED
+# define STRING_DATA_CONSTINIT constinit
+#else
+# define STRING_DATA_CONSTINIT
+#endif
+
#ifdef _LIBCPP_ABI_MICROSOFT
# define STREAM(StreamT, BufferT, CharT, var) \
- stream_data<StreamT<CharT>, BufferT<CharT>> var __asm__( \
+ STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var __asm__( \
"?" #var "@" ABI_NAMESPACE_STR "@std@@3V?$" #StreamT \
"@" CHAR_MANGLING(CharT) "U?$char_traits@" CHAR_MANGLING(CharT) "@" ABI_NAMESPACE_STR "@std@@@12 at A")
#else
-# define STREAM(StreamT, BufferT, CharT, var) stream_data<StreamT<CharT>, BufferT<CharT>> var
+# define STREAM(StreamT, BufferT, CharT, var) STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var
#endif
// These definitions and the declarations in <iostream> technically cause ODR violations, since they have
diff erent
diff --git a/libcxx/test/std/input.output/iostreams.base/ios.base/ios.types/ios_Init/ios_Init.global.pass.cpp b/libcxx/test/std/input.output/iostreams.base/ios.base/ios.types/ios_Init/ios_Init.global.pass.cpp
new file mode 100644
index 0000000000000..ac6a7213bb722
--- /dev/null
+++ b/libcxx/test/std/input.output/iostreams.base/ios.base/ios.types/ios_Init/ios_Init.global.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <iostream>
+
+// FIXME: Remove after issue https://github.com/llvm/llvm-project/issues/127348 resolved.
+extern "C" const char* __asan_default_options() { return "check_initialization_order=true:strict_init_order=true"; }
+
+// Test that ios used from globals constructors doesn't trigger Asan initialization-order-fiasco.
+
+struct Global {
+ Global() { std::cout << "Hello!"; }
+} global;
+
+int main(int, char**) { return 0; }
More information about the libcxx-commits
mailing list