Commit f03a51cb authored by Armin Rigo's avatar Armin Rigo

Marshal clean-up (SF patch #873224)

parent 37b10a7d
...@@ -175,6 +175,11 @@ class BugsTestCase(unittest.TestCase): ...@@ -175,6 +175,11 @@ class BugsTestCase(unittest.TestCase):
# Simple-minded check for SF 588452: Debug build crashes # Simple-minded check for SF 588452: Debug build crashes
marshal.dumps([128] * 1000) 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(): def test_main():
test_support.run_unittest(IntTestCase, test_support.run_unittest(IntTestCase,
FloatTestCase, FloatTestCase,
......
...@@ -706,12 +706,12 @@ read_compiled_module(char *cpathname, FILE *fp) ...@@ -706,12 +706,12 @@ read_compiled_module(char *cpathname, FILE *fp)
PyObject *co; PyObject *co;
co = PyMarshal_ReadLastObjectFromFile(fp); co = PyMarshal_ReadLastObjectFromFile(fp);
/* Ugly: rd_object() may return NULL with or without error */ if (co == NULL)
if (co == NULL || !PyCode_Check(co)) { return NULL;
if (!PyErr_Occurred()) if (!PyCode_Check(co)) {
PyErr_Format(PyExc_ImportError, PyErr_Format(PyExc_ImportError,
"Non-code object in %.200s", cpathname); "Non-code object in %.200s", cpathname);
Py_XDECREF(co); Py_DECREF(co);
return NULL; return NULL;
} }
return (PyCodeObject *)co; return (PyCodeObject *)co;
...@@ -819,7 +819,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, long mtime) ...@@ -819,7 +819,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, long mtime)
/* First write a 0 for mtime */ /* First write a 0 for mtime */
PyMarshal_WriteLongToFile(0L, fp); PyMarshal_WriteLongToFile(0L, fp);
PyMarshal_WriteObjectToFile((PyObject *)co, fp); PyMarshal_WriteObjectToFile((PyObject *)co, fp);
if (ferror(fp)) { if (fflush(fp) != 0 || ferror(fp)) {
if (Py_VerboseFlag) if (Py_VerboseFlag)
PySys_WriteStderr("# can't write %s\n", cpathname); PySys_WriteStderr("# can't write %s\n", cpathname);
/* Don't keep partial file */ /* Don't keep partial file */
......
...@@ -380,6 +380,8 @@ r_long64(RFILE *p) ...@@ -380,6 +380,8 @@ r_long64(RFILE *p)
static PyObject * static PyObject *
r_object(RFILE *p) r_object(RFILE *p)
{ {
/* NULL is a valid return value, it does not necessarily means that
an exception is set. */
PyObject *v, *v2; PyObject *v, *v2;
long i, n; long i, n;
int type = r_byte(p); int type = r_byte(p);
...@@ -430,8 +432,16 @@ r_object(RFILE *p) ...@@ -430,8 +432,16 @@ r_object(RFILE *p)
if (ob == NULL) if (ob == NULL)
return NULL; return NULL;
ob->ob_size = n; ob->ob_size = n;
for (i = 0; i < size; i++) for (i = 0; i < size; i++) {
ob->ob_digit[i] = r_short(p); 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; return (PyObject *)ob;
} }
...@@ -440,7 +450,7 @@ r_object(RFILE *p) ...@@ -440,7 +450,7 @@ r_object(RFILE *p)
char buf[256]; char buf[256];
double dx; double dx;
n = r_byte(p); 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, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
return NULL; return NULL;
...@@ -458,7 +468,7 @@ r_object(RFILE *p) ...@@ -458,7 +468,7 @@ r_object(RFILE *p)
char buf[256]; char buf[256];
Py_complex c; Py_complex c;
n = r_byte(p); 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, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
return NULL; return NULL;
...@@ -468,7 +478,7 @@ r_object(RFILE *p) ...@@ -468,7 +478,7 @@ r_object(RFILE *p)
c.real = atof(buf); c.real = atof(buf);
PyFPE_END_PROTECT(c) PyFPE_END_PROTECT(c)
n = r_byte(p); 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, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
return NULL; return NULL;
...@@ -535,6 +545,9 @@ r_object(RFILE *p) ...@@ -535,6 +545,9 @@ r_object(RFILE *p)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
v2 = r_object(p); v2 = r_object(p);
if ( v2 == NULL ) { if ( v2 == NULL ) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"NULL object in marshal data");
Py_DECREF(v); Py_DECREF(v);
v = NULL; v = NULL;
break; break;
...@@ -555,6 +568,9 @@ r_object(RFILE *p) ...@@ -555,6 +568,9 @@ r_object(RFILE *p)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
v2 = r_object(p); v2 = r_object(p);
if ( v2 == NULL ) { if ( v2 == NULL ) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"NULL object in marshal data");
Py_DECREF(v); Py_DECREF(v);
v = NULL; v = NULL;
break; break;
...@@ -571,13 +587,17 @@ r_object(RFILE *p) ...@@ -571,13 +587,17 @@ r_object(RFILE *p)
PyObject *key, *val; PyObject *key, *val;
key = r_object(p); key = r_object(p);
if (key == NULL) if (key == NULL)
break; /* XXX Assume TYPE_NULL, not an error */ break;
val = r_object(p); val = r_object(p);
if (val != NULL) if (val != NULL)
PyDict_SetItem(v, key, val); PyDict_SetItem(v, key, val);
Py_DECREF(key); Py_DECREF(key);
Py_XDECREF(val); Py_XDECREF(val);
} }
if (PyErr_Occurred()) {
Py_DECREF(v);
v = NULL;
}
return v; return v;
case TYPE_CODE: case TYPE_CODE:
...@@ -592,29 +612,16 @@ r_object(RFILE *p) ...@@ -592,29 +612,16 @@ r_object(RFILE *p)
int nlocals = r_long(p); int nlocals = r_long(p);
int stacksize = r_long(p); int stacksize = r_long(p);
int flags = r_long(p); int flags = r_long(p);
PyObject *code = NULL; PyObject *code = r_object(p);
PyObject *consts = NULL; PyObject *consts = r_object(p);
PyObject *names = NULL; PyObject *names = r_object(p);
PyObject *varnames = NULL; PyObject *varnames = r_object(p);
PyObject *freevars = NULL; PyObject *freevars = r_object(p);
PyObject *cellvars = NULL; PyObject *cellvars = r_object(p);
PyObject *filename = NULL; PyObject *filename = r_object(p);
PyObject *name = NULL; PyObject *name = r_object(p);
int firstlineno = 0; int firstlineno = r_long(p);
PyObject *lnotab = NULL; PyObject *lnotab = r_object(p);
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);
}
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
v = (PyObject *) PyCode_New( v = (PyObject *) PyCode_New(
...@@ -647,6 +654,20 @@ r_object(RFILE *p) ...@@ -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 int
PyMarshal_ReadShortFromFile(FILE *fp) PyMarshal_ReadShortFromFile(FILE *fp)
{ {
...@@ -693,10 +714,6 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) ...@@ -693,10 +714,6 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp)
#ifdef HAVE_FSTAT #ifdef HAVE_FSTAT
off_t filesize; off_t filesize;
#endif #endif
if (PyErr_Occurred()) {
fprintf(stderr, "XXX rd_object called with exception set\n");
return NULL;
}
#ifdef HAVE_FSTAT #ifdef HAVE_FSTAT
filesize = getfilesize(fp); filesize = getfilesize(fp);
if (filesize > 0) { if (filesize > 0) {
...@@ -730,27 +747,18 @@ PyObject * ...@@ -730,27 +747,18 @@ PyObject *
PyMarshal_ReadObjectFromFile(FILE *fp) PyMarshal_ReadObjectFromFile(FILE *fp)
{ {
RFILE rf; RFILE rf;
if (PyErr_Occurred()) {
fprintf(stderr, "XXX rd_object called with exception set\n");
return NULL;
}
rf.fp = fp; rf.fp = fp;
return r_object(&rf); return read_object(&rf);
} }
PyObject * PyObject *
PyMarshal_ReadObjectFromString(char *str, int len) PyMarshal_ReadObjectFromString(char *str, int len)
{ {
RFILE rf; RFILE rf;
if (PyErr_Occurred()) {
fprintf(stderr, "XXX rds_object called with exception set\n");
return NULL;
}
rf.fp = NULL; rf.fp = NULL;
rf.str = NULL;
rf.ptr = str; rf.ptr = str;
rf.end = str + len; rf.end = str + len;
return r_object(&rf); return read_object(&rf);
} }
PyObject * PyObject *
...@@ -816,7 +824,6 @@ marshal_load(PyObject *self, PyObject *args) ...@@ -816,7 +824,6 @@ marshal_load(PyObject *self, PyObject *args)
{ {
RFILE rf; RFILE rf;
PyObject *f; PyObject *f;
PyObject *v;
if (!PyArg_ParseTuple(args, "O:load", &f)) if (!PyArg_ParseTuple(args, "O:load", &f))
return NULL; return NULL;
if (!PyFile_Check(f)) { if (!PyFile_Check(f)) {
...@@ -825,15 +832,7 @@ marshal_load(PyObject *self, PyObject *args) ...@@ -825,15 +832,7 @@ marshal_load(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
rf.fp = PyFile_AsFile(f); rf.fp = PyFile_AsFile(f);
rf.str = NULL; return read_object(&rf);
rf.ptr = rf.end = NULL;
PyErr_Clear();
v = r_object(&rf);
if (PyErr_Occurred()) {
Py_XDECREF(v);
v = NULL;
}
return v;
} }
static PyObject * static PyObject *
...@@ -849,22 +848,14 @@ static PyObject * ...@@ -849,22 +848,14 @@ static PyObject *
marshal_loads(PyObject *self, PyObject *args) marshal_loads(PyObject *self, PyObject *args)
{ {
RFILE rf; RFILE rf;
PyObject *v;
char *s; char *s;
int n; int n;
if (!PyArg_ParseTuple(args, "s#:loads", &s, &n)) if (!PyArg_ParseTuple(args, "s#:loads", &s, &n))
return NULL; return NULL;
rf.fp = NULL; rf.fp = NULL;
rf.str = args;
rf.ptr = s; rf.ptr = s;
rf.end = s + n; rf.end = s + n;
PyErr_Clear(); return read_object(&rf);
v = r_object(&rf);
if (PyErr_Occurred()) {
Py_XDECREF(v);
v = NULL;
}
return v;
} }
static PyMethodDef marshal_methods[] = { static PyMethodDef marshal_methods[] = {
......
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