mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Issue #17872: Fix a segfault in marshal.load() when input stream returns
more bytes than requested.
This commit is contained in:
commit
f9e6672ae8
3 changed files with 35 additions and 15 deletions
|
@ -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
|
||||||
|
@ -259,6 +260,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)))
|
||||||
|
|
||||||
def _test_eof(self):
|
def _test_eof(self):
|
||||||
data = marshal.dumps(("hello", "dolly", None))
|
data = marshal.dumps(("hello", "dolly", None))
|
||||||
for i in range(len(data)):
|
for i in range(len(data)):
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
|
||||||
Core and Builtins
|
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
|
- Issue #18338: `python --version` now prints version string to stdout, and
|
||||||
not to stderr. Patch by Berker Peksag and Michael Dickens.
|
not to stderr. Patch by Berker Peksag and Michael Dickens.
|
||||||
|
|
||||||
|
|
|
@ -570,10 +570,19 @@ r_string(char *s, Py_ssize_t n, RFILE *p)
|
||||||
else {
|
else {
|
||||||
read = (int)PyBytes_GET_SIZE(data);
|
read = (int)PyBytes_GET_SIZE(data);
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
|
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);
|
ptr = PyBytes_AS_STRING(data);
|
||||||
memcpy(s, ptr, read);
|
memcpy(s, ptr, read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Py_DECREF(data);
|
Py_DECREF(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,11 +850,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())
|
||||||
|
@ -860,8 +871,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;
|
||||||
}
|
}
|
||||||
|
@ -881,21 +890,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())
|
||||||
|
@ -910,8 +923,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;
|
||||||
}
|
}
|
||||||
|
@ -921,8 +932,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;
|
||||||
}
|
}
|
||||||
|
@ -954,8 +963,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;
|
||||||
}
|
}
|
||||||
|
@ -986,8 +993,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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue