]> granicus.if.org Git - python/commitdiff
bpo-27880: Fixed integer overflow in cPickle when pickle large strings or (#662)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 14 Mar 2017 05:29:33 +0000 (07:29 +0200)
committerGitHub <noreply@github.com>
Tue, 14 Mar 2017 05:29:33 +0000 (07:29 +0200)
too many objects.

Misc/NEWS
Modules/cPickle.c

index fca1540a55019cacc2acfa3d6787a431f6d710a2..2b492f406cb85a7f454d0ac0fe45b349b200b3b8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@ Extension Modules
 Library
 -------
 
+- bpo-27880: Fixed integer overflow in cPickle when pickle large strings or
+  too many objects.
+
 - bpo-29110: Fix file object leak in aifc.open() when file is given as a
   filesystem path and is not in valid AIFF format.
   Original patch by Anthony Zhang.
index c1c00c0043d7412cf1ad7d7a5aa94318582a7a9f..914ebb3eebeedf480bedf218b1e21cf32bba9449 100644 (file)
@@ -778,7 +778,7 @@ get(Picklerobject *self, PyObject *id)
             s[1] = (int)(c_value & 0xff);
             len = 2;
         }
-        else {
+        else if (c_value < 0x7fffffffL) {
             s[0] = LONG_BINGET;
             s[1] = (int)(c_value & 0xff);
             s[2] = (int)((c_value >> 8)  & 0xff);
@@ -786,6 +786,11 @@ get(Picklerobject *self, PyObject *id)
             s[4] = (int)((c_value >> 24) & 0xff);
             len = 5;
         }
+        else { /* unlikely */
+            PyErr_SetString(PicklingError,
+                            "memo id too large for LONG_BINGET");
+            return -1;
+        }
     }
 
     if (self->write_func(self, s, len) < 0)
@@ -857,7 +862,12 @@ put2(Picklerobject *self, PyObject *ob)
         goto finally;
     }
     else {
-        if (p >= 256) {
+        if (p < 256) {
+            c_str[0] = BINPUT;
+            c_str[1] = p;
+            len = 2;
+        }
+        else if (p < 0x7fffffffL) {
             c_str[0] = LONG_BINPUT;
             c_str[1] = (int)(p & 0xff);
             c_str[2] = (int)((p >> 8)  & 0xff);
@@ -865,10 +875,10 @@ put2(Picklerobject *self, PyObject *ob)
             c_str[4] = (int)((p >> 24) & 0xff);
             len = 5;
         }
-        else {
-            c_str[0] = BINPUT;
-            c_str[1] = p;
-            len = 2;
+        else { /* unlikely */
+            PyErr_SetString(PicklingError,
+                            "memo id too large for LONG_BINPUT");
+            goto finally;
         }
     }
 
@@ -1268,14 +1278,17 @@ save_string(Picklerobject *self, PyObject *args, int doput)
             c_str[1] = size;
             len = 2;
         }
-        else if (size <= INT_MAX) {
+        else if (size <= 0x7fffffffL) {
             c_str[0] = BINSTRING;
             for (i = 1; i < 5; i++)
                 c_str[i] = (int)(size >> ((i - 1) * 8));
             len = 5;
         }
-        else
+        else {
+            PyErr_SetString(PyExc_OverflowError,
+                            "cannot serialize a string larger than 2 GiB");
             return -1;    /* string too large */
+        }
 
         if (self->write_func(self, c_str, len) < 0)
             return -1;
@@ -1436,8 +1449,11 @@ save_unicode(Picklerobject *self, PyObject *args, int doput)
 
         if ((size = PyString_Size(repr)) < 0)
             goto err;
-        if (size > INT_MAX)
-            return -1;   /* string too large */
+        if (size > 0x7fffffffL) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "cannot serialize a Unicode string larger than 2 GiB");
+            goto err;   /* string too large */
+        }
 
         c_str[0] = BINUNICODE;
         for (i = 1; i < 5; i++)