diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -114,6 +114,11 @@ comment `here `_ if you are broken by this change and need to define the macro. +- On Apple platforms, ``std::random_device`` is now implemented on top of ``arc4random()`` + instead of reading from ``/dev/urandom``. Any implementation-defined token used when + constructing a ``std::random_device`` will now be ignored instead of interpreted as a + file to read entropy from. + Build System Changes -------------------- diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -107,6 +107,13 @@ # define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI // Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr # define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI +// std::random_device holds some state when it uses an implementation that gets +// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this +// implementation to another one on a platform that has already shipped +// std::random_device, one needs to retain the same object layout to remain ABI +// compatible. This switch removes these workarounds for platforms that don't care +// about ABI compatibility. +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support @@ -371,7 +378,7 @@ // Use rand_s(), for use on Windows. // When this option is used, the token passed to `std::random_device`'s // constructor *must* be "/dev/urandom" -- anything else is an error. -#if defined(__OpenBSD__) +#if defined(__OpenBSD__) || defined(__APPLE__) # define _LIBCPP_USING_ARC4_RANDOM #elif defined(__wasi__) # define _LIBCPP_USING_GETENTROPY diff --git a/libcxx/include/__random/random_device.h b/libcxx/include/__random/random_device.h --- a/libcxx/include/__random/random_device.h +++ b/libcxx/include/__random/random_device.h @@ -27,7 +27,26 @@ { #ifdef _LIBCPP_USING_DEV_RANDOM int __f_; +#elif !defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT) +# if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-private-field" +# endif + + // Apple platforms used to use the `_LIBCPP_USING_DEV_RANDOM` code path, and now + // use `arc4random()` as of this comment. In order to avoid breaking the ABI, we + // retain the same layout as before. +# if defined(__APPLE__) + int __padding_; // padding to fake the `__f_` field above +# endif + + // ... vendors can add workarounds here if they switch to a different representation ... + +# if defined(__clang__) +# pragma clang diagnostic pop +# endif #endif + public: // types typedef unsigned result_type; diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp --- a/libcxx/src/random.cpp +++ b/libcxx/src/random.cpp @@ -68,10 +68,8 @@ #elif defined(_LIBCPP_USING_ARC4_RANDOM) -random_device::random_device(const string& __token) +random_device::random_device(const string&) { - if (__token != "/dev/urandom") - __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); } random_device::~random_device() diff --git a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp --- a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp @@ -9,6 +9,11 @@ // See https://llvm.org/PR20183 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}} +// The behavior of std::random_device changed on Apple platforms with +// https://llvm.org/D116045. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11|12}} + // UNSUPPORTED: libcpp-has-no-random-device // @@ -59,13 +64,24 @@ } // Check the validity of various tokens { - check_random_device_invalid("wrong file"); - check_random_device_invalid("/dev/whatever"); +#if defined(_LIBCPP_USING_ARC4_RANDOM) + check_random_device_valid("/dev/urandom"); + check_random_device_valid("/dev/random"); + check_random_device_valid("/dev/null"); + check_random_device_valid("/dev/nonexistent"); + check_random_device_valid("wrong file"); +#elif defined(_LIBCPP_USING_DEV_RANDOM) check_random_device_valid("/dev/urandom"); -#if defined(_LIBCPP_USING_DEV_RANDOM) check_random_device_valid("/dev/random"); + check_random_device_valid("/dev/null"); + check_random_device_invalid("/dev/nonexistent"); + check_random_device_invalid("wrong file"); #else + check_random_device_valid("/dev/urandom"); check_random_device_invalid("/dev/random"); + check_random_device_invalid("/dev/null"); + check_random_device_invalid("/dev/nonexistent"); + check_random_device_invalid("wrong file"); #endif } diff --git a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp --- a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp +++ b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp @@ -6,9 +6,6 @@ // //===----------------------------------------------------------------------===// -// See https://llvm.org/PR20183 -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}} - // UNSUPPORTED: libcpp-has-no-random-device //