From owner-freebsd-bugs@FreeBSD.ORG Fri Sep 5 11:40:02 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9B53716A4BF for ; Fri, 5 Sep 2003 11:40:02 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 03B944400D for ; Fri, 5 Sep 2003 11:40:00 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h85Ie0Up025004 for ; Fri, 5 Sep 2003 11:40:00 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h85Ie0Lg025003; Fri, 5 Sep 2003 11:40:00 -0700 (PDT) Resent-Date: Fri, 5 Sep 2003 11:40:00 -0700 (PDT) Resent-Message-Id: <200309051840.h85Ie0Lg025003@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Hiroki Sato Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0611016A4BF for ; Fri, 5 Sep 2003 11:31:31 -0700 (PDT) Received: from delta.allbsd.org (p38078-adsao12honb4-acca.tokyo.ocn.ne.jp [219.161.135.78]) by mx1.FreeBSD.org (Postfix) with ESMTP id B2F6143FE3 for ; Fri, 5 Sep 2003 11:31:28 -0700 (PDT) (envelope-from hrs@allbsd.org) Received: from alph.allbsd.org (alph.allbsd.org [192.168.0.10]) by delta.allbsd.org (8.12.9/8.12.6) with ESMTP id h85IUP9q089847 for ; Sat, 6 Sep 2003 03:30:26 +0900 (JST) (envelope-from hrs@alph.d.allbsd.org) Received: from alph.allbsd.org (localhost [127.0.0.1]) by alph.allbsd.org (8.12.9/8.12.9) with ESMTP id h85IUOGc075843 for ; Sat, 6 Sep 2003 03:30:24 +0900 (JST) (envelope-from hrs@alph.d.allbsd.org) Received: (from hrs@localhost) by alph.allbsd.org (8.12.9/8.12.9/Submit) id h85IULXJ075842; Sat, 6 Sep 2003 03:30:21 +0900 (JST) Message-Id: <200309051830.h85IULXJ075842@alph.allbsd.org> Date: Sat, 6 Sep 2003 03:30:21 +0900 (JST) From: Hiroki Sato To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/56502: initstate() causes memory corruption on LP64 platforms X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Hiroki Sato List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Sep 2003 18:40:02 -0000 >Number: 56502 >Category: bin >Synopsis: initstate() causes memory corruption on LP64 platforms >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Sep 05 11:40:00 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Hiroki Sato >Release: FreeBSD 4.8-STABLE i386 >Organization: Tokyo University of Science >Environment: System: FreeBSD alph.allbsd.org 4.8-STABLE FreeBSD 4.8-STABLE #7: Tue May 20 00:05:43 JST 2003 hrs@alph.allbsd.org:/home/obj/home/src/sys/ALPH i386 >Description: 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. >How-To-Repeat: #include #include static int *a; static char b[256]; static int *c; int main(void) { struct timeval tv; gettimeofday(&tv, NULL); printf("before: %p\n", c); initstate((unsigned long)tv.tv_usec, b, sizeof(b)); printf("after: %p\n", c); return(0); } >Fix: Index: stdlib/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 --- stdlib/random.c 10 Aug 2003 17:49:55 -0000 1.23 +++ stdlib/random.c 1 Sep 2003 02:11:49 -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 uint32_t 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 uint32_t *fptr = &randtbl[SEP_3 + 1]; +static uint32_t *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 uint32_t *state = &randtbl[1]; +static int rand_type = TYPE_3; +static int rand_deg = DEG_3; +static int rand_sep = SEP_3; +static uint32_t *end_ptr = &randtbl[DEG_3 + 1]; static inline long good_rand(long); @@ -270,14 +270,14 @@ srandom(x) unsigned long x; { - long i, lim; + int i, lim; - state[0] = x; + state[0] = (uint32_t)x; if (rand_type == TYPE_0) lim = NSHUFF; else { for (i = 1; i < rand_deg; i++) - state[i] = good_rand(state[i - 1]); + state[i] = (uint32_t)good_rand(state[i - 1]); fptr = &state[rand_sep]; rptr = &state[0]; lim = 10 * rand_deg; @@ -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; + uint32_t *int_arg_state = (uint32_t *)(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 * (uint32_t)(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 = (uint32_t *) (int_arg_state + 1); /* first location */ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom(seed); + srandom((uint32_t)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 * (uint32_t)(rptr - state) + rand_type; return(ostate); } @@ -426,15 +426,15 @@ setstate(arg_state) char *arg_state; /* pointer to state array */ { - long *new_state = (long *) arg_state; - long type = new_state[0] % MAX_TYPES; - long rear = new_state[0] / MAX_TYPES; + uint32_t *new_state = (uint32_t *)(void *)arg_state; + uint32_t type = new_state[0] % MAX_TYPES; + uint32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); if (rand_type == TYPE_0) state[-1] = rand_type; else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; + state[-1] = MAX_TYPES * (uint32_t)(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 = (uint32_t *) (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; + uint32_t i; + uint32_t *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 = (*f >> 1) & 0x7fffffff; if (++f >= end_ptr) { f = state; ++r; @@ -501,5 +502,5 @@ fptr = f; rptr = r; } - return(i); + return((long)i); } >Release-Note: >Audit-Trail: >Unformatted: