diff options
Diffstat (limited to 'Python/marshal.c')
-rw-r--r-- | Python/marshal.c | 2130 |
1 files changed, 1065 insertions, 1065 deletions
diff --git a/Python/marshal.c b/Python/marshal.c index 90cd306..73d4f37 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -24,28 +24,28 @@ #define MAX_MARSHAL_STACK_DEPTH 2000 #endif -#define TYPE_NULL '0' -#define TYPE_NONE 'N' -#define TYPE_FALSE 'F' -#define TYPE_TRUE 'T' -#define TYPE_STOPITER 'S' -#define TYPE_ELLIPSIS '.' -#define TYPE_INT 'i' -#define TYPE_INT64 'I' -#define TYPE_FLOAT 'f' -#define TYPE_BINARY_FLOAT 'g' -#define TYPE_COMPLEX 'x' -#define TYPE_BINARY_COMPLEX 'y' -#define TYPE_LONG 'l' -#define TYPE_STRING 's' -#define TYPE_TUPLE '(' -#define TYPE_LIST '[' -#define TYPE_DICT '{' -#define TYPE_CODE 'c' -#define TYPE_UNICODE 'u' -#define TYPE_UNKNOWN '?' -#define TYPE_SET '<' -#define TYPE_FROZENSET '>' +#define TYPE_NULL '0' +#define TYPE_NONE 'N' +#define TYPE_FALSE 'F' +#define TYPE_TRUE 'T' +#define TYPE_STOPITER 'S' +#define TYPE_ELLIPSIS '.' +#define TYPE_INT 'i' +#define TYPE_INT64 'I' +#define TYPE_FLOAT 'f' +#define TYPE_BINARY_FLOAT 'g' +#define TYPE_COMPLEX 'x' +#define TYPE_BINARY_COMPLEX 'y' +#define TYPE_LONG 'l' +#define TYPE_STRING 's' +#define TYPE_TUPLE '(' +#define TYPE_LIST '[' +#define TYPE_DICT '{' +#define TYPE_CODE 'c' +#define TYPE_UNICODE 'u' +#define TYPE_UNKNOWN '?' +#define TYPE_SET '<' +#define TYPE_FROZENSET '>' #define WFERR_OK 0 #define WFERR_UNMARSHALLABLE 1 @@ -53,79 +53,79 @@ #define WFERR_NOMEMORY 3 typedef struct { - FILE *fp; - int error; /* see WFERR_* values */ - int depth; - /* If fp == NULL, the following are valid: */ - PyObject *str; - char *ptr; - char *end; - PyObject *strings; /* dict on marshal, list on unmarshal */ - int version; + FILE *fp; + int error; /* see WFERR_* values */ + int depth; + /* If fp == NULL, the following are valid: */ + PyObject *str; + char *ptr; + char *end; + PyObject *strings; /* dict on marshal, list on unmarshal */ + int version; } WFILE; #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \ - else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \ - else w_more(c, p) + else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \ + else w_more(c, p) static void w_more(int c, WFILE *p) { - Py_ssize_t size, newsize; - if (p->str == NULL) - return; /* An error already occurred */ - size = PyBytes_Size(p->str); - newsize = size + size + 1024; - if (newsize > 32*1024*1024) { - newsize = size + (size >> 3); /* 12.5% overallocation */ - } - if (_PyBytes_Resize(&p->str, newsize) != 0) { - p->ptr = p->end = NULL; - } - else { - p->ptr = PyBytes_AS_STRING((PyBytesObject *)p->str) + size; - p->end = - PyBytes_AS_STRING((PyBytesObject *)p->str) + newsize; - *p->ptr++ = Py_SAFE_DOWNCAST(c, int, char); - } + Py_ssize_t size, newsize; + if (p->str == NULL) + return; /* An error already occurred */ + size = PyBytes_Size(p->str); + newsize = size + size + 1024; + if (newsize > 32*1024*1024) { + newsize = size + (size >> 3); /* 12.5% overallocation */ + } + if (_PyBytes_Resize(&p->str, newsize) != 0) { + p->ptr = p->end = NULL; + } + else { + p->ptr = PyBytes_AS_STRING((PyBytesObject *)p->str) + size; + p->end = + PyBytes_AS_STRING((PyBytesObject *)p->str) + newsize; + *p->ptr++ = Py_SAFE_DOWNCAST(c, int, char); + } } static void w_string(char *s, int n, WFILE *p) { - if (p->fp != NULL) { - fwrite(s, 1, n, p->fp); - } - else { - while (--n >= 0) { - w_byte(*s, p); - s++; - } - } + if (p->fp != NULL) { + fwrite(s, 1, n, p->fp); + } + else { + while (--n >= 0) { + w_byte(*s, p); + s++; + } + } } static void w_short(int x, WFILE *p) { - w_byte((char)( x & 0xff), p); - w_byte((char)((x>> 8) & 0xff), p); + w_byte((char)( x & 0xff), p); + w_byte((char)((x>> 8) & 0xff), p); } static void w_long(long x, WFILE *p) { - w_byte((char)( x & 0xff), p); - w_byte((char)((x>> 8) & 0xff), p); - w_byte((char)((x>>16) & 0xff), p); - w_byte((char)((x>>24) & 0xff), p); + w_byte((char)( x & 0xff), p); + w_byte((char)((x>> 8) & 0xff), p); + w_byte((char)((x>>16) & 0xff), p); + w_byte((char)((x>>24) & 0xff), p); } #if SIZEOF_LONG > 4 static void w_long64(long x, WFILE *p) { - w_long(x, p); - w_long(x>>32, p); + w_long(x, p); + w_long(x>>32, p); } #endif @@ -144,322 +144,322 @@ w_long64(long x, WFILE *p) static void w_PyLong(const PyLongObject *ob, WFILE *p) { - Py_ssize_t i, j, n, l; - digit d; - - w_byte(TYPE_LONG, p); - if (Py_SIZE(ob) == 0) { - w_long((long)0, p); - return; - } - - /* set l to number of base PyLong_MARSHAL_BASE digits */ - n = ABS(Py_SIZE(ob)); - l = (n-1) * PyLong_MARSHAL_RATIO; - d = ob->ob_digit[n-1]; - assert(d != 0); /* a PyLong is always normalized */ - do { - d >>= PyLong_MARSHAL_SHIFT; - l++; - } while (d != 0); - w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); - - for (i=0; i < n-1; i++) { - d = ob->ob_digit[i]; - for (j=0; j < PyLong_MARSHAL_RATIO; j++) { - w_short(d & PyLong_MARSHAL_MASK, p); - d >>= PyLong_MARSHAL_SHIFT; - } - assert (d == 0); - } - d = ob->ob_digit[n-1]; - do { - w_short(d & PyLong_MARSHAL_MASK, p); - d >>= PyLong_MARSHAL_SHIFT; - } while (d != 0); + Py_ssize_t i, j, n, l; + digit d; + + w_byte(TYPE_LONG, p); + if (Py_SIZE(ob) == 0) { + w_long((long)0, p); + return; + } + + /* set l to number of base PyLong_MARSHAL_BASE digits */ + n = ABS(Py_SIZE(ob)); + l = (n-1) * PyLong_MARSHAL_RATIO; + d = ob->ob_digit[n-1]; + assert(d != 0); /* a PyLong is always normalized */ + do { + d >>= PyLong_MARSHAL_SHIFT; + l++; + } while (d != 0); + w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); + + for (i=0; i < n-1; i++) { + d = ob->ob_digit[i]; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } + assert (d == 0); + } + d = ob->ob_digit[n-1]; + do { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } while (d != 0); } static void w_object(PyObject *v, WFILE *p) { - Py_ssize_t i, n; - - p->depth++; - - if (p->depth > MAX_MARSHAL_STACK_DEPTH) { - p->error = WFERR_NESTEDTOODEEP; - } - else if (v == NULL) { - w_byte(TYPE_NULL, p); - } - else if (v == Py_None) { - w_byte(TYPE_NONE, p); - } - else if (v == PyExc_StopIteration) { - w_byte(TYPE_STOPITER, p); - } - else if (v == Py_Ellipsis) { - w_byte(TYPE_ELLIPSIS, p); - } - else if (v == Py_False) { - w_byte(TYPE_FALSE, p); - } - else if (v == Py_True) { - w_byte(TYPE_TRUE, p); - } - else if (PyLong_CheckExact(v)) { - long x = PyLong_AsLong(v); - if ((x == -1) && PyErr_Occurred()) { - PyLongObject *ob = (PyLongObject *)v; - PyErr_Clear(); - w_PyLong(ob, p); - } - else { + Py_ssize_t i, n; + + p->depth++; + + if (p->depth > MAX_MARSHAL_STACK_DEPTH) { + p->error = WFERR_NESTEDTOODEEP; + } + else if (v == NULL) { + w_byte(TYPE_NULL, p); + } + else if (v == Py_None) { + w_byte(TYPE_NONE, p); + } + else if (v == PyExc_StopIteration) { + w_byte(TYPE_STOPITER, p); + } + else if (v == Py_Ellipsis) { + w_byte(TYPE_ELLIPSIS, p); + } + else if (v == Py_False) { + w_byte(TYPE_FALSE, p); + } + else if (v == Py_True) { + w_byte(TYPE_TRUE, p); + } + else if (PyLong_CheckExact(v)) { + long x = PyLong_AsLong(v); + if ((x == -1) && PyErr_Occurred()) { + PyLongObject *ob = (PyLongObject *)v; + PyErr_Clear(); + w_PyLong(ob, p); + } + else { #if SIZEOF_LONG > 4 - long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31); - if (y && y != -1) { - w_byte(TYPE_INT64, p); - w_long64(x, p); - } - else + long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31); + if (y && y != -1) { + w_byte(TYPE_INT64, p); + w_long64(x, p); + } + else #endif - { - w_byte(TYPE_INT, p); - w_long(x, p); - } - } - } - else if (PyFloat_CheckExact(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyFloat_AsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_BINARY_FLOAT, p); - w_string((char*)buf, 8, p); - } - else { - char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte(TYPE_FLOAT, p); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - } - } - else if (PyComplex_CheckExact(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_BINARY_COMPLEX, p); - w_string((char*)buf, 8, p); - if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_string((char*)buf, 8, p); - } - else { - char *buf; - w_byte(TYPE_COMPLEX, p); - buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - } - } - else if (PyBytes_CheckExact(v)) { - w_byte(TYPE_STRING, p); - n = PyBytes_GET_SIZE(v); - if (n > INT_MAX) { - /* huge strings are not supported */ - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(PyBytes_AS_STRING(v), (int)n, p); - } - else if (PyUnicode_CheckExact(v)) { - PyObject *utf8; - utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - "surrogatepass"); - if (utf8 == NULL) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_UNICODE, p); - n = PyBytes_GET_SIZE(utf8); - if (n > INT_MAX) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(PyBytes_AS_STRING(utf8), (int)n, p); - Py_DECREF(utf8); - } - else if (PyTuple_CheckExact(v)) { - w_byte(TYPE_TUPLE, p); - n = PyTuple_Size(v); - w_long((long)n, p); - for (i = 0; i < n; i++) { - w_object(PyTuple_GET_ITEM(v, i), p); - } - } - else if (PyList_CheckExact(v)) { - w_byte(TYPE_LIST, p); - n = PyList_GET_SIZE(v); - w_long((long)n, p); - for (i = 0; i < n; i++) { - w_object(PyList_GET_ITEM(v, i), p); - } - } - else if (PyDict_CheckExact(v)) { - Py_ssize_t pos; - PyObject *key, *value; - w_byte(TYPE_DICT, p); - /* This one is NULL object terminated! */ - pos = 0; - while (PyDict_Next(v, &pos, &key, &value)) { - w_object(key, p); - w_object(value, p); - } - w_object((PyObject *)NULL, p); - } - else if (PyAnySet_CheckExact(v)) { - PyObject *value, *it; - - if (PyObject_TypeCheck(v, &PySet_Type)) - w_byte(TYPE_SET, p); - else - w_byte(TYPE_FROZENSET, p); - n = PyObject_Size(v); - if (n == -1) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - it = PyObject_GetIter(v); - if (it == NULL) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - while ((value = PyIter_Next(it)) != NULL) { - w_object(value, p); - Py_DECREF(value); - } - Py_DECREF(it); - if (PyErr_Occurred()) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - } - else if (PyCode_Check(v)) { - PyCodeObject *co = (PyCodeObject *)v; - w_byte(TYPE_CODE, p); - w_long(co->co_argcount, p); - w_long(co->co_kwonlyargcount, p); - w_long(co->co_nlocals, p); - w_long(co->co_stacksize, p); - w_long(co->co_flags, p); - w_object(co->co_code, p); - w_object(co->co_consts, p); - w_object(co->co_names, p); - w_object(co->co_varnames, p); - w_object(co->co_freevars, p); - w_object(co->co_cellvars, p); - w_object(co->co_filename, p); - w_object(co->co_name, p); - w_long(co->co_firstlineno, p); - w_object(co->co_lnotab, p); - } - else if (PyObject_CheckBuffer(v)) { - /* Write unknown buffer-style objects as a string */ - char *s; - PyBufferProcs *pb = v->ob_type->tp_as_buffer; - Py_buffer view; - if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) { - w_byte(TYPE_UNKNOWN, p); - p->error = WFERR_UNMARSHALLABLE; - } - w_byte(TYPE_STRING, p); - n = view.len; - s = view.buf; - if (n > INT_MAX) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(s, (int)n, p); - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(v, &view); - } - else { - w_byte(TYPE_UNKNOWN, p); - p->error = WFERR_UNMARSHALLABLE; - } - p->depth--; + { + w_byte(TYPE_INT, p); + w_long(x, p); + } + } + } + else if (PyFloat_CheckExact(v)) { + if (p->version > 1) { + unsigned char buf[8]; + if (_PyFloat_Pack8(PyFloat_AsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_BINARY_FLOAT, p); + w_string((char*)buf, 8, p); + } + else { + char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte(TYPE_FLOAT, p); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + } + } + else if (PyComplex_CheckExact(v)) { + if (p->version > 1) { + unsigned char buf[8]; + if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_BINARY_COMPLEX, p); + w_string((char*)buf, 8, p); + if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_string((char*)buf, 8, p); + } + else { + char *buf; + w_byte(TYPE_COMPLEX, p); + buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + } + } + else if (PyBytes_CheckExact(v)) { + w_byte(TYPE_STRING, p); + n = PyBytes_GET_SIZE(v); + if (n > INT_MAX) { + /* huge strings are not supported */ + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(PyBytes_AS_STRING(v), (int)n, p); + } + else if (PyUnicode_CheckExact(v)) { + PyObject *utf8; + utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), + PyUnicode_GET_SIZE(v), + "surrogatepass"); + if (utf8 == NULL) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_UNICODE, p); + n = PyBytes_GET_SIZE(utf8); + if (n > INT_MAX) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(PyBytes_AS_STRING(utf8), (int)n, p); + Py_DECREF(utf8); + } + else if (PyTuple_CheckExact(v)) { + w_byte(TYPE_TUPLE, p); + n = PyTuple_Size(v); + w_long((long)n, p); + for (i = 0; i < n; i++) { + w_object(PyTuple_GET_ITEM(v, i), p); + } + } + else if (PyList_CheckExact(v)) { + w_byte(TYPE_LIST, p); + n = PyList_GET_SIZE(v); + w_long((long)n, p); + for (i = 0; i < n; i++) { + w_object(PyList_GET_ITEM(v, i), p); + } + } + else if (PyDict_CheckExact(v)) { + Py_ssize_t pos; + PyObject *key, *value; + w_byte(TYPE_DICT, p); + /* This one is NULL object terminated! */ + pos = 0; + while (PyDict_Next(v, &pos, &key, &value)) { + w_object(key, p); + w_object(value, p); + } + w_object((PyObject *)NULL, p); + } + else if (PyAnySet_CheckExact(v)) { + PyObject *value, *it; + + if (PyObject_TypeCheck(v, &PySet_Type)) + w_byte(TYPE_SET, p); + else + w_byte(TYPE_FROZENSET, p); + n = PyObject_Size(v); + if (n == -1) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + it = PyObject_GetIter(v); + if (it == NULL) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + while ((value = PyIter_Next(it)) != NULL) { + w_object(value, p); + Py_DECREF(value); + } + Py_DECREF(it); + if (PyErr_Occurred()) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + } + else if (PyCode_Check(v)) { + PyCodeObject *co = (PyCodeObject *)v; + w_byte(TYPE_CODE, p); + w_long(co->co_argcount, p); + w_long(co->co_kwonlyargcount, p); + w_long(co->co_nlocals, p); + w_long(co->co_stacksize, p); + w_long(co->co_flags, p); + w_object(co->co_code, p); + w_object(co->co_consts, p); + w_object(co->co_names, p); + w_object(co->co_varnames, p); + w_object(co->co_freevars, p); + w_object(co->co_cellvars, p); + w_object(co->co_filename, p); + w_object(co->co_name, p); + w_long(co->co_firstlineno, p); + w_object(co->co_lnotab, p); + } + else if (PyObject_CheckBuffer(v)) { + /* Write unknown buffer-style objects as a string */ + char *s; + PyBufferProcs *pb = v->ob_type->tp_as_buffer; + Py_buffer view; + if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + } + w_byte(TYPE_STRING, p); + n = view.len; + s = view.buf; + if (n > INT_MAX) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(s, (int)n, p); + if (pb->bf_releasebuffer != NULL) + (*pb->bf_releasebuffer)(v, &view); + } + else { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + } + p->depth--; } /* version currently has no effect for writing longs. */ void PyMarshal_WriteLongToFile(long x, FILE *fp, int version) { - WFILE wf; - wf.fp = fp; - wf.error = WFERR_OK; - wf.depth = 0; - wf.strings = NULL; - wf.version = version; - w_long(x, &wf); + WFILE wf; + wf.fp = fp; + wf.error = WFERR_OK; + wf.depth = 0; + wf.strings = NULL; + wf.version = version; + w_long(x, &wf); } void PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) { - WFILE wf; - wf.fp = fp; - wf.error = WFERR_OK; - wf.depth = 0; - wf.strings = (version > 0) ? PyDict_New() : NULL; - wf.version = version; - w_object(x, &wf); - Py_XDECREF(wf.strings); + WFILE wf; + wf.fp = fp; + wf.error = WFERR_OK; + wf.depth = 0; + wf.strings = (version > 0) ? PyDict_New() : NULL; + wf.version = version; + w_object(x, &wf); + Py_XDECREF(wf.strings); } typedef WFILE RFILE; /* Same struct with different invariants */ @@ -471,49 +471,49 @@ typedef WFILE RFILE; /* Same struct with different invariants */ static int r_string(char *s, int n, RFILE *p) { - if (p->fp != NULL) - /* The result fits into int because it must be <=n. */ - return (int)fread(s, 1, n, p->fp); - if (p->end - p->ptr < n) - n = (int)(p->end - p->ptr); - memcpy(s, p->ptr, n); - p->ptr += n; - return n; + if (p->fp != NULL) + /* The result fits into int because it must be <=n. */ + return (int)fread(s, 1, n, p->fp); + if (p->end - p->ptr < n) + n = (int)(p->end - p->ptr); + memcpy(s, p->ptr, n); + p->ptr += n; + return n; } static int r_short(RFILE *p) { - register short x; - x = r_byte(p); - x |= r_byte(p) << 8; - /* Sign-extension, in case short greater than 16 bits */ - x |= -(x & 0x8000); - return x; + register short x; + x = r_byte(p); + x |= r_byte(p) << 8; + /* Sign-extension, in case short greater than 16 bits */ + x |= -(x & 0x8000); + return x; } static long r_long(RFILE *p) { - register long x; - register FILE *fp = p->fp; - if (fp) { - x = getc(fp); - x |= (long)getc(fp) << 8; - x |= (long)getc(fp) << 16; - x |= (long)getc(fp) << 24; - } - else { - x = rs_byte(p); - x |= (long)rs_byte(p) << 8; - x |= (long)rs_byte(p) << 16; - x |= (long)rs_byte(p) << 24; - } + register long x; + register FILE *fp = p->fp; + if (fp) { + x = getc(fp); + x |= (long)getc(fp) << 8; + x |= (long)getc(fp) << 16; + x |= (long)getc(fp) << 24; + } + else { + x = rs_byte(p); + x |= (long)rs_byte(p) << 8; + x |= (long)rs_byte(p) << 16; + x |= (long)rs_byte(p) << 24; + } #if SIZEOF_LONG > 4 - /* Sign extension for 64-bit machines */ - x |= -(x & 0x80000000L); + /* Sign extension for 64-bit machines */ + x |= -(x & 0x80000000L); #endif - return x; + return x; } /* r_long64 deals with the TYPE_INT64 code. On a machine with @@ -526,534 +526,534 @@ r_long(RFILE *p) static PyObject * r_long64(RFILE *p) { - long lo4 = r_long(p); - long hi4 = r_long(p); + long lo4 = r_long(p); + long hi4 = r_long(p); #if SIZEOF_LONG > 4 - long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); - return PyLong_FromLong(x); + long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); + return PyLong_FromLong(x); #else - unsigned char buf[8]; - int one = 1; - int is_little_endian = (int)*(char*)&one; - if (is_little_endian) { - memcpy(buf, &lo4, 4); - memcpy(buf+4, &hi4, 4); - } - else { - memcpy(buf, &hi4, 4); - memcpy(buf+4, &lo4, 4); - } - return _PyLong_FromByteArray(buf, 8, is_little_endian, 1); + unsigned char buf[8]; + int one = 1; + int is_little_endian = (int)*(char*)&one; + if (is_little_endian) { + memcpy(buf, &lo4, 4); + memcpy(buf+4, &hi4, 4); + } + else { + memcpy(buf, &hi4, 4); + memcpy(buf+4, &lo4, 4); + } + return _PyLong_FromByteArray(buf, 8, is_little_endian, 1); #endif } static PyObject * r_PyLong(RFILE *p) { - PyLongObject *ob; - int size, i, j, md, shorts_in_top_digit; - long n; - digit d; - - n = r_long(p); - if (n == 0) - return (PyObject *)_PyLong_New(0); - if (n < -INT_MAX || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "bad marshal data (long size out of range)"); - return NULL; - } - - size = 1 + (ABS(n) - 1) / PyLong_MARSHAL_RATIO; - shorts_in_top_digit = 1 + (ABS(n) - 1) % PyLong_MARSHAL_RATIO; - ob = _PyLong_New(size); - if (ob == NULL) - return NULL; - Py_SIZE(ob) = n > 0 ? size : -size; - - for (i = 0; i < size-1; i++) { - d = 0; - for (j=0; j < PyLong_MARSHAL_RATIO; j++) { - md = r_short(p); - if (md < 0 || md > PyLong_MARSHAL_BASE) - goto bad_digit; - d += (digit)md << j*PyLong_MARSHAL_SHIFT; - } - ob->ob_digit[i] = d; - } - d = 0; - for (j=0; j < shorts_in_top_digit; j++) { - md = r_short(p); - if (md < 0 || md > PyLong_MARSHAL_BASE) - goto bad_digit; - /* topmost marshal digit should be nonzero */ - if (md == 0 && j == shorts_in_top_digit - 1) { - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (unnormalized long data)"); - return NULL; - } - d += (digit)md << j*PyLong_MARSHAL_SHIFT; - } - /* top digit should be nonzero, else the resulting PyLong won't be - normalized */ - ob->ob_digit[size-1] = d; - return (PyObject *)ob; + PyLongObject *ob; + int size, i, j, md, shorts_in_top_digit; + long n; + digit d; + + n = r_long(p); + if (n == 0) + return (PyObject *)_PyLong_New(0); + if (n < -INT_MAX || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "bad marshal data (long size out of range)"); + return NULL; + } + + size = 1 + (ABS(n) - 1) / PyLong_MARSHAL_RATIO; + shorts_in_top_digit = 1 + (ABS(n) - 1) % PyLong_MARSHAL_RATIO; + ob = _PyLong_New(size); + if (ob == NULL) + return NULL; + Py_SIZE(ob) = n > 0 ? size : -size; + + for (i = 0; i < size-1; i++) { + d = 0; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[i] = d; + } + d = 0; + for (j=0; j < shorts_in_top_digit; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + /* topmost marshal digit should be nonzero */ + if (md == 0 && j == shorts_in_top_digit - 1) { + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (unnormalized long data)"); + return NULL; + } + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + /* top digit should be nonzero, else the resulting PyLong won't be + normalized */ + ob->ob_digit[size-1] = d; + return (PyObject *)ob; bad_digit: - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (digit out of range in long)"); - return NULL; + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (digit out of range in long)"); + return NULL; } 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); - 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"); - retval = NULL; - break; - - case TYPE_NULL: - retval = NULL; - break; - - case TYPE_NONE: - Py_INCREF(Py_None); - retval = Py_None; - break; - - case TYPE_STOPITER: - Py_INCREF(PyExc_StopIteration); - retval = PyExc_StopIteration; - break; - - case TYPE_ELLIPSIS: - Py_INCREF(Py_Ellipsis); - retval = Py_Ellipsis; - break; - - case TYPE_FALSE: - Py_INCREF(Py_False); - retval = Py_False; - break; - - case TYPE_TRUE: - Py_INCREF(Py_True); - retval = Py_True; - break; - - case TYPE_INT: - retval = PyLong_FromLong(r_long(p)); - break; - - case TYPE_INT64: - retval = r_long64(p); - break; - - case TYPE_LONG: - retval = r_PyLong(p); - break; - - case TYPE_FLOAT: - { - char buf[256]; - double dx; - retval = NULL; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - buf[n] = '\0'; - dx = PyOS_string_to_double(buf, NULL, NULL); - if (dx == -1.0 && PyErr_Occurred()) - break; - retval = PyFloat_FromDouble(dx); - break; - } - - case TYPE_BINARY_FLOAT: - { - 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; - } - x = _PyFloat_Unpack8(buf, 1); - if (x == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - retval = PyFloat_FromDouble(x); - break; - } - - case TYPE_COMPLEX: - { - char buf[256]; - Py_complex c; - retval = NULL; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - 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, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - buf[n] = '\0'; - c.imag = PyOS_string_to_double(buf, NULL, NULL); - if (c.imag == -1.0 && PyErr_Occurred()) - break; - retval = PyComplex_FromCComplex(c); - break; - } - - case TYPE_BINARY_COMPLEX: - { - 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; - } - c.real = _PyFloat_Unpack8(buf, 1); - if (c.real == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - } - c.imag = _PyFloat_Unpack8(buf, 1); - if (c.imag == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - retval = PyComplex_FromCComplex(c); - break; - } - - case TYPE_STRING: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); - retval = NULL; - break; - } - v = PyBytes_FromStringAndSize((char *)NULL, n); - if (v == NULL) { - retval = NULL; - break; - } - if (r_string(PyBytes_AS_STRING(v), (int)n, p) != n) { - Py_DECREF(v); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - } - retval = v; - break; - - case TYPE_UNICODE: - { - char *buffer; - - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); - retval = NULL; - break; - } - buffer = PyMem_NEW(char, n); - 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"); - retval = NULL; - break; - } - v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass"); - PyMem_DEL(buffer); - retval = v; - break; - } - - case TYPE_TUPLE: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); - retval = NULL; - break; - } - v = PyTuple_New((int)n); - if (v == NULL) { - retval = NULL; - break; - } - 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 for tuple"); - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SET_ITEM(v, (int)i, v2); - } - retval = v; - break; - - case TYPE_LIST: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); - retval = NULL; - break; - } - v = PyList_New((int)n); - if (v == NULL) { - retval = NULL; - break; - } - 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 for list"); - Py_DECREF(v); - v = NULL; - break; - } - PyList_SET_ITEM(v, (int)i, v2); - } - retval = v; - break; - - case TYPE_DICT: - v = PyDict_New(); - if (v == NULL) { - retval = NULL; - break; - } - for (;;) { - PyObject *key, *val; - key = r_object(p); - if (key == NULL) - 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; - } - retval = v; - break; - - case TYPE_SET: - case TYPE_FROZENSET: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); - retval = NULL; - break; - } - v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL); - if (v == NULL) { - retval = NULL; - break; - } - 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 for set"); - Py_DECREF(v); - v = NULL; - break; - } - if (PySet_Add(v, v2) == -1) { - Py_DECREF(v); - Py_DECREF(v2); - v = NULL; - break; - } - Py_DECREF(v2); - } - retval = v; - break; - - case TYPE_CODE: - { - int argcount; - int kwonlyargcount; - int nlocals; - int stacksize; - int flags; - 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; - PyObject *lnotab = NULL; - - v = NULL; - - /* XXX ignore long->int overflows for now */ - argcount = (int)r_long(p); - kwonlyargcount = (int)r_long(p); - nlocals = (int)r_long(p); - stacksize = (int)r_long(p); - flags = (int)r_long(p); - code = r_object(p); - if (code == NULL) - goto code_error; - consts = r_object(p); - if (consts == NULL) - goto code_error; - names = r_object(p); - if (names == NULL) - goto code_error; - varnames = r_object(p); - if (varnames == NULL) - goto code_error; - freevars = r_object(p); - if (freevars == NULL) - goto code_error; - cellvars = r_object(p); - if (cellvars == NULL) - goto code_error; - filename = r_object(p); - if (filename == NULL) - goto code_error; - name = r_object(p); - if (name == NULL) - goto code_error; - firstlineno = (int)r_long(p); - lnotab = r_object(p); - if (lnotab == NULL) - goto code_error; - - v = (PyObject *) PyCode_New( - argcount, kwonlyargcount, - nlocals, stacksize, flags, - code, consts, names, varnames, - freevars, cellvars, filename, name, - firstlineno, lnotab); - - code_error: - Py_XDECREF(code); - Py_XDECREF(consts); - Py_XDECREF(names); - Py_XDECREF(varnames); - Py_XDECREF(freevars); - Py_XDECREF(cellvars); - Py_XDECREF(filename); - Py_XDECREF(name); - Py_XDECREF(lnotab); - } - 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 (unknown type code)"); - retval = NULL; - break; - - } - p->depth--; - return retval; + /* 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); + 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"); + retval = NULL; + break; + + case TYPE_NULL: + retval = NULL; + break; + + case TYPE_NONE: + Py_INCREF(Py_None); + retval = Py_None; + break; + + case TYPE_STOPITER: + Py_INCREF(PyExc_StopIteration); + retval = PyExc_StopIteration; + break; + + case TYPE_ELLIPSIS: + Py_INCREF(Py_Ellipsis); + retval = Py_Ellipsis; + break; + + case TYPE_FALSE: + Py_INCREF(Py_False); + retval = Py_False; + break; + + case TYPE_TRUE: + Py_INCREF(Py_True); + retval = Py_True; + break; + + case TYPE_INT: + retval = PyLong_FromLong(r_long(p)); + break; + + case TYPE_INT64: + retval = r_long64(p); + break; + + case TYPE_LONG: + retval = r_PyLong(p); + break; + + case TYPE_FLOAT: + { + char buf[256]; + double dx; + retval = NULL; + n = r_byte(p); + if (n == EOF || r_string(buf, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + break; + } + buf[n] = '\0'; + dx = PyOS_string_to_double(buf, NULL, NULL); + if (dx == -1.0 && PyErr_Occurred()) + break; + retval = PyFloat_FromDouble(dx); + break; + } + + case TYPE_BINARY_FLOAT: + { + 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; + } + x = _PyFloat_Unpack8(buf, 1); + if (x == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + retval = PyFloat_FromDouble(x); + break; + } + + case TYPE_COMPLEX: + { + char buf[256]; + Py_complex c; + retval = NULL; + n = r_byte(p); + if (n == EOF || r_string(buf, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + 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, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + break; + } + buf[n] = '\0'; + c.imag = PyOS_string_to_double(buf, NULL, NULL); + if (c.imag == -1.0 && PyErr_Occurred()) + break; + retval = PyComplex_FromCComplex(c); + break; + } + + case TYPE_BINARY_COMPLEX: + { + 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; + } + c.real = _PyFloat_Unpack8(buf, 1); + if (c.real == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + if (r_string((char*)buf, 8, p) != 8) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + } + c.imag = _PyFloat_Unpack8(buf, 1); + if (c.imag == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + retval = PyComplex_FromCComplex(c); + break; + } + + case TYPE_STRING: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); + retval = NULL; + break; + } + v = PyBytes_FromStringAndSize((char *)NULL, n); + if (v == NULL) { + retval = NULL; + break; + } + if (r_string(PyBytes_AS_STRING(v), (int)n, p) != n) { + Py_DECREF(v); + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + } + retval = v; + break; + + case TYPE_UNICODE: + { + char *buffer; + + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); + retval = NULL; + break; + } + buffer = PyMem_NEW(char, n); + 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"); + retval = NULL; + break; + } + v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass"); + PyMem_DEL(buffer); + retval = v; + break; + } + + case TYPE_TUPLE: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); + retval = NULL; + break; + } + v = PyTuple_New((int)n); + if (v == NULL) { + retval = NULL; + break; + } + 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 for tuple"); + Py_DECREF(v); + v = NULL; + break; + } + PyTuple_SET_ITEM(v, (int)i, v2); + } + retval = v; + break; + + case TYPE_LIST: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); + retval = NULL; + break; + } + v = PyList_New((int)n); + if (v == NULL) { + retval = NULL; + break; + } + 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 for list"); + Py_DECREF(v); + v = NULL; + break; + } + PyList_SET_ITEM(v, (int)i, v2); + } + retval = v; + break; + + case TYPE_DICT: + v = PyDict_New(); + if (v == NULL) { + retval = NULL; + break; + } + for (;;) { + PyObject *key, *val; + key = r_object(p); + if (key == NULL) + 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; + } + retval = v; + break; + + case TYPE_SET: + case TYPE_FROZENSET: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); + retval = NULL; + break; + } + v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL); + if (v == NULL) { + retval = NULL; + break; + } + 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 for set"); + Py_DECREF(v); + v = NULL; + break; + } + if (PySet_Add(v, v2) == -1) { + Py_DECREF(v); + Py_DECREF(v2); + v = NULL; + break; + } + Py_DECREF(v2); + } + retval = v; + break; + + case TYPE_CODE: + { + int argcount; + int kwonlyargcount; + int nlocals; + int stacksize; + int flags; + 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; + PyObject *lnotab = NULL; + + v = NULL; + + /* XXX ignore long->int overflows for now */ + argcount = (int)r_long(p); + kwonlyargcount = (int)r_long(p); + nlocals = (int)r_long(p); + stacksize = (int)r_long(p); + flags = (int)r_long(p); + code = r_object(p); + if (code == NULL) + goto code_error; + consts = r_object(p); + if (consts == NULL) + goto code_error; + names = r_object(p); + if (names == NULL) + goto code_error; + varnames = r_object(p); + if (varnames == NULL) + goto code_error; + freevars = r_object(p); + if (freevars == NULL) + goto code_error; + cellvars = r_object(p); + if (cellvars == NULL) + goto code_error; + filename = r_object(p); + if (filename == NULL) + goto code_error; + name = r_object(p); + if (name == NULL) + goto code_error; + firstlineno = (int)r_long(p); + lnotab = r_object(p); + if (lnotab == NULL) + goto code_error; + + v = (PyObject *) PyCode_New( + argcount, kwonlyargcount, + nlocals, stacksize, flags, + code, consts, names, varnames, + freevars, cellvars, filename, name, + firstlineno, lnotab); + + code_error: + Py_XDECREF(code); + Py_XDECREF(consts); + Py_XDECREF(names); + Py_XDECREF(varnames); + Py_XDECREF(freevars); + Py_XDECREF(cellvars); + Py_XDECREF(filename); + Py_XDECREF(name); + Py_XDECREF(lnotab); + } + 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 (unknown type code)"); + retval = NULL; + break; + + } + p->depth--; + return retval; } static 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 for object"); - return v; + 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 for object"); + return v; } int PyMarshal_ReadShortFromFile(FILE *fp) { - RFILE rf; - assert(fp); - rf.fp = fp; - rf.strings = NULL; - rf.end = rf.ptr = NULL; - return r_short(&rf); + RFILE rf; + assert(fp); + rf.fp = fp; + rf.strings = NULL; + rf.end = rf.ptr = NULL; + return r_short(&rf); } long PyMarshal_ReadLongFromFile(FILE *fp) { - RFILE rf; - rf.fp = fp; - rf.strings = NULL; - rf.ptr = rf.end = NULL; - return r_long(&rf); + RFILE rf; + rf.fp = fp; + rf.strings = NULL; + rf.ptr = rf.end = NULL; + return r_long(&rf); } #ifdef HAVE_FSTAT @@ -1061,11 +1061,11 @@ PyMarshal_ReadLongFromFile(FILE *fp) static off_t getfilesize(FILE *fp) { - struct stat st; - if (fstat(fileno(fp), &st) != 0) - return -1; - else - return st.st_size; + struct stat st; + if (fstat(fileno(fp), &st) != 0) + return -1; + else + return st.st_size; } #endif @@ -1081,27 +1081,27 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) /* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. */ #define REASONABLE_FILE_LIMIT (1L << 18) #ifdef HAVE_FSTAT - off_t filesize; - filesize = getfilesize(fp); - if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) { - char* pBuf = (char *)PyMem_MALLOC(filesize); - if (pBuf != NULL) { - PyObject* v; - size_t n; - /* filesize must fit into an int, because it - is smaller than REASONABLE_FILE_LIMIT */ - n = fread(pBuf, 1, (int)filesize, fp); - v = PyMarshal_ReadObjectFromString(pBuf, n); - PyMem_FREE(pBuf); - return v; - } - - } + off_t filesize; + filesize = getfilesize(fp); + if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) { + char* pBuf = (char *)PyMem_MALLOC(filesize); + if (pBuf != NULL) { + PyObject* v; + size_t n; + /* filesize must fit into an int, because it + is smaller than REASONABLE_FILE_LIMIT */ + n = fread(pBuf, 1, (int)filesize, fp); + v = PyMarshal_ReadObjectFromString(pBuf, n); + PyMem_FREE(pBuf); + return v; + } + + } #endif - /* We don't have fstat, or we do but the file is larger than - * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time. - */ - return PyMarshal_ReadObjectFromFile(fp); + /* We don't have fstat, or we do but the file is larger than + * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time. + */ + return PyMarshal_ReadObjectFromFile(fp); #undef REASONABLE_FILE_LIMIT } @@ -1109,77 +1109,77 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) PyObject * PyMarshal_ReadObjectFromFile(FILE *fp) { - RFILE rf; - PyObject *result; - rf.fp = fp; - rf.strings = PyList_New(0); - rf.depth = 0; - rf.ptr = rf.end = NULL; - result = r_object(&rf); - Py_DECREF(rf.strings); - return result; + RFILE rf; + PyObject *result; + rf.fp = fp; + rf.strings = PyList_New(0); + rf.depth = 0; + rf.ptr = rf.end = NULL; + result = r_object(&rf); + Py_DECREF(rf.strings); + return result; } PyObject * PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) { - RFILE rf; - PyObject *result; - rf.fp = NULL; - 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; + RFILE rf; + PyObject *result; + rf.fp = NULL; + 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; } PyObject * PyMarshal_WriteObjectToString(PyObject *x, int version) { - WFILE wf; - PyObject *res = NULL; - - wf.fp = NULL; - wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); - if (wf.str == NULL) - return NULL; - wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str); - wf.end = wf.ptr + PyBytes_Size(wf.str); - wf.error = WFERR_OK; - wf.depth = 0; - wf.version = version; - wf.strings = (version > 0) ? PyDict_New() : NULL; - w_object(x, &wf); - Py_XDECREF(wf.strings); - if (wf.str != NULL) { - char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str); - if (wf.ptr - base > PY_SSIZE_T_MAX) { - Py_DECREF(wf.str); - PyErr_SetString(PyExc_OverflowError, - "too much marshal data for a string"); - return NULL; - } - if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0) - return NULL; - } - if (wf.error != WFERR_OK) { - Py_XDECREF(wf.str); - if (wf.error == WFERR_NOMEMORY) - PyErr_NoMemory(); - else - PyErr_SetString(PyExc_ValueError, - (wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object" - :"object too deeply nested to marshal"); - return NULL; - } - if (wf.str != NULL) { - /* XXX Quick hack -- need to do this differently */ - res = PyBytes_FromObject(wf.str); - Py_DECREF(wf.str); - } - return res; + WFILE wf; + PyObject *res = NULL; + + wf.fp = NULL; + wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); + if (wf.str == NULL) + return NULL; + wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str); + wf.end = wf.ptr + PyBytes_Size(wf.str); + wf.error = WFERR_OK; + wf.depth = 0; + wf.version = version; + wf.strings = (version > 0) ? PyDict_New() : NULL; + w_object(x, &wf); + Py_XDECREF(wf.strings); + if (wf.str != NULL) { + char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str); + if (wf.ptr - base > PY_SSIZE_T_MAX) { + Py_DECREF(wf.str); + PyErr_SetString(PyExc_OverflowError, + "too much marshal data for a string"); + return NULL; + } + if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0) + return NULL; + } + if (wf.error != WFERR_OK) { + Py_XDECREF(wf.str); + if (wf.error == WFERR_NOMEMORY) + PyErr_NoMemory(); + else + PyErr_SetString(PyExc_ValueError, + (wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object" + :"object too deeply nested to marshal"); + return NULL; + } + if (wf.str != NULL) { + /* XXX Quick hack -- need to do this differently */ + res = PyBytes_FromObject(wf.str); + Py_DECREF(wf.str); + } + return res; } /* And an interface for Python programs... */ @@ -1187,20 +1187,20 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) static PyObject * marshal_dump(PyObject *self, PyObject *args) { - /* XXX Quick hack -- need to do this differently */ - PyObject *x; - PyObject *f; - int version = Py_MARSHAL_VERSION; - PyObject *s; - PyObject *res; - if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) - return NULL; - s = PyMarshal_WriteObjectToString(x, version); - if (s == NULL) - return NULL; - res = PyObject_CallMethod(f, "write", "O", s); - Py_DECREF(s); - return res; + /* XXX Quick hack -- need to do this differently */ + PyObject *x; + PyObject *f; + int version = Py_MARSHAL_VERSION; + PyObject *s; + PyObject *res; + if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) + return NULL; + s = PyMarshal_WriteObjectToString(x, version); + if (s == NULL) + return NULL; + res = PyObject_CallMethod(f, "write", "O", s); + Py_DECREF(s); + return res; } PyDoc_STRVAR(dump_doc, @@ -1219,35 +1219,35 @@ The version argument indicates the data format that dump should use."); static PyObject * marshal_load(PyObject *self, PyObject *f) { - /* XXX Quick hack -- need to do this differently */ - PyObject *data, *result; - RFILE rf; - data = PyObject_CallMethod(f, "read", ""); - if (data == NULL) - return NULL; - rf.fp = NULL; - if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else { - PyErr_Format(PyExc_TypeError, - "f.read() returned neither string " - "nor bytes but %.100s", - data->ob_type->tp_name); - Py_DECREF(data); - return NULL; - } - rf.strings = PyList_New(0); - rf.depth = 0; - result = read_object(&rf); - Py_DECREF(rf.strings); - Py_DECREF(data); - return result; + /* XXX Quick hack -- need to do this differently */ + PyObject *data, *result; + RFILE rf; + data = PyObject_CallMethod(f, "read", ""); + if (data == NULL) + return NULL; + rf.fp = NULL; + if (PyBytes_Check(data)) { + rf.ptr = PyBytes_AS_STRING(data); + rf.end = rf.ptr + PyBytes_GET_SIZE(data); + } + else if (PyBytes_Check(data)) { + rf.ptr = PyBytes_AS_STRING(data); + rf.end = rf.ptr + PyBytes_GET_SIZE(data); + } + else { + PyErr_Format(PyExc_TypeError, + "f.read() returned neither string " + "nor bytes but %.100s", + data->ob_type->tp_name); + Py_DECREF(data); + return NULL; + } + rf.strings = PyList_New(0); + rf.depth = 0; + result = read_object(&rf); + Py_DECREF(rf.strings); + Py_DECREF(data); + return result; } PyDoc_STRVAR(load_doc, @@ -1266,11 +1266,11 @@ dump(), load() will substitute None for the unmarshallable type."); static PyObject * marshal_dumps(PyObject *self, PyObject *args) { - PyObject *x; - int version = Py_MARSHAL_VERSION; - if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) - return NULL; - return PyMarshal_WriteObjectToString(x, version); + PyObject *x; + int version = Py_MARSHAL_VERSION; + if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) + return NULL; + return PyMarshal_WriteObjectToString(x, version); } PyDoc_STRVAR(dumps_doc, @@ -1286,24 +1286,24 @@ The version argument indicates the data format that dumps should use."); static PyObject * marshal_loads(PyObject *self, PyObject *args) { - RFILE rf; - Py_buffer p; - char *s; - Py_ssize_t n; - PyObject* result; - if (!PyArg_ParseTuple(args, "s*:loads", &p)) - return NULL; - s = p.buf; - n = p.len; - rf.fp = NULL; - rf.ptr = s; - rf.end = s + n; - rf.strings = PyList_New(0); - rf.depth = 0; - result = read_object(&rf); - Py_DECREF(rf.strings); - PyBuffer_Release(&p); - return result; + RFILE rf; + Py_buffer p; + char *s; + Py_ssize_t n; + PyObject* result; + if (!PyArg_ParseTuple(args, "s*:loads", &p)) + return NULL; + s = p.buf; + n = p.len; + rf.fp = NULL; + rf.ptr = s; + rf.end = s + n; + rf.strings = PyList_New(0); + rf.depth = 0; + result = read_object(&rf); + Py_DECREF(rf.strings); + PyBuffer_Release(&p); + return result; } PyDoc_STRVAR(loads_doc, @@ -1314,11 +1314,11 @@ EOFError, ValueError or TypeError. Extra characters in the string are\n\ ignored."); static PyMethodDef marshal_methods[] = { - {"dump", marshal_dump, METH_VARARGS, dump_doc}, - {"load", marshal_load, METH_O, load_doc}, - {"dumps", marshal_dumps, METH_VARARGS, dumps_doc}, - {"loads", marshal_loads, METH_VARARGS, loads_doc}, - {NULL, NULL} /* sentinel */ + {"dump", marshal_dump, METH_VARARGS, dump_doc}, + {"load", marshal_load, METH_O, load_doc}, + {"dumps", marshal_dumps, METH_VARARGS, dumps_doc}, + {"loads", marshal_loads, METH_VARARGS, loads_doc}, + {NULL, NULL} /* sentinel */ }; @@ -1353,23 +1353,23 @@ loads() -- read value from a string"); static struct PyModuleDef marshalmodule = { - PyModuleDef_HEAD_INIT, - "marshal", - module_doc, - 0, - marshal_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "marshal", + module_doc, + 0, + marshal_methods, + NULL, + NULL, + NULL, + NULL }; PyMODINIT_FUNC PyMarshal_Init(void) { - PyObject *mod = PyModule_Create(&marshalmodule); - if (mod == NULL) - return NULL; - PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION); - return mod; + PyObject *mod = PyModule_Create(&marshalmodule); + if (mod == NULL) + return NULL; + PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION); + return mod; } |