Shawn Ligocki added the comment:

I've got a patch! The problem was that the state was being cast from a
C-type unsigned long to a long.

On 32-bit machines this makes large 32-bit longs negative.
On 64-bit machines this preserves the sign of 32-bit values (because
they are stored in 64-bit longs).

My patch returns the values with PyLong_FromUnsignedLong() instead of
PyInt_FromLong(), therefore there is no casting to long and both 32-bit
and 64-bit machines produce the same result.

I added code to read states from the old (buggy) version and decypher it
appropriately (from either 32-bit or 64-bit source!). In other words,
old pickles can now be opened on either architecture with the new patch.

This patch is taken from the svn head, but also works on Python 2.5.1 .

I haven't tested this patch fully on 64-bit machine yet. I'll let you
know when I have.

Cheers,
-Shawn

_____________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1727780>
_____________________________________
Index: Lib/random.py
===================================================================
--- Lib/random.py	(revision 58178)
+++ Lib/random.py	(working copy)
@@ -83,7 +83,7 @@
 
     """
 
-    VERSION = 2     # used by getstate/setstate
+    VERSION = 3     # used by getstate/setstate
 
     def __init__(self, x=None):
         """Initialize an instance.
@@ -120,9 +120,20 @@
     def setstate(self, state):
         """Restore internal state from object returned by getstate()."""
         version = state[0]
-        if version == 2:
+        if version == 3:
             version, internalstate, self.gauss_next = state
             super(Random, self).setstate(internalstate)
+        elif version == 2:
+            version, internalstate, self.gauss_next = state
+            # In version 2, the state was saved as signed ints, which causes
+            #   inconsistencies between 32/64-bit systems. The state is
+            #   really unsigned 32-bit ints, so we convert negative ints from
+            #   version 2 to positive longs for version 3.
+            try:
+                internalstate = tuple( long(x) % (2**32) for x in internalstate )
+            except ValueError, e:
+                raise TypeError, e
+            super(Random, self).setstate(internalstate)
         else:
             raise ValueError("state with version %s passed to "
                              "Random.setstate() of version %s" %
Index: Modules/_randommodule.c
===================================================================
--- Modules/_randommodule.c	(revision 58178)
+++ Modules/_randommodule.c	(working copy)
@@ -319,12 +319,12 @@
 	if (state == NULL)
 		return NULL;
 	for (i=0; i<N ; i++) {
-		element = PyInt_FromLong((long)(self->state[i]));
+		element = PyLong_FromUnsignedLong(self->state[i]);
 		if (element == NULL)
 			goto Fail;
 		PyTuple_SET_ITEM(state, i, element);
 	}
-	element = PyInt_FromLong((long)(self->index));
+	element = PyLong_FromLong((long)(self->index));
 	if (element == NULL)
 		goto Fail;
 	PyTuple_SET_ITEM(state, i, element);
@@ -339,7 +339,8 @@
 random_setstate(RandomObject *self, PyObject *state)
 {
 	int i;
-	long element;
+	unsigned long element;
+	long index;
 
 	if (!PyTuple_Check(state)) {
 		PyErr_SetString(PyExc_TypeError,
@@ -353,16 +354,16 @@
 	}
 
 	for (i=0; i<N ; i++) {
-		element = PyInt_AsLong(PyTuple_GET_ITEM(state, i));
+		element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
 		if (element == -1 && PyErr_Occurred())
 			return NULL;
-		self->state[i] = (unsigned long)element;
+		self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
 	}
 
-	element = PyInt_AsLong(PyTuple_GET_ITEM(state, i));
-	if (element == -1 && PyErr_Occurred())
+	index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
+	if (index == -1 && PyErr_Occurred())
 		return NULL;
-	self->index = (int)element;
+	self->index = (int)index;
 
 	Py_INCREF(Py_None);
 	return Py_None;
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to