]> granicus.if.org Git - python/commitdiff
Issue #12847: Fix a crash with negative PUT and LONG_BINPUT arguments in
authorAntoine Pitrou <solipsis@pitrou.net>
Mon, 29 Aug 2011 22:27:10 +0000 (00:27 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Mon, 29 Aug 2011 22:27:10 +0000 (00:27 +0200)
the C pickle implementation.

Lib/pickle.py
Lib/test/pickletester.py
Misc/NEWS
Modules/_pickle.c

index aca8fd183c23acdd98d840f2328317c4aec36c79..32ae02bc7d3e42c441e0509f0eadf0c33588a7a3 100644 (file)
@@ -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
 
index 2b1fdd222a38c403f89615f6c6fd420d90d82d52..6dc2b5b3002207f5e18a6cdf1507d84c2b403504 100644 (file)
@@ -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):
 
index 61f5bd2f314a8dce97a0a09f866fbc1a6bae2b7f..68caece095b82a4371801b3550298f5b37ed6218 100644 (file)
--- 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.
 
index d7d81cddb52e9c0c1e0ad2c0f9790b5c0834c86a..20ee30299afbe99ada2d7ba129d68e43e947b157 100644 (file)
@@ -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);
 }