From 01ab279056c0452516e58d47979be70455d3f581 Mon Sep 17 00:00:00 2001 From: Armin Rigo Date: Fri, 26 Mar 2004 15:09:27 +0000 Subject: [PATCH] Marshal clean-up (SF patch #873224) --- Lib/test/test_marshal.py | 5 ++ Python/import.c | 14 ++--- Python/marshal.c | 117 ++++++++++++++++++--------------------- 3 files changed, 66 insertions(+), 70 deletions(-) diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index f971d11f8f7..eb075217884 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -175,6 +175,11 @@ class BugsTestCase(unittest.TestCase): # Simple-minded check for SF 588452: Debug build crashes marshal.dumps([128] * 1000) + def test_patch_873224(self): + self.assertRaises(Exception, marshal.loads, '0') + self.assertRaises(Exception, marshal.loads, 'f') + self.assertRaises(Exception, marshal.loads, marshal.dumps(5L)[:-1]) + def test_main(): test_support.run_unittest(IntTestCase, FloatTestCase, diff --git a/Python/import.c b/Python/import.c index 5479677aa3d..71ee6c3e56e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -706,12 +706,12 @@ read_compiled_module(char *cpathname, FILE *fp) PyObject *co; co = PyMarshal_ReadLastObjectFromFile(fp); - /* Ugly: rd_object() may return NULL with or without error */ - if (co == NULL || !PyCode_Check(co)) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_ImportError, - "Non-code object in %.200s", cpathname); - Py_XDECREF(co); + if (co == NULL) + return NULL; + if (!PyCode_Check(co)) { + PyErr_Format(PyExc_ImportError, + "Non-code object in %.200s", cpathname); + Py_DECREF(co); return NULL; } return (PyCodeObject *)co; @@ -819,7 +819,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, long mtime) /* First write a 0 for mtime */ PyMarshal_WriteLongToFile(0L, fp); PyMarshal_WriteObjectToFile((PyObject *)co, fp); - if (ferror(fp)) { + if (fflush(fp) != 0 || ferror(fp)) { if (Py_VerboseFlag) PySys_WriteStderr("# can't write %s\n", cpathname); /* Don't keep partial file */ diff --git a/Python/marshal.c b/Python/marshal.c index 0bb7b4f69cd..d3cd659314b 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -380,6 +380,8 @@ r_long64(RFILE *p) static PyObject * r_object(RFILE *p) { + /* NULL is a valid return value, it does not necessarily means that + an exception is set. */ PyObject *v, *v2; long i, n; int type = r_byte(p); @@ -430,8 +432,16 @@ r_object(RFILE *p) if (ob == NULL) return NULL; ob->ob_size = n; - for (i = 0; i < size; i++) - ob->ob_digit[i] = r_short(p); + for (i = 0; i < size; i++) { + int digit = r_short(p); + if (digit < 0) { + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data"); + return NULL; + } + ob->ob_digit[i] = digit; + } return (PyObject *)ob; } @@ -440,7 +450,7 @@ r_object(RFILE *p) char buf[256]; double dx; n = r_byte(p); - if (r_string(buf, (int)n, p) != n) { + if (n == EOF || r_string(buf, (int)n, p) != n) { PyErr_SetString(PyExc_EOFError, "EOF read where object expected"); return NULL; @@ -458,7 +468,7 @@ r_object(RFILE *p) char buf[256]; Py_complex c; n = r_byte(p); - if (r_string(buf, (int)n, p) != n) { + if (n == EOF || r_string(buf, (int)n, p) != n) { PyErr_SetString(PyExc_EOFError, "EOF read where object expected"); return NULL; @@ -468,7 +478,7 @@ r_object(RFILE *p) c.real = atof(buf); PyFPE_END_PROTECT(c) n = r_byte(p); - if (r_string(buf, (int)n, p) != n) { + if (n == EOF || r_string(buf, (int)n, p) != n) { PyErr_SetString(PyExc_EOFError, "EOF read where object expected"); return NULL; @@ -535,6 +545,9 @@ r_object(RFILE *p) for (i = 0; i < n; i++) { v2 = r_object(p); if ( v2 == NULL ) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, + "NULL object in marshal data"); Py_DECREF(v); v = NULL; break; @@ -555,6 +568,9 @@ r_object(RFILE *p) for (i = 0; i < n; i++) { v2 = r_object(p); if ( v2 == NULL ) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, + "NULL object in marshal data"); Py_DECREF(v); v = NULL; break; @@ -571,13 +587,17 @@ r_object(RFILE *p) PyObject *key, *val; key = r_object(p); if (key == NULL) - break; /* XXX Assume TYPE_NULL, not an error */ + break; val = r_object(p); if (val != NULL) PyDict_SetItem(v, key, val); Py_DECREF(key); Py_XDECREF(val); } + if (PyErr_Occurred()) { + Py_DECREF(v); + v = NULL; + } return v; case TYPE_CODE: @@ -592,29 +612,16 @@ r_object(RFILE *p) int nlocals = r_long(p); int stacksize = r_long(p); int flags = r_long(p); - PyObject *code = NULL; - PyObject *consts = NULL; - PyObject *names = NULL; - PyObject *varnames = NULL; - PyObject *freevars = NULL; - PyObject *cellvars = NULL; - PyObject *filename = NULL; - PyObject *name = NULL; - int firstlineno = 0; - PyObject *lnotab = NULL; - - code = r_object(p); - if (code) consts = r_object(p); - if (consts) names = r_object(p); - if (names) varnames = r_object(p); - if (varnames) freevars = r_object(p); - if (freevars) cellvars = r_object(p); - if (cellvars) filename = r_object(p); - if (filename) name = r_object(p); - if (name) { - firstlineno = r_long(p); - lnotab = r_object(p); - } + PyObject *code = r_object(p); + PyObject *consts = r_object(p); + PyObject *names = r_object(p); + PyObject *varnames = r_object(p); + PyObject *freevars = r_object(p); + PyObject *cellvars = r_object(p); + PyObject *filename = r_object(p); + PyObject *name = r_object(p); + int firstlineno = r_long(p); + PyObject *lnotab = r_object(p); if (!PyErr_Occurred()) { v = (PyObject *) PyCode_New( @@ -647,6 +654,20 @@ r_object(RFILE *p) } } +PyObject * +read_object(RFILE *p) +{ + PyObject *v; + if (PyErr_Occurred()) { + fprintf(stderr, "XXX readobject called with exception set\n"); + return NULL; + } + v = r_object(p); + if (v == NULL && !PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, "NULL object in marshal data"); + return v; +} + int PyMarshal_ReadShortFromFile(FILE *fp) { @@ -693,10 +714,6 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) #ifdef HAVE_FSTAT off_t filesize; #endif - if (PyErr_Occurred()) { - fprintf(stderr, "XXX rd_object called with exception set\n"); - return NULL; - } #ifdef HAVE_FSTAT filesize = getfilesize(fp); if (filesize > 0) { @@ -730,27 +747,18 @@ PyObject * PyMarshal_ReadObjectFromFile(FILE *fp) { RFILE rf; - if (PyErr_Occurred()) { - fprintf(stderr, "XXX rd_object called with exception set\n"); - return NULL; - } rf.fp = fp; - return r_object(&rf); + return read_object(&rf); } PyObject * PyMarshal_ReadObjectFromString(char *str, int len) { RFILE rf; - if (PyErr_Occurred()) { - fprintf(stderr, "XXX rds_object called with exception set\n"); - return NULL; - } rf.fp = NULL; - rf.str = NULL; rf.ptr = str; rf.end = str + len; - return r_object(&rf); + return read_object(&rf); } PyObject * @@ -816,7 +824,6 @@ marshal_load(PyObject *self, PyObject *args) { RFILE rf; PyObject *f; - PyObject *v; if (!PyArg_ParseTuple(args, "O:load", &f)) return NULL; if (!PyFile_Check(f)) { @@ -825,15 +832,7 @@ marshal_load(PyObject *self, PyObject *args) return NULL; } rf.fp = PyFile_AsFile(f); - rf.str = NULL; - rf.ptr = rf.end = NULL; - PyErr_Clear(); - v = r_object(&rf); - if (PyErr_Occurred()) { - Py_XDECREF(v); - v = NULL; - } - return v; + return read_object(&rf); } static PyObject * @@ -849,22 +848,14 @@ static PyObject * marshal_loads(PyObject *self, PyObject *args) { RFILE rf; - PyObject *v; char *s; int n; if (!PyArg_ParseTuple(args, "s#:loads", &s, &n)) return NULL; rf.fp = NULL; - rf.str = args; rf.ptr = s; rf.end = s + n; - PyErr_Clear(); - v = r_object(&rf); - if (PyErr_Occurred()) { - Py_XDECREF(v); - v = NULL; - } - return v; + return read_object(&rf); } static PyMethodDef marshal_methods[] = {