[libcxx] r210061 - [libc++] Don't return uninitialized data from random_device::operator()

David Majnemer david.majnemer at gmail.com
Mon Jun 2 19:40:39 PDT 2014


Author: majnemer
Date: Mon Jun  2 21:40:39 2014
New Revision: 210061

URL: http://llvm.org/viewvc/llvm-project?rev=210061&view=rev
Log:
[libc++] Don't return uninitialized data from random_device::operator()

Make sure we appropriately retry calls to read if the return result is
less than what we asked for.

Additionally, check and handle IO errors: EINTR results in the read
operation getting restarted; other errors turn into exceptions.

Modified:
    libcxx/trunk/src/random.cpp
    libcxx/trunk/test/numerics/rand/rand.device/eval.pass.cpp

Modified: libcxx/trunk/src/random.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/random.cpp?rev=210061&r1=210060&r2=210061&view=diff
==============================================================================
--- libcxx/trunk/src/random.cpp (original)
+++ libcxx/trunk/src/random.cpp Mon Jun  2 21:40:39 2014
@@ -62,7 +62,22 @@ unsigned
 random_device::operator()()
 {
     unsigned r;
-    read(__f_, &r, sizeof(r));
+    size_t n = sizeof(r);
+    char* p = reinterpret_cast<char*>(&r);
+    while (n > 0)
+    {
+        ssize_t s = read(__f_, p, n);
+        if (s == 0)
+            __throw_system_error(ENODATA, "random_device got EOF");
+        if (s == -1)
+        {
+            if (errno != EINTR)
+                __throw_system_error(errno, "random_device got an unexpected error");
+            continue;
+        }
+        n -= static_cast<size_t>(s);
+        p += static_cast<size_t>(s);
+    }
     return r;
 }
 #endif // defined(_WIN32)

Modified: libcxx/trunk/test/numerics/rand/rand.device/eval.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/numerics/rand/rand.device/eval.pass.cpp?rev=210061&r1=210060&r2=210061&view=diff
==============================================================================
--- libcxx/trunk/test/numerics/rand/rand.device/eval.pass.cpp (original)
+++ libcxx/trunk/test/numerics/rand/rand.device/eval.pass.cpp Mon Jun  2 21:40:39 2014
@@ -18,6 +18,18 @@
 
 int main()
 {
-    std::random_device r;
-    std::random_device::result_type e = r();
+    {
+        std::random_device r;
+        std::random_device::result_type e = r();
+    }
+
+    try
+    {
+        std::random_device r("/dev/null");
+        r();
+        assert(false);
+    }
+    catch (const std::system_error& e)
+    {
+    }
 }





More information about the cfe-commits mailing list