mirror of
https://github.com/python/cpython.git
synced 2025-10-17 04:08:28 +00:00
test_pickle works on sizeof(long)==8 boxes again.
pickle.py The code implicitly assumed that all ints fit in 4 bytes, causing all sorts of mischief (from nonsense results to corrupted pickles). Repaired that. marshal.c The int marshaling code assumed that right shifts of signed longs sign-extend. Repaired that.
This commit is contained in:
parent
d8ae7c2999
commit
44714007e8
2 changed files with 19 additions and 12 deletions
|
@ -243,18 +243,25 @@ class Pickler:
|
||||||
|
|
||||||
def save_int(self, object):
|
def save_int(self, object):
|
||||||
if self.bin:
|
if self.bin:
|
||||||
i = mdumps(object)[1:]
|
# If the int is small enough to fit in a signed 4-byte 2's-comp
|
||||||
if i[-2:] == '\000\000':
|
# format, we can store it more efficiently than the general
|
||||||
if i[-3] == '\000':
|
# case.
|
||||||
self.write(BININT1 + i[:-3])
|
high_bits = object >> 31 # note that Python shift sign-extends
|
||||||
return
|
if high_bits == 0 or high_bits == -1:
|
||||||
|
# All high bits are copies of bit 2**31, so the value
|
||||||
self.write(BININT2 + i[:-2])
|
# fits in a 4-byte signed int.
|
||||||
|
i = mdumps(object)[1:]
|
||||||
|
assert len(i) == 4
|
||||||
|
if i[-2:] == '\000\000': # fits in 2-byte unsigned int
|
||||||
|
if i[-3] == '\000': # fits in 1-byte unsigned int
|
||||||
|
self.write(BININT1 + i[0])
|
||||||
|
else:
|
||||||
|
self.write(BININT2 + i[:2])
|
||||||
|
else:
|
||||||
|
self.write(BININT + i)
|
||||||
return
|
return
|
||||||
|
# Text pickle, or int too big to fit in signed 4-byte format.
|
||||||
self.write(BININT + i)
|
self.write(INT + `object` + '\n')
|
||||||
else:
|
|
||||||
self.write(INT + `object` + '\n')
|
|
||||||
dispatch[IntType] = save_int
|
dispatch[IntType] = save_int
|
||||||
|
|
||||||
def save_long(self, object):
|
def save_long(self, object):
|
||||||
|
|
|
@ -126,7 +126,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
else if (PyInt_Check(v)) {
|
else if (PyInt_Check(v)) {
|
||||||
long x = PyInt_AS_LONG((PyIntObject *)v);
|
long x = PyInt_AS_LONG((PyIntObject *)v);
|
||||||
#if SIZEOF_LONG > 4
|
#if SIZEOF_LONG > 4
|
||||||
long y = x>>31;
|
long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);
|
||||||
if (y && y != -1) {
|
if (y && y != -1) {
|
||||||
w_byte(TYPE_INT64, p);
|
w_byte(TYPE_INT64, p);
|
||||||
w_long64(x, p);
|
w_long64(x, p);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue