public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-5056] libstdc++: Support getentropy and arc4random in std::random_device
@ 2021-11-09 14:40 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-11-09 14:40 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:3439657b02869299685d259c3a77aa38714565b7

commit r12-5056-g3439657b02869299685d259c3a77aa38714565b7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 4 15:51:37 2021 +0000

    libstdc++: Support getentropy and arc4random in std::random_device
    
    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.
    
    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.

Diff:
---
 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 +++++++++++++-
 .../26_numerics/random/random_device/cons/token.cc |   1 +
 .../26_numerics/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 07713e5c67f..e56afbc9c97 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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-11-09 14:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-09 14:40 [gcc r12-5056] libstdc++: Support getentropy and arc4random in std::random_device Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).