summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/pickle.py6
-rw-r--r--Lib/test/pickletester.py12
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_pickle.c11
4 files changed, 31 insertions, 1 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py
index fdeadee..0aee77a 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -1154,16 +1154,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 807221a..f4b50aa 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -1150,6 +1150,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 c8c1fa6..93ee402 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -268,6 +268,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 541bd1b..0fbd440 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -4873,8 +4873,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);
}
@@ -4913,6 +4917,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);
}