summaryrefslogtreecommitdiffstats
path: root/Lib/pickle.py
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-04-10 05:02:52 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-04-10 05:02:52 (GMT)
commit44714007e888acba27d8527122bf618c28a4120b (patch)
tree2d100e6115c29f4e73644aa8a5c769970719d7d9 /Lib/pickle.py
parentd8ae7c2999b0362c098e57d64f49a710ce8238d0 (diff)
downloadcpython-44714007e888acba27d8527122bf618c28a4120b.zip
cpython-44714007e888acba27d8527122bf618c28a4120b.tar.gz
cpython-44714007e888acba27d8527122bf618c28a4120b.tar.bz2
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.
Diffstat (limited to 'Lib/pickle.py')
-rw-r--r--Lib/pickle.py29
1 files changed, 18 insertions, 11 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py
index 4abc046..f6cbea8 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -243,18 +243,25 @@ class Pickler:
def save_int(self, object):
if self.bin:
- i = mdumps(object)[1:]
- if i[-2:] == '\000\000':
- if i[-3] == '\000':
- self.write(BININT1 + i[:-3])
- return
-
- self.write(BININT2 + i[:-2])
+ # If the int is small enough to fit in a signed 4-byte 2's-comp
+ # format, we can store it more efficiently than the general
+ # case.
+ high_bits = object >> 31 # note that Python shift sign-extends
+ if high_bits == 0 or high_bits == -1:
+ # All high bits are copies of bit 2**31, so the value
+ # 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
-
- self.write(BININT + i)
- else:
- self.write(INT + `object` + '\n')
+ # Text pickle, or int too big to fit in signed 4-byte format.
+ self.write(INT + `object` + '\n')
dispatch[IntType] = save_int
def save_long(self, object):