diff -r 377a50f8cb8b Lib/pickle.py --- a/Lib/pickle.py Fri Nov 16 13:17:59 2012 +0200 +++ b/Lib/pickle.py Fri Nov 16 23:15:10 2012 +0200 @@ -931,6 +931,9 @@ def load_long4(self): n = mloads(b'i' + self.read(4)) + if n < 0: + # Corrupt or hostile pickle -- we never write one like this + raise UnpicklingError("LONG pickle has negative byte count"); data = self.read(n) self.append(decode_long(data)) dispatch[LONG4[0]] = load_long4 @@ -960,13 +963,17 @@ def load_binstring(self): len = mloads(b'i' + self.read(4)) + if len < 0: + raise UnpicklingError("BINSTRING pickle has negative byte count"); data = self.read(len) value = str(data, self.encoding, self.errors) self.append(value) dispatch[BINSTRING[0]] = load_binstring - def load_binbytes(self): - len = mloads(b'i' + self.read(4)) + def load_binbytes(self, unpack=struct.unpack, maxsize=sys.maxsize): + len, = unpack(' maxsize: + raise UnpicklingError("BINBYTES exceeds system's maximum size of %d bytes" % maxsize); self.append(self.read(len)) dispatch[BINBYTES[0]] = load_binbytes @@ -974,8 +981,10 @@ 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 @@ -1106,6 +1115,9 @@ 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 @@ -1159,8 +1171,8 @@ 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 -r 377a50f8cb8b Modules/_pickle.c --- a/Modules/_pickle.c Fri Nov 16 13:17:59 2012 +0200 +++ b/Modules/_pickle.c Fri Nov 16 23:15:10 2012 +0200 @@ -1248,7 +1248,7 @@ pdata[1] = (unsigned char)(*value & 0xff); len = 2; } - else if (*value <= 0xffffffffL) { + else if (*value <= 0x7fffffffL) { pdata[0] = LONG_BINGET; pdata[1] = (unsigned char)(*value & 0xff); pdata[2] = (unsigned char)((*value >> 8) & 0xff); @@ -1298,7 +1298,7 @@ pdata[1] = (unsigned char)x; len = 2; } - else if (x <= 0xffffffffL) { + else if (x <= 0x7fffffffL) { pdata[0] = LONG_BINPUT; pdata[1] = (unsigned char)(x & 0xff); pdata[2] = (unsigned char)((x >> 8) & 0xff); @@ -1589,7 +1589,7 @@ * 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; @@ -1778,7 +1778,7 @@ header[1] = (unsigned char)size; len = 2; } - else if (size <= 0xffffffffL) { + else if (size <= 0x7fffffffL) { header[0] = BINBYTES; header[1] = (unsigned char)(size & 0xff); header[2] = (unsigned char)((size >> 8) & 0xff); @@ -1788,7 +1788,7 @@ } else { PyErr_SetString(PyExc_OverflowError, - "cannot serialize a bytes object larger than 4GB"); + "cannot serialize a bytes object larger than 2GB"); return -1; /* string too large */ } @@ -1886,9 +1886,9 @@ goto error; size = PyBytes_GET_SIZE(encoded); - if (size > 0xffffffffL) { + if (size > 0x7fffffffL) { PyErr_SetString(PyExc_OverflowError, - "cannot serialize a string larger than 4GB"); + "cannot serialize a string larger than 2GB"); goto error; /* string too large */ }