[Python-checkins] python/dist/src/Modules cPickle.c,2.73.2.1.2.3,2.73.2.1.2.4 structmodule.c,2.51.8.1,2.51.8.2
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Thu, 20 Mar 2003 10:31:30 -0800
Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv6172/Modules
Modified Files:
Tag: release22-maint
cPickle.c structmodule.c
Log Message:
SF bug 705836: struct.pack of floats in non-native endian order
pack_float, pack_double, save_float: All the routines for creating
IEEE-format packed representations of floats and doubles simply ignored
that rounding can (in rare cases) propagate out of a long string of
1 bits. At worst, the end-off carry can (by mistake) interfere with
the exponent value, and then unpacking yields a result wrong by a factor
of 2. In less severe cases, it can end up losing more low-order bits
than intended, or fail to catch overflow *caused* by rounding.
Index: cPickle.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/cPickle.c,v
retrieving revision 2.73.2.1.2.3
retrieving revision 2.73.2.1.2.4
diff -C2 -d -r2.73.2.1.2.3 -r2.73.2.1.2.4
*** cPickle.c 24 Sep 2002 11:53:34 -0000 2.73.2.1.2.3
--- cPickle.c 20 Mar 2003 18:31:13 -0000 2.73.2.1.2.4
***************
*** 706,710 ****
static int
put(Picklerobject *self, PyObject *ob) {
! if (ob->ob_refcnt < 2 || self->fast)
return 0;
--- 706,710 ----
static int
put(Picklerobject *self, PyObject *ob) {
! if (ob->ob_refcnt < 2 || self->fast)
return 0;
***************
*** 922,926 ****
}
! int
fast_save_leave(Picklerobject *self, PyObject *obj)
{
--- 922,926 ----
}
! int
fast_save_leave(Picklerobject *self, PyObject *obj)
{
***************
*** 1065,1074 ****
}
! if (e >= 1024) {
! /* XXX 1024 itself is reserved for Inf/NaN */
! PyErr_SetString(PyExc_OverflowError,
! "float too large to pack with d format");
! return -1;
! }
else if (e < -1022) {
/* Gradual underflow */
--- 1065,1070 ----
}
! if (e >= 1024)
! goto Overflow;
else if (e < -1022) {
/* Gradual underflow */
***************
*** 1084,1090 ****
--- 1080,1103 ----
f *= 268435456.0; /* 2**28 */
fhi = (long) floor(f); /* Truncate */
+ assert(fhi < 268435456);
+
f -= (double)fhi;
f *= 16777216.0; /* 2**24 */
flo = (long) floor(f + 0.5); /* Round */
+ assert(flo <= 16777216);
+ if (flo >> 24) {
+ /* The carry propagated out of a string of 24 1 bits. */
+ flo = 0;
+ ++fhi;
+ if (fhi >> 28) {
+ /* And it also progagated out of the next
+ * 28 bits.
+ */
+ fhi = 0;
+ ++e;
+ if (e >= 2047)
+ goto Overflow;
+ }
+ }
/* First byte */
***************
*** 1132,1135 ****
--- 1145,1153 ----
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with d format");
+ return -1;
}
***************
*** 2104,2110 ****
static PyObject *
Pickle_clear_memo(Picklerobject *self, PyObject *args) {
! if (!PyArg_ParseTuple(args,":clear_memo"))
return NULL;
! if (self->memo)
PyDict_Clear(self->memo);
Py_INCREF(Py_None);
--- 2122,2128 ----
static PyObject *
Pickle_clear_memo(Picklerobject *self, PyObject *args) {
! if (!PyArg_ParseTuple(args,":clear_memo"))
return NULL;
! if (self->memo)
PyDict_Clear(self->memo);
Py_INCREF(Py_None);
***************
*** 2121,2125 ****
/* Can be called by Python code or C code */
! if (args && !PyArg_ParseTuple(args, "|i:getvalue", &clear))
return NULL;
--- 2139,2143 ----
/* Can be called by Python code or C code */
! if (args && !PyArg_ParseTuple(args, "|i:getvalue", &clear))
return NULL;
***************
*** 2483,2487 ****
static PyGetSetDef Pickler_getsets[] = {
! {"persistent_id", (getter)Pickler_get_pers_func,
(setter)Pickler_set_pers_func},
{"inst_persistent_id", NULL, (setter)Pickler_set_inst_pers_func},
--- 2501,2505 ----
static PyGetSetDef Pickler_getsets[] = {
! {"persistent_id", (getter)Pickler_get_pers_func,
(setter)Pickler_set_pers_func},
{"inst_persistent_id", NULL, (setter)Pickler_set_inst_pers_func},
Index: structmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v
retrieving revision 2.51.8.1
retrieving revision 2.51.8.2
diff -C2 -d -r2.51.8.1 -r2.51.8.2
*** structmodule.c 23 Sep 2002 20:54:04 -0000 2.51.8.1
--- structmodule.c 20 Mar 2003 18:31:20 -0000 2.51.8.2
***************
*** 226,235 ****
}
! if (e >= 128) {
! /* XXX 128 itself is reserved for Inf/NaN */
! PyErr_SetString(PyExc_OverflowError,
! "float too large to pack with f format");
! return -1;
! }
else if (e < -126) {
/* Gradual underflow */
--- 226,231 ----
}
! if (e >= 128)
! goto Overflow;
else if (e < -126) {
/* Gradual underflow */
***************
*** 244,247 ****
--- 240,251 ----
f *= 8388608.0; /* 2**23 */
fbits = (long) floor(f + 0.5); /* Round */
+ assert(fbits <= 8388608);
+ if (fbits >> 23) {
+ /* The carry propagated out of a string of 23 1 bits. */
+ fbits = 0;
+ ++e;
+ if (e >= 255)
+ goto Overflow;
+ }
/* First byte */
***************
*** 262,265 ****
--- 266,274 ----
/* Done */
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with f format");
+ return -1;
}
***************
*** 297,306 ****
}
! if (e >= 1024) {
! /* XXX 1024 itself is reserved for Inf/NaN */
! PyErr_SetString(PyExc_OverflowError,
! "float too large to pack with d format");
! return -1;
! }
else if (e < -1022) {
/* Gradual underflow */
--- 306,311 ----
}
! if (e >= 1024)
! goto Overflow;
else if (e < -1022) {
/* Gradual underflow */
***************
*** 316,322 ****
--- 321,342 ----
f *= 268435456.0; /* 2**28 */
fhi = (long) floor(f); /* Truncate */
+ assert(fhi < 268435456);
+
f -= (double)fhi;
f *= 16777216.0; /* 2**24 */
flo = (long) floor(f + 0.5); /* Round */
+ assert(flo <= 16777216);
+ if (flo >> 24) {
+ /* The carry propagated out of a string of 24 1 bits. */
+ flo = 0;
+ ++fhi;
+ if (fhi >> 28) {
+ /* And it also progagated out of the next 28 bits. */
+ fhi = 0;
+ ++e;
+ if (e >= 2047)
+ goto Overflow;
+ }
+ }
/* First byte */
***************
*** 354,357 ****
--- 374,382 ----
/* Done */
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with d format");
+ return -1;
}