[Python-checkins] cpython (merge 3.3 -> default): Issue #17872: Fix a segfault in marshal.load() when input stream returns
serhiy.storchaka
python-checkins at python.org
Thu Jul 11 21:31:16 CEST 2013
http://hg.python.org/cpython/rev/5fa793ae36cc
changeset: 84557:5fa793ae36cc
parent: 84555:6587fd3d89ae
parent: 84556:fc7bab8a8618
user: Serhiy Storchaka <storchaka at gmail.com>
date: Thu Jul 11 22:28:18 2013 +0300
summary:
Issue #17872: Fix a segfault in marshal.load() when input stream returns
more bytes than requested.
files:
Lib/test/test_marshal.py | 12 +++++++++
Misc/NEWS | 3 ++
Python/marshal.c | 35 ++++++++++++++++------------
3 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py
--- a/Lib/test/test_marshal.py
+++ b/Lib/test/test_marshal.py
@@ -2,6 +2,7 @@
from test import support
import array
+import io
import marshal
import sys
import unittest
@@ -259,6 +260,17 @@
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)):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
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.
diff --git a/Python/marshal.c b/Python/marshal.c
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -570,8 +570,17 @@
else {
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);
@@ -841,11 +850,13 @@
double dx;
retval = NULL;
n = r_byte(p);
- if (n == EOF || r_string(buf, n, p) != n) {
+ if (n == EOF) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
break;
}
+ if (r_string(buf, n, p) != n)
+ break;
buf[n] = '\0';
dx = PyOS_string_to_double(buf, NULL, NULL);
if (dx == -1.0 && PyErr_Occurred())
@@ -860,8 +871,6 @@
unsigned char buf[8];
double x;
if (r_string((char*)buf, 8, p) != 8) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
retval = NULL;
break;
}
@@ -881,21 +890,25 @@
Py_complex c;
retval = NULL;
n = r_byte(p);
- if (n == EOF || r_string(buf, n, p) != n) {
+ if (n == EOF) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
break;
}
+ if (r_string(buf, n, p) != n)
+ break;
buf[n] = '\0';
c.real = PyOS_string_to_double(buf, NULL, NULL);
if (c.real == -1.0 && PyErr_Occurred())
break;
n = r_byte(p);
- if (n == EOF || r_string(buf, n, p) != n) {
+ if (n == EOF) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
break;
}
+ if (r_string(buf, n, p) != n)
+ break;
buf[n] = '\0';
c.imag = PyOS_string_to_double(buf, NULL, NULL);
if (c.imag == -1.0 && PyErr_Occurred())
@@ -910,8 +923,6 @@
unsigned char buf[8];
Py_complex c;
if (r_string((char*)buf, 8, p) != 8) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
retval = NULL;
break;
}
@@ -921,8 +932,6 @@
break;
}
if (r_string((char*)buf, 8, p) != 8) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
retval = NULL;
break;
}
@@ -954,8 +963,6 @@
}
if (r_string(PyBytes_AS_STRING(v), n, p) != n) {
Py_DECREF(v);
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
retval = NULL;
break;
}
@@ -986,8 +993,6 @@
}
if (r_string(buffer, n, p) != n) {
PyMem_DEL(buffer);
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
retval = NULL;
break;
}
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list