Skip to content

Commit 1aa1803

Browse files
bpo-27880: Fixed integer overflow in cPickle when pickle large strings or (#662)
too many objects.
1 parent 4ec14c2 commit 1aa1803

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ Extension Modules
3939
Library
4040
-------
4141

42+
- bpo-27880: Fixed integer overflow in cPickle when pickle large strings or
43+
too many objects.
44+
4245
- bpo-29110: Fix file object leak in aifc.open() when file is given as a
4346
filesystem path and is not in valid AIFF format.
4447
Original patch by Anthony Zhang.

Modules/cPickle.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -778,14 +778,19 @@ get(Picklerobject *self, PyObject *id)
778778
s[1] = (int)(c_value & 0xff);
779779
len = 2;
780780
}
781-
else {
781+
else if (c_value < 0x7fffffffL) {
782782
s[0] = LONG_BINGET;
783783
s[1] = (int)(c_value & 0xff);
784784
s[2] = (int)((c_value >> 8) & 0xff);
785785
s[3] = (int)((c_value >> 16) & 0xff);
786786
s[4] = (int)((c_value >> 24) & 0xff);
787787
len = 5;
788788
}
789+
else { /* unlikely */
790+
PyErr_SetString(PicklingError,
791+
"memo id too large for LONG_BINGET");
792+
return -1;
793+
}
789794
}
790795

791796
if (self->write_func(self, s, len) < 0)
@@ -857,18 +862,23 @@ put2(Picklerobject *self, PyObject *ob)
857862
goto finally;
858863
}
859864
else {
860-
if (p >= 256) {
865+
if (p < 256) {
866+
c_str[0] = BINPUT;
867+
c_str[1] = p;
868+
len = 2;
869+
}
870+
else if (p < 0x7fffffffL) {
861871
c_str[0] = LONG_BINPUT;
862872
c_str[1] = (int)(p & 0xff);
863873
c_str[2] = (int)((p >> 8) & 0xff);
864874
c_str[3] = (int)((p >> 16) & 0xff);
865875
c_str[4] = (int)((p >> 24) & 0xff);
866876
len = 5;
867877
}
868-
else {
869-
c_str[0] = BINPUT;
870-
c_str[1] = p;
871-
len = 2;
878+
else { /* unlikely */
879+
PyErr_SetString(PicklingError,
880+
"memo id too large for LONG_BINPUT");
881+
goto finally;
872882
}
873883
}
874884

@@ -1268,14 +1278,17 @@ save_string(Picklerobject *self, PyObject *args, int doput)
12681278
c_str[1] = size;
12691279
len = 2;
12701280
}
1271-
else if (size <= INT_MAX) {
1281+
else if (size <= 0x7fffffffL) {
12721282
c_str[0] = BINSTRING;
12731283
for (i = 1; i < 5; i++)
12741284
c_str[i] = (int)(size >> ((i - 1) * 8));
12751285
len = 5;
12761286
}
1277-
else
1287+
else {
1288+
PyErr_SetString(PyExc_OverflowError,
1289+
"cannot serialize a string larger than 2 GiB");
12781290
return -1; /* string too large */
1291+
}
12791292

12801293
if (self->write_func(self, c_str, len) < 0)
12811294
return -1;
@@ -1436,8 +1449,11 @@ save_unicode(Picklerobject *self, PyObject *args, int doput)
14361449

14371450
if ((size = PyString_Size(repr)) < 0)
14381451
goto err;
1439-
if (size > INT_MAX)
1440-
return -1; /* string too large */
1452+
if (size > 0x7fffffffL) {
1453+
PyErr_SetString(PyExc_OverflowError,
1454+
"cannot serialize a Unicode string larger than 2 GiB");
1455+
goto err; /* string too large */
1456+
}
14411457

14421458
c_str[0] = BINUNICODE;
14431459
for (i = 1; i < 5; i++)

0 commit comments

Comments
 (0)