Message ID | 20211105182023.2257591-1-jwakely@redhat.com |
---|---|
State | New |
Headers | show |
Series | [committed] libstdc++: Support getentropy and arc4random in std::random_device | expand |
Oops sorry - this is NOT committed yet. I won't push it until I've tested it on at least one BSD, preferably OpenBSD so I can test parts of the new code. On Fri, 5 Nov 2021 at 18:21, Jonathan Wakely via Libstdc++ < libstdc++@gcc.gnu.org> wrote: > This adds additional "getentropy" and "arc4random" tokens to > std::random_device. The former is supported on Glibc and OpenBSD (and > apparently wasm), and the latter is supported on various BSDs. > > I'm trying to test this on OpenBSD but I can't bootstrap GCC using the > system clang. > > > libstdc++-v3/ChangeLog: > > * acinclude.m4 (GLIBCXX_CHECK_GETENTROPY, > GLIBCXX_CHECK_ARC4RANDOM): > Define. > * configure.ac (GLIBCXX_CHECK_GETENTROPY, > GLIBCXX_CHECK_ARC4RANDOM): > Use them. > * config.h.in: Regenerate. > * configure: Regenerate. > * src/c++11/random.cc (random_device): Add getentropy and > arc4random as sources. > * testsuite/26_numerics/random/random_device/cons/token.cc: > Check new tokens. > * testsuite/26_numerics/random/random_device/entropy.cc: > Likewise. > --- > libstdc++-v3/acinclude.m4 | 46 ++++++++ > libstdc++-v3/config.h.in | 6 + > libstdc++-v3/configure | 103 ++++++++++++++++++ > libstdc++-v3/configure.ac | 4 + > libstdc++-v3/src/c++11/random.cc | 69 +++++++++++- > .../random/random_device/cons/token.cc | 1 + > .../random/random_device/entropy.cc | 7 ++ > 7 files changed, 234 insertions(+), 2 deletions(-) > > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 > index 90ecc4a87a2..497af5723e1 100644 > --- a/libstdc++-v3/acinclude.m4 > +++ b/libstdc++-v3/acinclude.m4 > @@ -4830,6 +4830,52 @@ AC_DEFUN([GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER], [ > fi > ]) > > +dnl > +dnl Check whether getentropy is present in <unistd.h>. > +dnl > +AC_DEFUN([GLIBCXX_CHECK_GETENTROPY], [ > + > + AC_LANG_SAVE > + AC_LANG_CPLUSPLUS > + AC_MSG_CHECKING([for getentropy]) > + AC_CACHE_VAL(glibcxx_cv_getentropy, [ > + AC_TRY_COMPILE( > + [#include <unistd.h>], > + [unsigned i; > + ::getentropy(&i, sizeof(i));], > + [glibcxx_cv_getentropy=yes], [glibcxx_cv_getentropy=no]) > + ]) > + > + if test $glibcxx_cv_getentropy = yes; then > + AC_DEFINE(HAVE_GETENTROPY, 1, [Define if getentropy is available in > <unistd.h>.]) > + fi > + AC_MSG_RESULT($glibcxx_cv_getentropy) > + AC_LANG_RESTORE > +]) > + > +dnl > +dnl Check whether arc4random is present in <stdlib.h>. > +dnl > +AC_DEFUN([GLIBCXX_CHECK_ARC4RANDOM], [ > + > + AC_LANG_SAVE > + AC_LANG_CPLUSPLUS > + AC_MSG_CHECKING([for arc4random]) > + AC_CACHE_VAL(glibcxx_cv_arc4random, [ > + AC_TRY_COMPILE( > + [#include <stdlib.h>], > + [unsigned i = ::arc4random();], > + [glibcxx_cv_arc4random=yes], [glibcxx_cv_arc4random=no]) > + ]) > + > + if test $glibcxx_cv_arc4random = yes; then > + AC_DEFINE(HAVE_ARC4RANDOM, 1, [Define if arc4random is available in > <stdlib.h>.]) > + fi > + AC_MSG_RESULT($glibcxx_cv_arc4random) > + AC_LANG_RESTORE > +]) > + > + > # Macros from the top-level gcc directory. > m4_include([../config/gc++filt.m4]) > m4_include([../config/tls.m4]) > diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in > index 228a758325e..420021fcb1a 100644 > --- a/libstdc++-v3/config.h.in > +++ b/libstdc++-v3/config.h.in > @@ -9,6 +9,9 @@ > /* Define to 1 if you have the `aligned_alloc' function. */ > #undef HAVE_ALIGNED_ALLOC > > +/* Define if arc4random is available in <stdlib.h>. */ > +#undef HAVE_ARC4RANDOM > + > /* Define to 1 if you have the <arpa/inet.h> header file. */ > #undef HAVE_ARPA_INET_H > > @@ -132,6 +135,9 @@ > /* Define to 1 if you have the `frexpl' function. */ > #undef HAVE_FREXPL > > +/* Define if getentropy is available in <unistd.h>. */ > +#undef HAVE_GETENTROPY > + > /* Define if _Unwind_GetIPInfo is available. */ > #undef HAVE_GETIPINFO > > diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure > index c1aea827070..21371031b66 100755 > --- a/libstdc++-v3/configure > +++ b/libstdc++-v3/configure > @@ -75429,6 +75429,109 @@ $as_echo "#define _GLIBCXX_X86_RDSEED 1" > >>confdefs.h > $as_echo "$ac_cv_x86_rdseed" >&6; } > > > +# Check for other random number APIs > + > + > + > + ac_ext=cpp > +ac_cpp='$CXXCPP $CPPFLAGS' > +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' > +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > + > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getentropy" >&5 > +$as_echo_n "checking for getentropy... " >&6; } > + if ${glibcxx_cv_getentropy+:} false; then : > + $as_echo_n "(cached) " >&6 > +else > + > + cat confdefs.h - <<_ACEOF >conftest.$ac_ext > +/* end confdefs.h. */ > +#include <unistd.h> > +int > +main () > +{ > +unsigned i; > + ::getentropy(&i, sizeof(i)); > + ; > + return 0; > +} > +_ACEOF > +if ac_fn_cxx_try_compile "$LINENO"; then : > + glibcxx_cv_getentropy=yes > +else > + glibcxx_cv_getentropy=no > +fi > +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext > + > +fi > + > + > + if test $glibcxx_cv_getentropy = yes; then > + > +$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h > + > + fi > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_getentropy" >&5 > +$as_echo "$glibcxx_cv_getentropy" >&6; } > + ac_ext=c > +ac_cpp='$CPP $CPPFLAGS' > +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' > +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > +ac_compiler_gnu=$ac_cv_c_compiler_gnu > + > + > + > + > + > + ac_ext=cpp > +ac_cpp='$CXXCPP $CPPFLAGS' > +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' > +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > + > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random" >&5 > +$as_echo_n "checking for arc4random... " >&6; } > + if ${glibcxx_cv_arc4random+:} false; then : > + $as_echo_n "(cached) " >&6 > +else > + > + cat confdefs.h - <<_ACEOF >conftest.$ac_ext > +/* end confdefs.h. */ > +#include <stdlib.h> > +int > +main () > +{ > +unsigned i = ::arc4random(); > + ; > + return 0; > +} > +_ACEOF > +if ac_fn_cxx_try_compile "$LINENO"; then : > + glibcxx_cv_arc4random=yes > +else > + glibcxx_cv_arc4random=no > +fi > +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext > + > +fi > + > + > + if test $glibcxx_cv_arc4random = yes; then > + > +$as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h > + > + fi > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_arc4random" >&5 > +$as_echo "$glibcxx_cv_arc4random" >&6; } > + ac_ext=c > +ac_cpp='$CPP $CPPFLAGS' > +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' > +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > +ac_compiler_gnu=$ac_cv_c_compiler_gnu > + > + > + > # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. > > # Do checks for resource limit functions. > diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac > index 2d68b3672b9..5b3c92f4bd7 100644 > --- a/libstdc++-v3/configure.ac > +++ b/libstdc++-v3/configure.ac > @@ -468,6 +468,10 @@ GLIBCXX_CHECK_X86_RDRAND > # Check if assembler supports rdseed opcode. > GLIBCXX_CHECK_X86_RDSEED > > +# Check for other random number APIs > +GLIBCXX_CHECK_GETENTROPY > +GLIBCXX_CHECK_ARC4RANDOM > + > # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. > GLIBCXX_CONFIGURE_TESTSUITE > > diff --git a/libstdc++-v3/src/c++11/random.cc > b/libstdc++-v3/src/c++11/random.cc > index 4b88818646f..4a553e0d84f 100644 > --- a/libstdc++-v3/src/c++11/random.cc > +++ b/libstdc++-v3/src/c++11/random.cc > @@ -68,7 +68,12 @@ > # include <stdlib.h> > #endif > > -#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM > +#ifdef _GLIBCXX_HAVE_GETENTROPY > +# include <unistd.h> > +#endif > + > +#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM \ > + || _GLIBCXX_HAVE_GETENTROPY > // The OS provides a source of randomness we can use. > # pragma GCC poison _M_mt > #elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN > @@ -166,6 +171,25 @@ namespace std _GLIBCXX_VISIBILITY(default) > } > #endif > > +#ifdef _GLIBCXX_HAVE_GETENTROPY > + unsigned int > + __libc_getentropy(void*) > + { > + unsigned int val; > + if (::getentropy(&val, sizeof(val)) != 0) > + std::__throw_runtime_error(__N("random_device: getentropy > failed")); > + return val; > + } > +#endif > + > +#ifdef _GLIBCXX_HAVE_ARC4RANDOM > + unsigned int > + __libc_arc4random(void*) > + { > + return ::arc4random(); > + } > +#endif > + > #ifdef USE_LCG > // TODO: use this to seed std::mt19937 engine too. > unsigned > @@ -214,7 +238,7 @@ namespace std _GLIBCXX_VISIBILITY(default) > #endif > > enum Which : unsigned { > - device_file = 1, prng = 2, rand_s = 4, > + device_file = 1, prng = 2, rand_s = 4, getentropy = 8, arc4random = > 16, > rdseed = 64, rdrand = 128, darn = 256, > any = 0xffff > }; > @@ -256,6 +280,16 @@ namespace std _GLIBCXX_VISIBILITY(default) > return device_file; > #endif > > +#ifdef _GLIBCXX_HAVE_ARC4RANDOM > + if (func == __libc_arc4random) > + return arc4random; > +#endif > + > +#ifdef _GLIBCXX_HAVE_GETENTROPY > + if (func == __libc_getentropy) > + return getentropy; > +#endif > + > #ifdef USE_LCG > if (func == &__lcg) > return prng; > @@ -311,6 +345,14 @@ namespace std _GLIBCXX_VISIBILITY(default) > else if (token == "rand_s") > which = rand_s; > #endif // _GLIBCXX_USE_CRT_RAND_S > +#ifdef _GLIBCXX_HAVE_GETENTROPY > + else if (token == "getentropy") > + which = getentropy; > +#endif // _GLIBCXX_HAVE_GETENTROPY > +#ifdef _GLIBCXX_HAVE_ARC4RANDOM > + else if (token == "arc4random") > + which = arc4random; > +#endif // _GLIBCXX_HAVE_ARC4RANDOM > #ifdef _GLIBCXX_USE_DEV_RANDOM > else if (token == "/dev/urandom" || token == "/dev/random") > { > @@ -395,6 +437,26 @@ namespace std _GLIBCXX_VISIBILITY(default) > } > #endif // USE_DARN > > +#ifdef _GLIBCXX_HAVE_ARC4RANDOM > + if (which & arc4random) > + { > + _M_func = &__libc_arc4random; > + return; > + } > +#endif // _GLIBCXX_HAVE_ARC4RANDOM > + > +#ifdef _GLIBCXX_HAVE_GETENTROPY > + if (which & getentropy) > + { > + unsigned int i; > + if (::getentropy(&i, sizeof(i)) == 0) // On linux the syscall can > fail. > + { > + _M_func = &__libc_getentropy; > + return; > + } > + } > +#endif // _GLIBCXX_HAVE_GETENTROPY > + > #ifdef _GLIBCXX_USE_DEV_RANDOM > if (which & device_file) > { > @@ -548,6 +610,9 @@ namespace std _GLIBCXX_VISIBILITY(default) > case rdseed: > case darn: > return (double) max; > + case arc4random: > + case getentropy: > + return (double) max; > case rand_s: > case prng: > return 0.0; > diff --git > a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc > b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc > index d6ac3a37c64..e13484e03a5 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc > @@ -53,6 +53,7 @@ test03() > const std::string tokens[] = { > "rdseed", "rdrand", "darn", > "rand_s", "/dev/urandom", "/dev/random", > + "getentropy", "arc4random", > "mt19937", "prng" > }; > int count = 0; > diff --git > a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc > b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc > index 6f3ebb1b38e..63b7043bf9b 100644 > --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc > +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc > @@ -28,6 +28,13 @@ test01() > const double entropy = std::random_device(token).entropy(); > VERIFY( entropy == max ); > } > + > + for (auto token : { "getentropy", "arc4random" }) > + if (__gnu_test::random_device_available(token)) > + { > + const double entropy = std::random_device(token).entropy(); > + VERIFY( entropy == max ); > + } > } > > int > -- > 2.31.1 > >
On Fri, 5 Nov 2021 at 18:22, Jonathan Wakely wrote: > Oops sorry - this is NOT committed yet. I won't push it until I've tested > it on at least one BSD, preferably OpenBSD so I can test parts of the new > code. > It got tested on darwin, and has been pushed to trunk now. > > > On Fri, 5 Nov 2021 at 18:21, Jonathan Wakely via Libstdc++ < > libstdc++@gcc.gnu.org> wrote: > >> This adds additional "getentropy" and "arc4random" tokens to >> std::random_device. The former is supported on Glibc and OpenBSD (and >> apparently wasm), and the latter is supported on various BSDs. >> >> I'm trying to test this on OpenBSD but I can't bootstrap GCC using the >> system clang. >> >> >> libstdc++-v3/ChangeLog: >> >> * acinclude.m4 (GLIBCXX_CHECK_GETENTROPY, >> GLIBCXX_CHECK_ARC4RANDOM): >> Define. >> * configure.ac (GLIBCXX_CHECK_GETENTROPY, >> GLIBCXX_CHECK_ARC4RANDOM): >> Use them. >> * config.h.in: Regenerate. >> * configure: Regenerate. >> * src/c++11/random.cc (random_device): Add getentropy and >> arc4random as sources. >> * testsuite/26_numerics/random/random_device/cons/token.cc: >> Check new tokens. >> * testsuite/26_numerics/random/random_device/entropy.cc: >> Likewise. >> --- >> libstdc++-v3/acinclude.m4 | 46 ++++++++ >> libstdc++-v3/config.h.in | 6 + >> libstdc++-v3/configure | 103 ++++++++++++++++++ >> libstdc++-v3/configure.ac | 4 + >> libstdc++-v3/src/c++11/random.cc | 69 +++++++++++- >> .../random/random_device/cons/token.cc | 1 + >> .../random/random_device/entropy.cc | 7 ++ >> 7 files changed, 234 insertions(+), 2 deletions(-) >> >> diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 >> index 90ecc4a87a2..497af5723e1 100644 >> --- a/libstdc++-v3/acinclude.m4 >> +++ b/libstdc++-v3/acinclude.m4 >> @@ -4830,6 +4830,52 @@ AC_DEFUN([GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER], [ >> fi >> ]) >> >> +dnl >> +dnl Check whether getentropy is present in <unistd.h>. >> +dnl >> +AC_DEFUN([GLIBCXX_CHECK_GETENTROPY], [ >> + >> + AC_LANG_SAVE >> + AC_LANG_CPLUSPLUS >> + AC_MSG_CHECKING([for getentropy]) >> + AC_CACHE_VAL(glibcxx_cv_getentropy, [ >> + AC_TRY_COMPILE( >> + [#include <unistd.h>], >> + [unsigned i; >> + ::getentropy(&i, sizeof(i));], >> + [glibcxx_cv_getentropy=yes], [glibcxx_cv_getentropy=no]) >> + ]) >> + >> + if test $glibcxx_cv_getentropy = yes; then >> + AC_DEFINE(HAVE_GETENTROPY, 1, [Define if getentropy is available in >> <unistd.h>.]) >> + fi >> + AC_MSG_RESULT($glibcxx_cv_getentropy) >> + AC_LANG_RESTORE >> +]) >> + >> +dnl >> +dnl Check whether arc4random is present in <stdlib.h>. >> +dnl >> +AC_DEFUN([GLIBCXX_CHECK_ARC4RANDOM], [ >> + >> + AC_LANG_SAVE >> + AC_LANG_CPLUSPLUS >> + AC_MSG_CHECKING([for arc4random]) >> + AC_CACHE_VAL(glibcxx_cv_arc4random, [ >> + AC_TRY_COMPILE( >> + [#include <stdlib.h>], >> + [unsigned i = ::arc4random();], >> + [glibcxx_cv_arc4random=yes], [glibcxx_cv_arc4random=no]) >> + ]) >> + >> + if test $glibcxx_cv_arc4random = yes; then >> + AC_DEFINE(HAVE_ARC4RANDOM, 1, [Define if arc4random is available in >> <stdlib.h>.]) >> + fi >> + AC_MSG_RESULT($glibcxx_cv_arc4random) >> + AC_LANG_RESTORE >> +]) >> + >> + >> # Macros from the top-level gcc directory. >> m4_include([../config/gc++filt.m4]) >> m4_include([../config/tls.m4]) >> diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in >> index 228a758325e..420021fcb1a 100644 >> --- a/libstdc++-v3/config.h.in >> +++ b/libstdc++-v3/config.h.in >> @@ -9,6 +9,9 @@ >> /* Define to 1 if you have the `aligned_alloc' function. */ >> #undef HAVE_ALIGNED_ALLOC >> >> +/* Define if arc4random is available in <stdlib.h>. */ >> +#undef HAVE_ARC4RANDOM >> + >> /* Define to 1 if you have the <arpa/inet.h> header file. */ >> #undef HAVE_ARPA_INET_H >> >> @@ -132,6 +135,9 @@ >> /* Define to 1 if you have the `frexpl' function. */ >> #undef HAVE_FREXPL >> >> +/* Define if getentropy is available in <unistd.h>. */ >> +#undef HAVE_GETENTROPY >> + >> /* Define if _Unwind_GetIPInfo is available. */ >> #undef HAVE_GETIPINFO >> >> diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure >> index c1aea827070..21371031b66 100755 >> --- a/libstdc++-v3/configure >> +++ b/libstdc++-v3/configure >> @@ -75429,6 +75429,109 @@ $as_echo "#define _GLIBCXX_X86_RDSEED 1" >> >>confdefs.h >> $as_echo "$ac_cv_x86_rdseed" >&6; } >> >> >> +# Check for other random number APIs >> + >> + >> + >> + ac_ext=cpp >> +ac_cpp='$CXXCPP $CPPFLAGS' >> +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' >> +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS >> conftest.$ac_ext $LIBS >&5' >> +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu >> + >> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getentropy" >&5 >> +$as_echo_n "checking for getentropy... " >&6; } >> + if ${glibcxx_cv_getentropy+:} false; then : >> + $as_echo_n "(cached) " >&6 >> +else >> + >> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext >> +/* end confdefs.h. */ >> +#include <unistd.h> >> +int >> +main () >> +{ >> +unsigned i; >> + ::getentropy(&i, sizeof(i)); >> + ; >> + return 0; >> +} >> +_ACEOF >> +if ac_fn_cxx_try_compile "$LINENO"; then : >> + glibcxx_cv_getentropy=yes >> +else >> + glibcxx_cv_getentropy=no >> +fi >> +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext >> + >> +fi >> + >> + >> + if test $glibcxx_cv_getentropy = yes; then >> + >> +$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h >> + >> + fi >> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: >> $glibcxx_cv_getentropy" >&5 >> +$as_echo "$glibcxx_cv_getentropy" >&6; } >> + ac_ext=c >> +ac_cpp='$CPP $CPPFLAGS' >> +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' >> +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS >> conftest.$ac_ext $LIBS >&5' >> +ac_compiler_gnu=$ac_cv_c_compiler_gnu >> + >> + >> + >> + >> + >> + ac_ext=cpp >> +ac_cpp='$CXXCPP $CPPFLAGS' >> +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' >> +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS >> conftest.$ac_ext $LIBS >&5' >> +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu >> + >> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random" >&5 >> +$as_echo_n "checking for arc4random... " >&6; } >> + if ${glibcxx_cv_arc4random+:} false; then : >> + $as_echo_n "(cached) " >&6 >> +else >> + >> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext >> +/* end confdefs.h. */ >> +#include <stdlib.h> >> +int >> +main () >> +{ >> +unsigned i = ::arc4random(); >> + ; >> + return 0; >> +} >> +_ACEOF >> +if ac_fn_cxx_try_compile "$LINENO"; then : >> + glibcxx_cv_arc4random=yes >> +else >> + glibcxx_cv_arc4random=no >> +fi >> +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext >> + >> +fi >> + >> + >> + if test $glibcxx_cv_arc4random = yes; then >> + >> +$as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h >> + >> + fi >> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: >> $glibcxx_cv_arc4random" >&5 >> +$as_echo "$glibcxx_cv_arc4random" >&6; } >> + ac_ext=c >> +ac_cpp='$CPP $CPPFLAGS' >> +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' >> +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS >> conftest.$ac_ext $LIBS >&5' >> +ac_compiler_gnu=$ac_cv_c_compiler_gnu >> + >> + >> + >> # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. >> >> # Do checks for resource limit functions. >> diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac >> index 2d68b3672b9..5b3c92f4bd7 100644 >> --- a/libstdc++-v3/configure.ac >> +++ b/libstdc++-v3/configure.ac >> @@ -468,6 +468,10 @@ GLIBCXX_CHECK_X86_RDRAND >> # Check if assembler supports rdseed opcode. >> GLIBCXX_CHECK_X86_RDSEED >> >> +# Check for other random number APIs >> +GLIBCXX_CHECK_GETENTROPY >> +GLIBCXX_CHECK_ARC4RANDOM >> + >> # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. >> GLIBCXX_CONFIGURE_TESTSUITE >> >> diff --git a/libstdc++-v3/src/c++11/random.cc >> b/libstdc++-v3/src/c++11/random.cc >> index 4b88818646f..4a553e0d84f 100644 >> --- a/libstdc++-v3/src/c++11/random.cc >> +++ b/libstdc++-v3/src/c++11/random.cc >> @@ -68,7 +68,12 @@ >> # include <stdlib.h> >> #endif >> >> -#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM >> +#ifdef _GLIBCXX_HAVE_GETENTROPY >> +# include <unistd.h> >> +#endif >> + >> +#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM \ >> + || _GLIBCXX_HAVE_GETENTROPY >> // The OS provides a source of randomness we can use. >> # pragma GCC poison _M_mt >> #elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN >> @@ -166,6 +171,25 @@ namespace std _GLIBCXX_VISIBILITY(default) >> } >> #endif >> >> +#ifdef _GLIBCXX_HAVE_GETENTROPY >> + unsigned int >> + __libc_getentropy(void*) >> + { >> + unsigned int val; >> + if (::getentropy(&val, sizeof(val)) != 0) >> + std::__throw_runtime_error(__N("random_device: getentropy >> failed")); >> + return val; >> + } >> +#endif >> + >> +#ifdef _GLIBCXX_HAVE_ARC4RANDOM >> + unsigned int >> + __libc_arc4random(void*) >> + { >> + return ::arc4random(); >> + } >> +#endif >> + >> #ifdef USE_LCG >> // TODO: use this to seed std::mt19937 engine too. >> unsigned >> @@ -214,7 +238,7 @@ namespace std _GLIBCXX_VISIBILITY(default) >> #endif >> >> enum Which : unsigned { >> - device_file = 1, prng = 2, rand_s = 4, >> + device_file = 1, prng = 2, rand_s = 4, getentropy = 8, arc4random >> = 16, >> rdseed = 64, rdrand = 128, darn = 256, >> any = 0xffff >> }; >> @@ -256,6 +280,16 @@ namespace std _GLIBCXX_VISIBILITY(default) >> return device_file; >> #endif >> >> +#ifdef _GLIBCXX_HAVE_ARC4RANDOM >> + if (func == __libc_arc4random) >> + return arc4random; >> +#endif >> + >> +#ifdef _GLIBCXX_HAVE_GETENTROPY >> + if (func == __libc_getentropy) >> + return getentropy; >> +#endif >> + >> #ifdef USE_LCG >> if (func == &__lcg) >> return prng; >> @@ -311,6 +345,14 @@ namespace std _GLIBCXX_VISIBILITY(default) >> else if (token == "rand_s") >> which = rand_s; >> #endif // _GLIBCXX_USE_CRT_RAND_S >> +#ifdef _GLIBCXX_HAVE_GETENTROPY >> + else if (token == "getentropy") >> + which = getentropy; >> +#endif // _GLIBCXX_HAVE_GETENTROPY >> +#ifdef _GLIBCXX_HAVE_ARC4RANDOM >> + else if (token == "arc4random") >> + which = arc4random; >> +#endif // _GLIBCXX_HAVE_ARC4RANDOM >> #ifdef _GLIBCXX_USE_DEV_RANDOM >> else if (token == "/dev/urandom" || token == "/dev/random") >> { >> @@ -395,6 +437,26 @@ namespace std _GLIBCXX_VISIBILITY(default) >> } >> #endif // USE_DARN >> >> +#ifdef _GLIBCXX_HAVE_ARC4RANDOM >> + if (which & arc4random) >> + { >> + _M_func = &__libc_arc4random; >> + return; >> + } >> +#endif // _GLIBCXX_HAVE_ARC4RANDOM >> + >> +#ifdef _GLIBCXX_HAVE_GETENTROPY >> + if (which & getentropy) >> + { >> + unsigned int i; >> + if (::getentropy(&i, sizeof(i)) == 0) // On linux the syscall can >> fail. >> + { >> + _M_func = &__libc_getentropy; >> + return; >> + } >> + } >> +#endif // _GLIBCXX_HAVE_GETENTROPY >> + >> #ifdef _GLIBCXX_USE_DEV_RANDOM >> if (which & device_file) >> { >> @@ -548,6 +610,9 @@ namespace std _GLIBCXX_VISIBILITY(default) >> case rdseed: >> case darn: >> return (double) max; >> + case arc4random: >> + case getentropy: >> + return (double) max; >> case rand_s: >> case prng: >> return 0.0; >> diff --git >> a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc >> b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc >> index d6ac3a37c64..e13484e03a5 100644 >> --- >> a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc >> +++ >> b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc >> @@ -53,6 +53,7 @@ test03() >> const std::string tokens[] = { >> "rdseed", "rdrand", "darn", >> "rand_s", "/dev/urandom", "/dev/random", >> + "getentropy", "arc4random", >> "mt19937", "prng" >> }; >> int count = 0; >> diff --git >> a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc >> b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc >> index 6f3ebb1b38e..63b7043bf9b 100644 >> --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc >> +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc >> @@ -28,6 +28,13 @@ test01() >> const double entropy = std::random_device(token).entropy(); >> VERIFY( entropy == max ); >> } >> + >> + for (auto token : { "getentropy", "arc4random" }) >> + if (__gnu_test::random_device_available(token)) >> + { >> + const double entropy = std::random_device(token).entropy(); >> + VERIFY( entropy == max ); >> + } >> } >> >> int >> -- >> 2.31.1 >> >>
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 90ecc4a87a2..497af5723e1 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -4830,6 +4830,52 @@ AC_DEFUN([GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER], [ fi ]) +dnl +dnl Check whether getentropy is present in <unistd.h>. +dnl +AC_DEFUN([GLIBCXX_CHECK_GETENTROPY], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_MSG_CHECKING([for getentropy]) + AC_CACHE_VAL(glibcxx_cv_getentropy, [ + AC_TRY_COMPILE( + [#include <unistd.h>], + [unsigned i; + ::getentropy(&i, sizeof(i));], + [glibcxx_cv_getentropy=yes], [glibcxx_cv_getentropy=no]) + ]) + + if test $glibcxx_cv_getentropy = yes; then + AC_DEFINE(HAVE_GETENTROPY, 1, [Define if getentropy is available in <unistd.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_getentropy) + AC_LANG_RESTORE +]) + +dnl +dnl Check whether arc4random is present in <stdlib.h>. +dnl +AC_DEFUN([GLIBCXX_CHECK_ARC4RANDOM], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_MSG_CHECKING([for arc4random]) + AC_CACHE_VAL(glibcxx_cv_arc4random, [ + AC_TRY_COMPILE( + [#include <stdlib.h>], + [unsigned i = ::arc4random();], + [glibcxx_cv_arc4random=yes], [glibcxx_cv_arc4random=no]) + ]) + + if test $glibcxx_cv_arc4random = yes; then + AC_DEFINE(HAVE_ARC4RANDOM, 1, [Define if arc4random is available in <stdlib.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_arc4random) + AC_LANG_RESTORE +]) + + # Macros from the top-level gcc directory. m4_include([../config/gc++filt.m4]) m4_include([../config/tls.m4]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 228a758325e..420021fcb1a 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -9,6 +9,9 @@ /* Define to 1 if you have the `aligned_alloc' function. */ #undef HAVE_ALIGNED_ALLOC +/* Define if arc4random is available in <stdlib.h>. */ +#undef HAVE_ARC4RANDOM + /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H @@ -132,6 +135,9 @@ /* Define to 1 if you have the `frexpl' function. */ #undef HAVE_FREXPL +/* Define if getentropy is available in <unistd.h>. */ +#undef HAVE_GETENTROPY + /* Define if _Unwind_GetIPInfo is available. */ #undef HAVE_GETIPINFO diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index c1aea827070..21371031b66 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -75429,6 +75429,109 @@ $as_echo "#define _GLIBCXX_X86_RDSEED 1" >>confdefs.h $as_echo "$ac_cv_x86_rdseed" >&6; } +# Check for other random number APIs + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getentropy" >&5 +$as_echo_n "checking for getentropy... " >&6; } + if ${glibcxx_cv_getentropy+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <unistd.h> +int +main () +{ +unsigned i; + ::getentropy(&i, sizeof(i)); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_getentropy=yes +else + glibcxx_cv_getentropy=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + + if test $glibcxx_cv_getentropy = yes; then + +$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_getentropy" >&5 +$as_echo "$glibcxx_cv_getentropy" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random" >&5 +$as_echo_n "checking for arc4random... " >&6; } + if ${glibcxx_cv_arc4random+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +int +main () +{ +unsigned i = ::arc4random(); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_arc4random=yes +else + glibcxx_cv_arc4random=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + + if test $glibcxx_cv_arc4random = yes; then + +$as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_arc4random" >&5 +$as_echo "$glibcxx_cv_arc4random" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. # Do checks for resource limit functions. diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 2d68b3672b9..5b3c92f4bd7 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -468,6 +468,10 @@ GLIBCXX_CHECK_X86_RDRAND # Check if assembler supports rdseed opcode. GLIBCXX_CHECK_X86_RDSEED +# Check for other random number APIs +GLIBCXX_CHECK_GETENTROPY +GLIBCXX_CHECK_ARC4RANDOM + # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. GLIBCXX_CONFIGURE_TESTSUITE diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 4b88818646f..4a553e0d84f 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -68,7 +68,12 @@ # include <stdlib.h> #endif -#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM +#ifdef _GLIBCXX_HAVE_GETENTROPY +# include <unistd.h> +#endif + +#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM \ + || _GLIBCXX_HAVE_GETENTROPY // The OS provides a source of randomness we can use. # pragma GCC poison _M_mt #elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN @@ -166,6 +171,25 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif +#ifdef _GLIBCXX_HAVE_GETENTROPY + unsigned int + __libc_getentropy(void*) + { + unsigned int val; + if (::getentropy(&val, sizeof(val)) != 0) + std::__throw_runtime_error(__N("random_device: getentropy failed")); + return val; + } +#endif + +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + unsigned int + __libc_arc4random(void*) + { + return ::arc4random(); + } +#endif + #ifdef USE_LCG // TODO: use this to seed std::mt19937 engine too. unsigned @@ -214,7 +238,7 @@ namespace std _GLIBCXX_VISIBILITY(default) #endif enum Which : unsigned { - device_file = 1, prng = 2, rand_s = 4, + device_file = 1, prng = 2, rand_s = 4, getentropy = 8, arc4random = 16, rdseed = 64, rdrand = 128, darn = 256, any = 0xffff }; @@ -256,6 +280,16 @@ namespace std _GLIBCXX_VISIBILITY(default) return device_file; #endif +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + if (func == __libc_arc4random) + return arc4random; +#endif + +#ifdef _GLIBCXX_HAVE_GETENTROPY + if (func == __libc_getentropy) + return getentropy; +#endif + #ifdef USE_LCG if (func == &__lcg) return prng; @@ -311,6 +345,14 @@ namespace std _GLIBCXX_VISIBILITY(default) else if (token == "rand_s") which = rand_s; #endif // _GLIBCXX_USE_CRT_RAND_S +#ifdef _GLIBCXX_HAVE_GETENTROPY + else if (token == "getentropy") + which = getentropy; +#endif // _GLIBCXX_HAVE_GETENTROPY +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + else if (token == "arc4random") + which = arc4random; +#endif // _GLIBCXX_HAVE_ARC4RANDOM #ifdef _GLIBCXX_USE_DEV_RANDOM else if (token == "/dev/urandom" || token == "/dev/random") { @@ -395,6 +437,26 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif // USE_DARN +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + if (which & arc4random) + { + _M_func = &__libc_arc4random; + return; + } +#endif // _GLIBCXX_HAVE_ARC4RANDOM + +#ifdef _GLIBCXX_HAVE_GETENTROPY + if (which & getentropy) + { + unsigned int i; + if (::getentropy(&i, sizeof(i)) == 0) // On linux the syscall can fail. + { + _M_func = &__libc_getentropy; + return; + } + } +#endif // _GLIBCXX_HAVE_GETENTROPY + #ifdef _GLIBCXX_USE_DEV_RANDOM if (which & device_file) { @@ -548,6 +610,9 @@ namespace std _GLIBCXX_VISIBILITY(default) case rdseed: case darn: return (double) max; + case arc4random: + case getentropy: + return (double) max; case rand_s: case prng: return 0.0; diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc index d6ac3a37c64..e13484e03a5 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc @@ -53,6 +53,7 @@ test03() const std::string tokens[] = { "rdseed", "rdrand", "darn", "rand_s", "/dev/urandom", "/dev/random", + "getentropy", "arc4random", "mt19937", "prng" }; int count = 0; diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc index 6f3ebb1b38e..63b7043bf9b 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc @@ -28,6 +28,13 @@ test01() const double entropy = std::random_device(token).entropy(); VERIFY( entropy == max ); } + + for (auto token : { "getentropy", "arc4random" }) + if (__gnu_test::random_device_available(token)) + { + const double entropy = std::random_device(token).entropy(); + VERIFY( entropy == max ); + } } int