initstate() on FreeBSD/sparc64
Hiroki Sato
hrs at eos.ocn.ne.jp
Sat Aug 30 20:27:35 PDT 2003
Hi,
I noticed that initstate() caused memory corruption on
FreeBSD/sparc64. I guess this is because lib/libc/stdlib/random.c
assumes "long" is 32-bit long.
The attached patch works fine on my box, but this is a bit ugly.
Could anyone take care of this?
--
| Hiroki SATO <hrs at eos.ocn.ne.jp> / <hrs at FreeBSD.org>
Index: random.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/random.c,v
retrieving revision 1.23
diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.23 random.c
--- random.c 10 Aug 2003 17:49:55 -0000 1.23
+++ random.c 31 Aug 2003 03:00:04 -0000
@@ -61,10 +61,10 @@
* congruential generator. If the amount of state information is less than
* 32 bytes, a simple linear congruential R.N.G. is used.
*
- * Internally, the state information is treated as an array of longs; the
+ * Internally, the state information is treated as an array of ints; the
* zeroeth element of the array is the type of R.N.G. being used (small
* integer); the remainder of the array is the state information for the
- * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of
+ * R.N.G. Thus, 32 bytes of state information will give 7 ints worth of
* state information, which will allow a degree seven polynomial. (Note:
* the zeroeth word of state information also has some other information
* stored in it -- see setstate() for details).
@@ -148,8 +148,8 @@
#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
#endif /* !USE_WEAK_SEEDING */
-static long degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
-static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
/*
* Initially, everything is set up as if from:
@@ -165,7 +165,7 @@
* MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
*/
-static long randtbl[DEG_3 + 1] = {
+static int randtbl[DEG_3 + 1] = {
TYPE_3,
#ifdef USE_WEAK_SEEDING
/* Historic implementation compatibility */
@@ -200,8 +200,8 @@
* in the initialization of randtbl) because the state table pointer is set
* to point to randtbl[1] (as explained below).
*/
-static long *fptr = &randtbl[SEP_3 + 1];
-static long *rptr = &randtbl[1];
+static int *fptr = &randtbl[SEP_3 + 1];
+static int *rptr = &randtbl[1];
/*
* The following things are the pointer to the state information table, the
@@ -213,11 +213,11 @@
* this is more efficient than indexing every time to find the address of
* the last element to see if the front and rear pointers have wrapped.
*/
-static long *state = &randtbl[1];
-static long rand_type = TYPE_3;
-static long rand_deg = DEG_3;
-static long rand_sep = SEP_3;
-static long *end_ptr = &randtbl[DEG_3 + 1];
+static int *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static int *end_ptr = &randtbl[DEG_3 + 1];
static inline long good_rand(long);
@@ -350,7 +350,7 @@
*
* Returns a pointer to the old state.
*
- * Note: The Sparc platform requires that arg_state begin on a long
+ * Note: The Sparc platform requires that arg_state begin on an int
* word boundary; otherwise a bus error will occur. Even so, lint will
* complain about mis-alignment, but you should disregard these messages.
*/
@@ -361,12 +361,12 @@
long n; /* # bytes of state info */
{
char *ostate = (char *)(&state[-1]);
- long *long_arg_state = (long *) arg_state;
+ int *int_arg_state = (int *)(void *)arg_state;
if (rand_type == TYPE_0)
state[-1] = rand_type;
else
- state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ state[-1] = MAX_TYPES * (int)(rptr - state) + rand_type;
if (n < BREAK_0) {
(void)fprintf(stderr,
"random: not enough state (%ld bytes); ignored.\n", n);
@@ -393,13 +393,13 @@
rand_deg = DEG_4;
rand_sep = SEP_4;
}
- state = (long *) (long_arg_state + 1); /* first location */
+ state = (int *) (int_arg_state + 1); /* first location */
end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
- srandom(seed);
+ srandom((unsigned int)seed);
if (rand_type == TYPE_0)
- long_arg_state[0] = rand_type;
+ int_arg_state[0] = rand_type;
else
- long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+ int_arg_state[0] = MAX_TYPES * (int)(rptr - state) + rand_type;
return(ostate);
}
@@ -426,7 +426,7 @@
setstate(arg_state)
char *arg_state; /* pointer to state array */
{
- long *new_state = (long *) arg_state;
+ int *new_state = (int *)(void *)arg_state;
long type = new_state[0] % MAX_TYPES;
long rear = new_state[0] / MAX_TYPES;
char *ostate = (char *)(&state[-1]);
@@ -434,7 +434,7 @@
if (rand_type == TYPE_0)
state[-1] = rand_type;
else
- state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ state[-1] = MAX_TYPES * (int)(rptr - state) + rand_type;
switch(type) {
case TYPE_0:
case TYPE_1:
@@ -449,7 +449,7 @@
(void)fprintf(stderr,
"random: state info corrupted; not changed.\n");
}
- state = (long *) (new_state + 1);
+ state = (int *) (new_state + 1);
if (rand_type != TYPE_0) {
rptr = &state[rear];
fptr = &state[(rear + rand_sep) % rand_deg];
@@ -478,8 +478,8 @@
long
random()
{
- long i;
- long *f, *r;
+ int i;
+ int *f, *r;
if (rand_type == TYPE_0) {
i = state[0];
@@ -490,7 +490,8 @@
*/
f = fptr; r = rptr;
*f += *r;
- i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ /* chucking least random bit */
+ i = ((unsigned int)*f >> 1) & 0x7fffffff;
if (++f >= end_ptr) {
f = state;
++r;
More information about the freebsd-hackers
mailing list