This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix initstate{,_r} (BZ #710)


Hi!

initstate{,_r} fails to save old state, although the comment above it
states:
Note: The first thing we do is save the current state, if any, just like
setstate so that it doesn't matter when initstate is called.

The patch below does just that, using the same code setstate uses.
I've checked FreeBSD random.c and it behaves similarly (well, it is initstate
not initstate_r there) and run the testcase on Solaris, where it passed
(unlike on unpatched glibc).

2005-02-09  Jakub Jelinek  <jakub@redhat.com>

	[BZ #710]
	* stdlib/random_r.c (__initstate_r): Save old state.
	* stdlib/Makefile (tests): Add tst-random2.
	* stdlib/tst-random2.c: New test.
	Reported by Peter Bergner <bergner@vnet.ibm.com>.

--- libc/stdlib/random_r.c.jj	2002-07-06 08:35:55.000000000 +0200
+++ libc/stdlib/random_r.c	2005-02-09 21:22:34.700318767 +0100
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 1995 Free Software Foundation
+   Copyright (C) 1995, 2005 Free Software Foundation
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -240,10 +240,19 @@ __initstate_r (seed, arg_state, n, buf)
   int degree;
   int separation;
   int32_t *state;
+  int old_type;
+  int32_t *old_state;
 
   if (buf == NULL)
     goto fail;
 
+  old_type = buf->rand_type;
+  old_state = buf->state;
+  if (old_type == TYPE_0)
+    old_state[-1] = TYPE_0;
+  else
+    old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
+
   if (n >= BREAK_3)
     type = n < BREAK_4 ? TYPE_3 : TYPE_4;
   else if (n < BREAK_1)
--- libc/stdlib/Makefile.jj	2005-01-26 18:22:23.000000000 +0100
+++ libc/stdlib/Makefile	2005-02-09 21:19:00.689543768 +0100
@@ -61,9 +61,9 @@ distribute	:= exit.h grouping.h abort-in
 test-srcs	:= tst-fmtmsg
 tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   test-canon test-canon2 tst-strtoll tst-environ	    \
-		   tst-xpg-basename tst-random tst-bsearch tst-limits	    \
-		   tst-rand48 bug-strtod tst-setcontext test-a64l tst-qsort \
-		   tst-system testmb2
+		   tst-xpg-basename tst-random tst-random2 tst-bsearch	    \
+		   tst-limits tst-rand48 bug-strtod tst-setcontext	    \
+		   test-a64l tst-qsort tst-system testmb2
 
 include ../Makeconfig
 
--- libc/stdlib/tst-random2.c.jj	2005-02-09 21:05:16.972676949 +0100
+++ libc/stdlib/tst-random2.c	2005-02-09 21:14:39.892126585 +0100
@@ -0,0 +1,58 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int pass;
+  int ret = 0;
+  long int r[2];
+
+  for (pass = 0; pass < 2; pass++)
+    {
+      srandom (0x12344321);
+
+      int j;
+      for (j = 0; j < 3; ++j)
+	random ();
+      if (pass == 1)
+	{
+	  char state[128];
+	  char *ostate = initstate (0x34562101, state, 128);
+	  if (setstate (ostate) != state)
+	    {
+	      puts ("setstate (ostate) != state");
+	      ret = 1;
+	    }
+	}
+
+      random ();
+      r[pass] = random ();
+    }
+
+  if (r[0] != r[1])
+    {
+      printf ("%ld != %ld\n", r[0], r[1]);
+      ret = 1;
+    }
+  return ret;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]