From: Serhiy Storchaka Date: Thu, 11 Jul 2013 19:28:18 +0000 (+0300) Subject: Issue #17872: Fix a segfault in marshal.load() when input stream returns X-Git-Tag: v3.4.0a1~257 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9e6672ae8044f9dbcbafe98a6b63ab30189770e;p=python Issue #17872: Fix a segfault in marshal.load() when input stream returns more bytes than requested. --- f9e6672ae8044f9dbcbafe98a6b63ab30189770e diff --cc Lib/test/test_marshal.py index 292746bd58,7e37f39c6a..ab06237064 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@@ -259,11 -280,17 +260,22 @@@ class BugsTestCase(unittest.TestCase) unicode_string = 'T' self.assertRaises(TypeError, marshal.loads, unicode_string) + def test_bad_reader(self): + class BadReader(io.BytesIO): + def read(self, n=-1): + b = super().read(n) + if n is not None and n > 4: + b += b' ' * 10**6 + return b + for value in (1.0, 1j, b'0123456789', '0123456789'): + self.assertRaises(ValueError, marshal.load, + BadReader(marshal.dumps(value))) + + def _test_eof(self): + data = marshal.dumps(("hello", "dolly", None)) + for i in range(len(data)): + self.assertRaises(EOFError, marshal.loads, data[0: i]) + LARGE_SIZE = 2**31 pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4 diff --cc Misc/NEWS index ea5a287f3e,3ff4d3e35f..4cfe4f8fb1 --- a/Misc/NEWS +++ b/Misc/NEWS @@@ -10,9 -12,9 +10,12 @@@ What's New in Python 3.4.0 Alpha 1 Core and Builtins ----------------- + - Issue #17872: Fix a segfault in marshal.load() when input stream returns + more bytes than requested. + +- Issue #18338: `python --version` now prints version string to stdout, and + not to stderr. Patch by Berker Peksag and Michael Dickens. + - Issue #18426: Fix NULL pointer dereference in C extension import when PyModule_GetDef() returns an error. diff --cc Python/marshal.c index a45e148ff9,a0e527fc83..1997e1964f --- a/Python/marshal.c +++ b/Python/marshal.c @@@ -568,10 -488,19 +568,19 @@@ r_string(char *s, Py_ssize_t n, RFILE * data->ob_type->tp_name); } else { - read = PyBytes_GET_SIZE(data); + read = (int)PyBytes_GET_SIZE(data); if (read > 0) { - ptr = PyBytes_AS_STRING(data); - memcpy(s, ptr, read); + if (read > n) { + PyErr_Format(PyExc_ValueError, + "read() returned too much data: " + "%zd bytes requested, %zd returned", + n, read); + read = -1; + } + else { + ptr = PyBytes_AS_STRING(data); + memcpy(s, ptr, read); + } } } Py_DECREF(data); @@@ -978,26 -871,13 +985,24 @@@ r_object(RFILE *p retval = NULL; break; } - buffer = PyMem_NEW(char, n); - if (buffer == NULL) { - retval = PyErr_NoMemory(); - break; - } - if (r_string(buffer, n, p) != n) { + if (n != 0) { + buffer = PyMem_NEW(char, n); + if (buffer == NULL) { + retval = PyErr_NoMemory(); + break; + } + if (r_string(buffer, n, p) != n) { + PyMem_DEL(buffer); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); + retval = NULL; + break; + } + v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass"); PyMem_DEL(buffer); + } + else { + v = PyUnicode_New(0, 0); + } + if (v == NULL) { retval = NULL; break; }