[Python-checkins] python/dist/src/Modules cPickle.c,2.140,2.141 structmodule.c,2.57,2.58
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Thu, 20 Mar 2003 10:32:18 -0800
Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv9471/Modules
Modified Files:
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.
Bugfix candidate, but I already backported this to 2.2.
In 2.3, this code remains in severe need of refactoring.
Index: cPickle.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/cPickle.c,v
retrieving revision 2.140
retrieving revision 2.141
diff -C2 -d -r2.140 -r2.141
*** cPickle.c 19 Feb 2003 01:45:13 -0000 2.140
--- cPickle.c 20 Mar 2003 18:32:08 -0000 2.141
***************
*** 1157,1166 ****
}
! 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 */
--- 1157,1162 ----
}
! if (e >= 1024)
! goto Overflow;
else if (e < -1022) {
/* Gradual underflow */
***************
*** 1177,1183 ****
--- 1173,1196 ----
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 */
***************
*** 1225,1228 ****
--- 1238,1246 ----
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with d format");
+ return -1;
}
Index: structmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v
retrieving revision 2.57
retrieving revision 2.58
diff -C2 -d -r2.57 -r2.58
*** structmodule.c 3 Sep 2002 18:42:21 -0000 2.57
--- structmodule.c 20 Mar 2003 18:32:13 -0000 2.58
***************
*** 225,234 ****
}
! 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 */
--- 225,230 ----
}
! if (e >= 128)
! goto Overflow;
else if (e < -126) {
/* Gradual underflow */
***************
*** 243,246 ****
--- 239,250 ----
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 */
***************
*** 261,264 ****
--- 265,273 ----
/* Done */
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with f format");
+ return -1;
}
***************
*** 296,305 ****
}
! 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 */
--- 305,310 ----
}
! if (e >= 1024)
! goto Overflow;
else if (e < -1022) {
/* Gradual underflow */
***************
*** 315,321 ****
--- 320,341 ----
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 */
***************
*** 353,356 ****
--- 373,381 ----
/* Done */
return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with d format");
+ return -1;
}