From 55549ec476c178ca4723ba97d4f00a015f427427 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 30 Aug 2011 00:27:10 +0200 Subject: [PATCH] Issue #12847: Fix a crash with negative PUT and LONG_BINPUT arguments in the C pickle implementation. --- Lib/pickle.py | 6 ++++++ Lib/test/pickletester.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Modules/_pickle.c | 11 ++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Lib/pickle.py b/Lib/pickle.py index aca8fd183c..32ae02bc7d 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1156,16 +1156,22 @@ class _Unpickler: def load_put(self): i = int(self.readline()[:-1]) + if i < 0: + raise ValueError("negative PUT argument") self.memo[i] = self.stack[-1] dispatch[PUT[0]] = load_put def load_binput(self): i = self.read(1)[0] + if i < 0: + raise ValueError("negative BINPUT argument") self.memo[i] = self.stack[-1] dispatch[BINPUT[0]] = load_binput def load_long_binput(self): i = mloads(b'i' + self.read(4)) + if i < 0: + raise ValueError("negative LONG_BINPUT argument") self.memo[i] = self.stack[-1] dispatch[LONG_BINPUT[0]] = load_long_binput diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 2b1fdd222a..6dc2b5b300 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1121,6 +1121,18 @@ class AbstractPickleTests(unittest.TestCase): # On 32-bit builds, a BINUNICODE of 2**31 or more is refused self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.') + def test_negative_put(self): + # Issue #12847 + dumped = b'Va\np-1\n.' + self.assertRaises(ValueError, self.loads, dumped) + + def test_negative_32b_binput(self): + # Issue #12847 + if sys.maxsize > 2**32: + self.skipTest("test is only meaningful on 32-bit builds") + dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.' + self.assertRaises(ValueError, self.loads, dumped) + class BigmemPickleTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 61f5bd2f31..68caece095 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Core and Builtins Library ------- +- Issue #12847: Fix a crash with negative PUT and LONG_BINPUT arguments in + the C pickle implementation. + - Issue #11564: Avoid crashes when trying to pickle huge objects or containers (more than 2**31 items). Instead, in most cases, an OverflowError is raised. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index d7d81cddb5..20ee30299a 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4853,8 +4853,12 @@ load_put(UnpicklerObject *self) return -1; idx = PyLong_AsSsize_t(key); Py_DECREF(key); - if (idx == -1 && PyErr_Occurred()) + if (idx < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "negative PUT argument"); return -1; + } return _Unpickler_MemoPut(self, idx, value); } @@ -4893,6 +4897,11 @@ load_long_binput(UnpicklerObject *self) value = self->stack->data[Py_SIZE(self->stack) - 1]; idx = calc_binsize(s, 4); + if (idx < 0) { + PyErr_SetString(PyExc_ValueError, + "negative LONG_BINPUT argument"); + return -1; + } return _Unpickler_MemoPut(self, idx, value); } -- 2.40.0