summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-06-03 02:40:39 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-06-03 02:40:39 +0000
commit2dfdfdf45c4c26a628527a542d9c4deaaf300ea1 (patch)
tree5cc56dac5fafb9497f378e6af6f8a90318c3ac0e
parent1e9592a9c71ed87c806946ad2cccc1bcb472324d (diff)
downloadbcm5719-llvm-2dfdfdf45c4c26a628527a542d9c4deaaf300ea1.tar.gz
bcm5719-llvm-2dfdfdf45c4c26a628527a542d9c4deaaf300ea1.zip
[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
-rw-r--r--libcxx/src/random.cpp17
-rw-r--r--libcxx/test/numerics/rand/rand.device/eval.pass.cpp16
2 files changed, 30 insertions, 3 deletions
diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp
index 21e21689a87..86017ef0d46 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<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)
diff --git a/libcxx/test/numerics/rand/rand.device/eval.pass.cpp b/libcxx/test/numerics/rand/rand.device/eval.pass.cpp
index 2422635c92f..72aff076a5d 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)
+ {
+ }
}
OpenPOWER on IntegriCloud