From bf6ecf92fa9800b1b99d78a82518bcae30115e0c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Nov 2012 20:40:21 +0100 Subject: [PATCH] Issue #12848: The pure Python pickle implementation now treats object lengths as unsigned 32-bit integers, like the C implementation does. Patch by Serhiy Storchaka. --- Lib/pickle.py | 39 ++++++++++++++++++++++++++------------- Misc/NEWS | 4 ++++ Modules/_pickle.c | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Lib/pickle.py b/Lib/pickle.py index d10ac776cfe..a690ccd8bc5 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -265,7 +265,7 @@ class _Pickler: if i < 256: return BINPUT + bytes([i]) else: - return LONG_BINPUT + pack(" maxsize: + raise UnpicklingError("BINBYTES exceeds system's maximum size of %d bytes" % maxsize); self.append(self.read(len)) dispatch[BINBYTES[0]] = load_binbytes @@ -968,8 +976,10 @@ class _Unpickler: self.append(str(self.readline()[:-1], 'raw-unicode-escape')) dispatch[UNICODE[0]] = load_unicode - def load_binunicode(self): - len = mloads(b'i' + self.read(4)) + def load_binunicode(self, unpack=struct.unpack, maxsize=sys.maxsize): + len, = unpack(' maxsize: + raise UnpicklingError("BINUNICODE exceeds system's maximum size of %d bytes" % maxsize); self.append(str(self.read(len), 'utf-8', 'surrogatepass')) dispatch[BINUNICODE[0]] = load_binunicode @@ -1100,6 +1110,9 @@ class _Unpickler: return key = _inverted_registry.get(code) if not key: + if code <= 0: # note that 0 is forbidden + # Corrupt or hostile pickle. + raise UnpicklingError("EXT specifies code <= 0"); raise ValueError("unregistered extension code %d" % code) obj = self.find_class(*key) _extension_cache[code] = obj @@ -1153,8 +1166,8 @@ class _Unpickler: self.append(self.memo[i]) dispatch[BINGET[0]] = load_binget - def load_long_binget(self): - i = mloads(b'i' + self.read(4)) + def load_long_binget(self, unpack=struct.unpack): + i, = unpack(' maxsize: raise ValueError("negative LONG_BINPUT argument") self.memo[i] = self.stack[-1] dispatch[LONG_BINPUT[0]] = load_long_binput diff --git a/Misc/NEWS b/Misc/NEWS index 09e9597edaf..e10ebc6f68e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -167,6 +167,10 @@ Core and Builtins Library ------- +- Issue #12848: The pure Python pickle implementation now treats object + lengths as unsigned 32-bit integers, like the C implementation does. + Patch by Serhiy Storchaka. + - Issue #1160: Fix compiling large regular expressions on UCS2 builds. Patch by Serhiy Storchaka. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index fc5f87127e8..18eaa38bdb6 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1579,7 +1579,7 @@ save_long(PicklerObject *self, PyObject *obj) * byte at the start, and cut it back later if possible. */ nbytes = (nbits >> 3) + 1; - if (nbytes > INT_MAX) { + if (nbytes > 0x7fffffffL) { PyErr_SetString(PyExc_OverflowError, "long too large to pickle"); goto error;