diff Python/marshal.c @ 84557:5fa793ae36cc

Issue #17872: Fix a segfault in marshal.load() when input stream returns more bytes than requested.
author Serhiy Storchaka <storchaka@gmail.com>
date Thu, 11 Jul 2013 22:28:18 +0300
parents 19ed630d8d75 fc7bab8a8618
children e7f6cef7a4cc
line wrap: on
line diff
--- a/Python/marshal.c	Thu Jul 11 22:00:57 2013 +0300
+++ b/Python/marshal.c	Thu Jul 11 22:28:18 2013 +0300
@@ -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;
             }