From 2dfdfdf45c4c26a628527a542d9c4deaaf300ea1 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 3 Jun 2014 02:40:39 +0000 Subject: [PATCH] [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. llvm-svn: 210061 --- libcxx/src/random.cpp | 17 ++++++++++++++++- libcxx/test/numerics/rand/rand.device/eval.pass.cpp | 16 ++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp index 21e2168..86017ef0 100644 --- a/libcxx/src/random.cpp +++ b/libcxx/src/random.cpp @@ -62,7 +62,22 @@ unsigned random_device::operator()() { unsigned r; - read(__f_, &r, sizeof(r)); + size_t n = sizeof(r); + char* p = reinterpret_cast(&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(s); + p += static_cast(s); + } return r; } #endif // defined(_WIN32) diff --git a/libcxx/test/numerics/rand/rand.device/eval.pass.cpp b/libcxx/test/numerics/rand/rand.device/eval.pass.cpp index 2422635..72aff07 100644 --- a/libcxx/test/numerics/rand/rand.device/eval.pass.cpp +++ b/libcxx/test/numerics/rand/rand.device/eval.pass.cpp @@ -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) + { + } } -- 2.7.4