Commit 3641a74e authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #17872: Fix a segfault in marshal.load() when input stream returns

more bytes than requested.
parent 244d6252
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from test import support from test import support
import array import array
import io
import marshal import marshal
import sys import sys
import unittest import unittest
...@@ -279,6 +280,17 @@ class BugsTestCase(unittest.TestCase): ...@@ -279,6 +280,17 @@ class BugsTestCase(unittest.TestCase):
unicode_string = 'T' unicode_string = 'T'
self.assertRaises(TypeError, marshal.loads, unicode_string) 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)))
LARGE_SIZE = 2**31 LARGE_SIZE = 2**31
pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4 pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
......
...@@ -12,6 +12,9 @@ What's New in Python 3.3.3 release candidate 1? ...@@ -12,6 +12,9 @@ What's New in Python 3.3.3 release candidate 1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #17872: Fix a segfault in marshal.load() when input stream returns
more bytes than requested.
- Issue #18426: Fix NULL pointer dereference in C extension import when - Issue #18426: Fix NULL pointer dereference in C extension import when
PyModule_GetDef() returns an error. PyModule_GetDef() returns an error.
......
...@@ -490,8 +490,17 @@ r_string(char *s, Py_ssize_t n, RFILE *p) ...@@ -490,8 +490,17 @@ r_string(char *s, Py_ssize_t n, RFILE *p)
else { else {
read = PyBytes_GET_SIZE(data); read = PyBytes_GET_SIZE(data);
if (read > 0) { if (read > 0) {
ptr = PyBytes_AS_STRING(data); if (read > n) {
memcpy(s, ptr, read); 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); Py_DECREF(data);
...@@ -733,11 +742,13 @@ r_object(RFILE *p) ...@@ -733,11 +742,13 @@ r_object(RFILE *p)
double dx; double dx;
retval = NULL; retval = NULL;
n = r_byte(p); n = r_byte(p);
if (n == EOF || r_string(buf, n, p) != n) { if (n == EOF) {
PyErr_SetString(PyExc_EOFError, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
break; break;
} }
if (r_string(buf, n, p) != n)
break;
buf[n] = '\0'; buf[n] = '\0';
dx = PyOS_string_to_double(buf, NULL, NULL); dx = PyOS_string_to_double(buf, NULL, NULL);
if (dx == -1.0 && PyErr_Occurred()) if (dx == -1.0 && PyErr_Occurred())
...@@ -751,8 +762,6 @@ r_object(RFILE *p) ...@@ -751,8 +762,6 @@ r_object(RFILE *p)
unsigned char buf[8]; unsigned char buf[8];
double x; double x;
if (r_string((char*)buf, 8, p) != 8) { if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
retval = NULL; retval = NULL;
break; break;
} }
...@@ -771,21 +780,25 @@ r_object(RFILE *p) ...@@ -771,21 +780,25 @@ r_object(RFILE *p)
Py_complex c; Py_complex c;
retval = NULL; retval = NULL;
n = r_byte(p); n = r_byte(p);
if (n == EOF || r_string(buf, n, p) != n) { if (n == EOF) {
PyErr_SetString(PyExc_EOFError, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
break; break;
} }
if (r_string(buf, n, p) != n)
break;
buf[n] = '\0'; buf[n] = '\0';
c.real = PyOS_string_to_double(buf, NULL, NULL); c.real = PyOS_string_to_double(buf, NULL, NULL);
if (c.real == -1.0 && PyErr_Occurred()) if (c.real == -1.0 && PyErr_Occurred())
break; break;
n = r_byte(p); n = r_byte(p);
if (n == EOF || r_string(buf, n, p) != n) { if (n == EOF) {
PyErr_SetString(PyExc_EOFError, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
break; break;
} }
if (r_string(buf, n, p) != n)
break;
buf[n] = '\0'; buf[n] = '\0';
c.imag = PyOS_string_to_double(buf, NULL, NULL); c.imag = PyOS_string_to_double(buf, NULL, NULL);
if (c.imag == -1.0 && PyErr_Occurred()) if (c.imag == -1.0 && PyErr_Occurred())
...@@ -799,8 +812,6 @@ r_object(RFILE *p) ...@@ -799,8 +812,6 @@ r_object(RFILE *p)
unsigned char buf[8]; unsigned char buf[8];
Py_complex c; Py_complex c;
if (r_string((char*)buf, 8, p) != 8) { if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
retval = NULL; retval = NULL;
break; break;
} }
...@@ -810,8 +821,6 @@ r_object(RFILE *p) ...@@ -810,8 +821,6 @@ r_object(RFILE *p)
break; break;
} }
if (r_string((char*)buf, 8, p) != 8) { if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
retval = NULL; retval = NULL;
break; break;
} }
...@@ -842,8 +851,6 @@ r_object(RFILE *p) ...@@ -842,8 +851,6 @@ r_object(RFILE *p)
} }
if (r_string(PyBytes_AS_STRING(v), n, p) != n) { if (r_string(PyBytes_AS_STRING(v), n, p) != n) {
Py_DECREF(v); Py_DECREF(v);
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
retval = NULL; retval = NULL;
break; break;
} }
...@@ -871,8 +878,6 @@ r_object(RFILE *p) ...@@ -871,8 +878,6 @@ r_object(RFILE *p)
} }
if (r_string(buffer, n, p) != n) { if (r_string(buffer, n, p) != n) {
PyMem_DEL(buffer); PyMem_DEL(buffer);
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
retval = NULL; retval = NULL;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment