summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2018-03-20 18:25:24 +0000
committerJoseph Myers <joseph@codesourcery.com>2018-03-20 18:25:24 +0000
commit8a07b0c43c46a480da070efd53a2720195e2256f (patch)
tree04a4604ca52bf46526231039c4e60271a75570ec
parentceb54b9b4ff5ef7d518a6e6e415a6897fb77eb67 (diff)
Fix signed integer overflow in random_r (bug 17343).
Bug 17343 reports that stdlib/random_r.c has code with undefined behavior because of signed integer overflow on int32_t. This patch changes the code so that the possibly overflowing computations use unsigned arithmetic instead. Note that the bug report refers to "Most code" in that file. The places changed in this patch are the only ones I found where I think such overflow can occur. Tested for x86_64 and x86. [BZ #17343] * stdlib/random_r.c (__random_r): Use unsigned arithmetic for possibly overflowing computations.
-rw-r--r--ChangeLog6
-rw-r--r--stdlib/random_r.c9
2 files changed, 10 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 3399e567b8..83fa3089e5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2018-03-20 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #17343]
+ * stdlib/random_r.c (__random_r): Use unsigned arithmetic for
+ possibly overflowing computations.
+
2018-03-20 Samuel Thibault <samuel.thibault@ens-lyon.org>
* manual/errno.texi (EOWNERDEAD, ENOTRECOVERABLE): Remove errno
diff --git a/stdlib/random_r.c b/stdlib/random_r.c
index 4d2f0d472f..b47c65c6d7 100644
--- a/stdlib/random_r.c
+++ b/stdlib/random_r.c
@@ -361,8 +361,7 @@ __random_r (struct random_data *buf, int32_t *result)
if (buf->rand_type == TYPE_0)
{
- int32_t val = state[0];
- val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
+ int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
}
@@ -371,11 +370,11 @@ __random_r (struct random_data *buf, int32_t *result)
int32_t *fptr = buf->fptr;
int32_t *rptr = buf->rptr;
int32_t *end_ptr = buf->end_ptr;
- int32_t val;
+ uint32_t val;
- val = *fptr += *rptr;
+ val = *fptr += (uint32_t) *rptr;
/* Chucking least random bit. */
- *result = (val >> 1) & 0x7fffffff;
+ *result = val >> 1;
++fptr;
if (fptr >= end_ptr)
{