[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