diff --git a/Misc/NEWS b/Misc/NEWS index fca1540a550..2b492f406cb 100644 --- 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. diff --git a/Modules/cPickle.c b/Modules/cPickle.c index c1c00c0043d..914ebb3eebe 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -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++)