summaryrefslogtreecommitdiff
path: root/Python/marshal.c
diff options
context:
space:
mode:
authorNeal Norwitz <nnorwitz@gmail.com>2007-05-16 20:05:11 +0000
committerNeal Norwitz <nnorwitz@gmail.com>2007-05-16 20:05:11 +0000
commit649ee1f2ef59b21c96321f0b9919cc7b83a90e55 (patch)
treecfba1c0e87dc4157c4d7b144c2d9fbb8a8d8bd92 /Python/marshal.c
parentd3f8f7c99eefdbf7f832ac7d610f67b1688cd72f (diff)
downloadcpython-649ee1f2ef59b21c96321f0b9919cc7b83a90e55.tar.gz
Fix bug in marshal where bad data would cause a segfault due to
lack of an infinite recursion check. Contributed by Damien Miller at Google.
Diffstat (limited to 'Python/marshal.c')
-rw-r--r--Python/marshal.c225
1 files changed, 156 insertions, 69 deletions
diff --git a/Python/marshal.c b/Python/marshal.c
index 776836e557..8faea4726d 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -246,9 +246,16 @@ w_object(PyObject *v, WFILE *p)
goto exit;
}
else {
+ int ok;
o = PyInt_FromSsize_t(PyDict_Size(p->strings));
- PyDict_SetItem(p->strings, v, o);
- Py_DECREF(o);
+ ok = o &&
+ PyDict_SetItem(p->strings, v, o) >= 0;
+ Py_XDECREF(o);
+ if (!ok) {
+ p->depth--;
+ p->error = 1;
+ return;
+ }
w_byte(TYPE_INTERNED, p);
}
}
@@ -413,7 +420,7 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
typedef WFILE RFILE; /* Same struct with different invariants */
-#define rs_byte(p) (((p)->ptr != (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)
+#define rs_byte(p) (((p)->ptr < (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)
#define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p))
@@ -504,42 +511,60 @@ r_object(RFILE *p)
PyObject *v, *v2, *v3;
long i, n;
int type = r_byte(p);
+ PyObject *retval;
+
+ p->depth++;
+
+ if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
+ p->depth--;
+ PyErr_SetString(PyExc_ValueError, "recursion limit exceeded");
+ return NULL;
+ }
switch (type) {
case EOF:
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
case TYPE_NULL:
- return NULL;
+ retval = NULL;
+ break;
case TYPE_NONE:
Py_INCREF(Py_None);
- return Py_None;
+ retval = Py_None;
+ break;
case TYPE_STOPITER:
Py_INCREF(PyExc_StopIteration);
- return PyExc_StopIteration;
+ retval = PyExc_StopIteration;
+ break;
case TYPE_ELLIPSIS:
Py_INCREF(Py_Ellipsis);
- return Py_Ellipsis;
+ retval = Py_Ellipsis;
+ break;
case TYPE_FALSE:
Py_INCREF(Py_False);
- return Py_False;
+ retval = Py_False;
+ break;
case TYPE_TRUE:
Py_INCREF(Py_True);
- return Py_True;
+ retval = Py_True;
+ break;
case TYPE_INT:
- return PyInt_FromLong(r_long(p));
+ retval = PyInt_FromLong(r_long(p));
+ break;
case TYPE_INT64:
- return r_long64(p);
+ retval = r_long64(p);
+ break;
case TYPE_LONG:
{
@@ -549,12 +574,15 @@ r_object(RFILE *p)
if (n < -INT_MAX || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError,
"bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
size = n<0 ? -n : n;
ob = _PyLong_New(size);
- if (ob == NULL)
- return NULL;
+ if (ob == NULL) {
+ retval = NULL;
+ break;
+ }
ob->ob_size = n;
for (i = 0; i < size; i++) {
int digit = r_short(p);
@@ -562,11 +590,14 @@ r_object(RFILE *p)
Py_DECREF(ob);
PyErr_SetString(PyExc_ValueError,
"bad marshal data");
- return NULL;
+ ob = NULL;
+ break;
}
- ob->ob_digit[i] = digit;
+ if (ob != NULL)
+ ob->ob_digit[i] = digit;
}
- return (PyObject *)ob;
+ retval = (PyObject *)ob;
+ break;
}
case TYPE_FLOAT:
@@ -577,13 +608,16 @@ r_object(RFILE *p)
if (n == EOF || r_string(buf, (int)n, p) != n) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
buf[n] = '\0';
- PyFPE_START_PROTECT("atof", return 0)
+ retval = NULL;
+ PyFPE_START_PROTECT("atof", break)
dx = PyOS_ascii_atof(buf);
PyFPE_END_PROTECT(dx)
- return PyFloat_FromDouble(dx);
+ retval = PyFloat_FromDouble(dx);
+ break;
}
case TYPE_BINARY_FLOAT:
@@ -593,13 +627,16 @@ r_object(RFILE *p)
if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
x = _PyFloat_Unpack8(buf, 1);
if (x == -1.0 && PyErr_Occurred()) {
- return NULL;
+ retval = NULL;
+ break;
}
- return PyFloat_FromDouble(x);
+ retval = PyFloat_FromDouble(x);
+ break;
}
#ifndef WITHOUT_COMPLEX
@@ -611,23 +648,27 @@ r_object(RFILE *p)
if (n == EOF || r_string(buf, (int)n, p) != n) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
buf[n] = '\0';
- PyFPE_START_PROTECT("atof", return 0)
+ retval = NULL;
+ PyFPE_START_PROTECT("atof", break;)
c.real = PyOS_ascii_atof(buf);
PyFPE_END_PROTECT(c)
n = r_byte(p);
if (n == EOF || r_string(buf, (int)n, p) != n) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
buf[n] = '\0';
- PyFPE_START_PROTECT("atof", return 0)
+ PyFPE_START_PROTECT("atof", break)
c.imag = PyOS_ascii_atof(buf);
PyFPE_END_PROTECT(c)
- return PyComplex_FromCComplex(c);
+ retval = PyComplex_FromCComplex(c);
+ break;
}
case TYPE_BINARY_COMPLEX:
@@ -637,22 +678,27 @@ r_object(RFILE *p)
if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
c.real = _PyFloat_Unpack8(buf, 1);
if (c.real == -1.0 && PyErr_Occurred()) {
- return NULL;
+ retval = NULL;
+ break;
}
if (r_string((char*)buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
c.imag = _PyFloat_Unpack8(buf, 1);
if (c.imag == -1.0 && PyErr_Occurred()) {
- return NULL;
+ retval = NULL;
+ break;
}
- return PyComplex_FromCComplex(c);
+ retval = PyComplex_FromCComplex(c);
+ break;
}
#endif
@@ -661,32 +707,42 @@ r_object(RFILE *p)
n = r_long(p);
if (n < 0 || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyString_FromStringAndSize((char *)NULL, n);
- if (v == NULL)
- return v;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
if (r_string(PyString_AS_STRING(v), (int)n, p) != n) {
Py_DECREF(v);
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
if (type == TYPE_INTERNED) {
PyString_InternInPlace(&v);
- PyList_Append(p->strings, v);
+ if (PyList_Append(p->strings, v) < 0) {
+ retval = NULL;
+ break;
+ }
}
- return v;
+ retval = v;
+ break;
case TYPE_STRINGREF:
n = r_long(p);
if (n < 0 || n >= PyList_GET_SIZE(p->strings)) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyList_GET_ITEM(p->strings, n);
Py_INCREF(v);
- return v;
+ retval = v;
+ break;
#ifdef Py_USING_UNICODE
case TYPE_UNICODE:
@@ -696,20 +752,25 @@ r_object(RFILE *p)
n = r_long(p);
if (n < 0 || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
buffer = PyMem_NEW(char, n);
- if (buffer == NULL)
- return PyErr_NoMemory();
+ if (buffer == NULL) {
+ retval = PyErr_NoMemory();
+ break;
+ }
if (r_string(buffer, (int)n, p) != n) {
PyMem_DEL(buffer);
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyUnicode_DecodeUTF8(buffer, n, NULL);
PyMem_DEL(buffer);
- return v;
+ retval = v;
+ break;
}
#endif
@@ -717,11 +778,14 @@ r_object(RFILE *p)
n = r_long(p);
if (n < 0 || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyTuple_New((int)n);
- if (v == NULL)
- return v;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
for (i = 0; i < n; i++) {
v2 = r_object(p);
if ( v2 == NULL ) {
@@ -734,17 +798,21 @@ r_object(RFILE *p)
}
PyTuple_SET_ITEM(v, (int)i, v2);
}
- return v;
+ retval = v;
+ break;
case TYPE_LIST:
n = r_long(p);
if (n < 0 || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyList_New((int)n);
- if (v == NULL)
- return v;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
for (i = 0; i < n; i++) {
v2 = r_object(p);
if ( v2 == NULL ) {
@@ -755,14 +823,17 @@ r_object(RFILE *p)
v = NULL;
break;
}
- PyList_SetItem(v, (int)i, v2);
+ PyList_SET_ITEM(v, (int)i, v2);
}
- return v;
+ retval = v;
+ break;
case TYPE_DICT:
v = PyDict_New();
- if (v == NULL)
- return NULL;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
for (;;) {
PyObject *key, *val;
key = r_object(p);
@@ -778,18 +849,22 @@ r_object(RFILE *p)
Py_DECREF(v);
v = NULL;
}
- return v;
+ retval = v;
+ break;
case TYPE_SET:
case TYPE_FROZENSET:
n = r_long(p);
- if (n < 0) {
+ if (n < 0 || n > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
v = PyTuple_New((int)n);
- if (v == NULL)
- return v;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
for (i = 0; i < n; i++) {
v2 = r_object(p);
if ( v2 == NULL ) {
@@ -802,21 +877,25 @@ r_object(RFILE *p)
}
PyTuple_SET_ITEM(v, (int)i, v2);
}
- if (v == NULL)
- return v;
+ if (v == NULL) {
+ retval = NULL;
+ break;
+ }
if (type == TYPE_SET)
v3 = PySet_New(v);
else
v3 = PyFrozenSet_New(v);
Py_DECREF(v);
- return v3;
+ retval = v3;
+ break;
case TYPE_CODE:
if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError,
"cannot unmarshal code objects in "
"restricted execution mode");
- return NULL;
+ retval = NULL;
+ break;
}
else {
int argcount;
@@ -888,15 +967,19 @@ r_object(RFILE *p)
Py_XDECREF(lnotab);
}
- return v;
+ retval = v;
+ break;
default:
/* Bogus data got written, which isn't ideal.
This will let you keep working and recover. */
PyErr_SetString(PyExc_ValueError, "bad marshal data");
- return NULL;
+ retval = NULL;
+ break;
}
+ p->depth--;
+ return retval;
}
static PyObject *
@@ -1002,6 +1085,7 @@ PyMarshal_ReadObjectFromFile(FILE *fp)
PyObject *result;
rf.fp = fp;
rf.strings = PyList_New(0);
+ rf.depth = 0;
result = r_object(&rf);
Py_DECREF(rf.strings);
return result;
@@ -1016,6 +1100,7 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len)
rf.ptr = str;
rf.end = str + len;
rf.strings = PyList_New(0);
+ rf.depth = 0;
result = r_object(&rf);
Py_DECREF(rf.strings);
return result;
@@ -1104,6 +1189,7 @@ marshal_load(PyObject *self, PyObject *f)
}
rf.fp = PyFile_AsFile(f);
rf.strings = PyList_New(0);
+ rf.depth = 0;
result = read_object(&rf);
Py_DECREF(rf.strings);
return result;
@@ -1132,6 +1218,7 @@ marshal_loads(PyObject *self, PyObject *args)
rf.ptr = s;
rf.end = s + n;
rf.strings = PyList_New(0);
+ rf.depth = 0;
result = read_object(&rf);
Py_DECREF(rf.strings);
return result;