[Bug libc/30584] initstate and initstate_r crash when the state argument is unaligned
adhemerval.zanella at linaro dot org
sourceware-bugzilla@sourceware.org
Wed Oct 16 19:08:30 GMT 2024
https://sourceware.org/bugzilla/show_bug.cgi?id=30584
--- Comment #6 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
(In reply to Sam James from comment #5)
> azanella, would you be kind enough to look? I would be happy to try but
> https://sourceware.org/bugzilla/show_bug.cgi?id=30584#c3 makes me fear that
> it's not clear how to fix it at all without breaking ABI.
I think the way to fix unaligned access without breaking the API is internally
use memcpy or packed struct:
diff --git a/stdlib/random_r.c b/stdlib/random_r.c
index b6297fe099..dee3bc9535 100644
--- a/stdlib/random_r.c
+++ b/stdlib/random_r.c
@@ -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,19 @@ 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, size_t idx)
+{
+ int32_t r;
+ memcpy (&r, &b[idx], sizeof (int32_t));
+ return r;
+}
+static inline void
+write_state (int32_t *b, size_t idx, int32_t v)
+{
+ memcpy (&b[idx], &v, sizeof (int32_t));
+}
/* Initialize the random number generator based on the given seed. If the
@@ -177,7 +190,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 +207,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 +251,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 +284,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 +321,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 +376,8 @@ __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 +387,9 @@ __random_r (struct random_data *buf, int32_t *result)
int32_t *end_ptr = buf->end_ptr;
uint32_t val;
- val = *fptr += (uint32_t) *rptr;
+ val = read_state (rptr, 0);
+ int32_t t = read_state (fptr, 0);
+ write_state (fptr, 0, t + val);
/* Chucking least random bit. */
*result = val >> 1;
++fptr;
On most architecture that supports fast unaligned access, the resulting code
won't change. However, on sparc and others, it has the drawback that the state
will be updated byte-per-byte. It would be possible to speed up things by using
a temporary buffer and memcpy it back, but I don't think it is worth.
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the Glibc-bugs
mailing list