aboutsummaryrefslogtreecommitdiff
path: root/stdlib/random_r.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/random_r.c')
-rw-r--r--stdlib/random_r.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/stdlib/random_r.c b/stdlib/random_r.c
index b6297fe..b49f03f 100644
--- a/stdlib/random_r.c
+++ b/stdlib/random_r.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1995-2024 Free Software Foundation, Inc.
+ Copyright (C) 1995-2025 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -55,6 +55,7 @@
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
/* An improved random number generation package. In addition to the standard
@@ -146,7 +147,21 @@ static const struct random_poly_info random_poly_info =
{ DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }
};
+static inline int32_t
+read_state (int32_t *b, int idx)
+{
+ int32_t r;
+ memcpy (&r, (char *) b + idx * 4, sizeof (int32_t));
+ return r;
+}
+static inline void
+write_state (int32_t *b, int idx, int32_t v)
+{
+ /* Use literal 4 to avoid conversion to an unsigned type and pointer
+ wraparound. */
+ memcpy ((char *) b + idx * 4, &v, 4);
+}
/* Initialize the random number generator based on the given seed. If the
@@ -177,7 +192,7 @@ __srandom_r (unsigned int seed, struct random_data *buf)
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
if (seed == 0)
seed = 1;
- state[0] = seed;
+ write_state (state, 0, seed);
if (type == TYPE_0)
goto done;
@@ -194,7 +209,7 @@ __srandom_r (unsigned int seed, struct random_data *buf)
word = 16807 * lo - 2836 * hi;
if (word < 0)
word += 2147483647;
- *++dst = word;
+ write_state (++dst, 0, word);
}
buf->fptr = &state[buf->rand_sep];
@@ -238,9 +253,10 @@ __initstate_r (unsigned int seed, char *arg_state, size_t n,
{
int old_type = buf->rand_type;
if (old_type == TYPE_0)
- old_state[-1] = TYPE_0;
+ write_state (old_state, -1, TYPE_0);
else
- old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
+ write_state (old_state, -1, (MAX_TYPES * (buf->rptr - old_state))
+ + old_type);
}
int type;
@@ -270,9 +286,9 @@ __initstate_r (unsigned int seed, char *arg_state, size_t n,
__srandom_r (seed, buf);
- state[-1] = TYPE_0;
+ write_state (state, -1, TYPE_0);
if (type != TYPE_0)
- state[-1] = (buf->rptr - state) * MAX_TYPES + type;
+ write_state (state, -1, (buf->rptr - state) * MAX_TYPES + type);
return 0;
@@ -307,9 +323,10 @@ __setstate_r (char *arg_state, struct random_data *buf)
old_type = buf->rand_type;
old_state = buf->state;
if (old_type == TYPE_0)
- old_state[-1] = TYPE_0;
+ write_state (old_state, -1, TYPE_0);
else
- old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
+ write_state (old_state, -1, (MAX_TYPES * (buf->rptr - old_state))
+ + old_type);
type = new_state[-1] % MAX_TYPES;
if (type < TYPE_0 || type > TYPE_4)
@@ -361,8 +378,9 @@ __random_r (struct random_data *buf, int32_t *result)
if (buf->rand_type == TYPE_0)
{
- int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
- state[0] = val;
+ int32_t val = ((read_state(state, 0) * 1103515245U) + 12345U)
+ & 0x7fffffff;
+ write_state (state, 0, val);
*result = val;
}
else
@@ -372,7 +390,10 @@ __random_r (struct random_data *buf, int32_t *result)
int32_t *end_ptr = buf->end_ptr;
uint32_t val;
- val = *fptr += (uint32_t) *rptr;
+ /* Avoid integer overflow with uint32_t arihmetic. */
+ val = read_state (fptr, 0);
+ val += read_state (rptr, 0);
+ write_state (fptr, 0, val);
/* Chucking least random bit. */
*result = val >> 1;
++fptr;