diff options
Diffstat (limited to 'Python/marshal.c')
-rw-r--r-- | Python/marshal.c | 136 |
1 files changed, 67 insertions, 69 deletions
diff --git a/Python/marshal.c b/Python/marshal.c index 1edb696fd9..cc17329913 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -31,6 +31,9 @@ #define TYPE_STOPITER 'S' #define TYPE_ELLIPSIS '.' #define TYPE_INT 'i' +/* TYPE_INT64 is deprecated. It is not + generated anymore, and support for reading it + will be removed in Python 3.4. */ #define TYPE_INT64 'I' #define TYPE_FLOAT 'f' #define TYPE_BINARY_FLOAT 'g' @@ -59,9 +62,9 @@ typedef struct { /* If fp == NULL, the following are valid: */ PyObject *readable; /* Stream-like object being read from */ PyObject *str; + PyObject *current_filename; char *ptr; char *end; - PyObject *strings; /* dict on marshal, list on unmarshal */ int version; } WFILE; @@ -92,7 +95,7 @@ w_more(int c, WFILE *p) } static void -w_string(char *s, Py_ssize_t n, WFILE *p) +w_string(const char *s, Py_ssize_t n, WFILE *p) { if (p->fp != NULL) { fwrite(s, 1, n, p->fp); @@ -121,15 +124,6 @@ w_long(long x, WFILE *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); -} -#endif - #define SIZE32_MAX 0x7FFFFFFF #if SIZEOF_SIZE_T > 4 @@ -145,7 +139,14 @@ w_long64(long x, WFILE *p) # define W_SIZE w_long #endif -/* We assume that Python longs are stored internally in base some power of +static void +w_pstring(const char *s, Py_ssize_t n, WFILE *p) +{ + W_SIZE(n, p); + w_string(s, n, p); +} + +/* We assume that Python ints are stored internally in base some power of 2**15; for the sake of portability we'll always read and write them in base exactly 2**15. */ @@ -239,8 +240,8 @@ w_object(PyObject *v, WFILE *p) #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); + /* Too large for TYPE_INT */ + w_PyLong((PyLongObject*)v, p); } else #endif @@ -319,24 +320,18 @@ w_object(PyObject *v, WFILE *p) } else if (PyBytes_CheckExact(v)) { w_byte(TYPE_STRING, p); - n = PyBytes_GET_SIZE(v); - W_SIZE(n, p); - w_string(PyBytes_AS_STRING(v), n, p); + w_pstring(PyBytes_AS_STRING(v), PyBytes_GET_SIZE(v), p); } else if (PyUnicode_CheckExact(v)) { PyObject *utf8; - utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - "surrogatepass"); + utf8 = PyUnicode_AsEncodedString(v, "utf8", "surrogatepass"); if (utf8 == NULL) { p->depth--; p->error = WFERR_UNMARSHALLABLE; return; } w_byte(TYPE_UNICODE, p); - n = PyBytes_GET_SIZE(utf8); - W_SIZE(n, p); - w_string(PyBytes_AS_STRING(utf8), n, p); + w_pstring(PyBytes_AS_STRING(utf8), PyBytes_GET_SIZE(utf8), p); Py_DECREF(utf8); } else if (PyTuple_CheckExact(v)) { @@ -419,7 +414,6 @@ w_object(PyObject *v, WFILE *p) } else if (PyObject_CheckBuffer(v)) { /* Write unknown buffer-style objects as a string */ - char *s; Py_buffer view; if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) { w_byte(TYPE_UNKNOWN, p); @@ -428,10 +422,7 @@ w_object(PyObject *v, WFILE *p) return; } w_byte(TYPE_STRING, p); - n = view.len; - s = view.buf; - W_SIZE(n, p); - w_string(s, n, p); + w_pstring(view.buf, view.len, p); PyBuffer_Release(&view); } else { @@ -441,7 +432,7 @@ w_object(PyObject *v, WFILE *p) p->depth--; } -/* version currently has no effect for writing longs. */ +/* version currently has no effect for writing ints. */ void PyMarshal_WriteLongToFile(long x, FILE *fp, int version) { @@ -449,7 +440,6 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version) wf.fp = fp; wf.error = WFERR_OK; wf.depth = 0; - wf.strings = NULL; wf.version = version; w_long(x, &wf); } @@ -461,10 +451,8 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) 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 */ @@ -489,7 +477,9 @@ r_string(char *s, Py_ssize_t n, RFILE *p) } } else { - PyObject *data = PyObject_CallMethod(p->readable, "read", "n", n); + _Py_IDENTIFIER(read); + + PyObject *data = _PyObject_CallMethodId(p->readable, &PyId_read, "n", n); read = 0; if (data != NULL) { if (!PyBytes_Check(data)) { @@ -500,8 +490,17 @@ r_string(char *s, Py_ssize_t n, RFILE *p) else { read = 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); @@ -743,11 +742,13 @@ r_object(RFILE *p) 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()) @@ -761,8 +762,6 @@ r_object(RFILE *p) 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; } @@ -781,21 +780,25 @@ r_object(RFILE *p) 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()) @@ -809,8 +812,6 @@ r_object(RFILE *p) 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; } @@ -820,8 +821,6 @@ r_object(RFILE *p) break; } if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); retval = NULL; break; } @@ -852,8 +851,6 @@ r_object(RFILE *p) } 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; } @@ -881,8 +878,6 @@ r_object(RFILE *p) } if (r_string(buffer, n, p) != n) { PyMem_DEL(buffer); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); retval = NULL; break; } @@ -1073,6 +1068,18 @@ r_object(RFILE *p) filename = r_object(p); if (filename == NULL) goto code_error; + if (PyUnicode_CheckExact(filename)) { + if (p->current_filename != NULL) { + if (!PyUnicode_Compare(filename, p->current_filename)) { + Py_DECREF(filename); + Py_INCREF(p->current_filename); + filename = p->current_filename; + } + } + else { + p->current_filename = filename; + } + } name = r_object(p); if (name == NULL) goto code_error; @@ -1135,7 +1142,7 @@ PyMarshal_ReadShortFromFile(FILE *fp) assert(fp); rf.readable = NULL; rf.fp = fp; - rf.strings = NULL; + rf.current_filename = NULL; rf.end = rf.ptr = NULL; return r_short(&rf); } @@ -1146,7 +1153,7 @@ PyMarshal_ReadLongFromFile(FILE *fp) RFILE rf; rf.fp = fp; rf.readable = NULL; - rf.strings = NULL; + rf.current_filename = NULL; rf.ptr = rf.end = NULL; return r_long(&rf); } @@ -1204,11 +1211,10 @@ PyMarshal_ReadObjectFromFile(FILE *fp) PyObject *result; rf.fp = fp; rf.readable = NULL; - rf.strings = PyList_New(0); + rf.current_filename = NULL; rf.depth = 0; rf.ptr = rf.end = NULL; result = r_object(&rf); - Py_DECREF(rf.strings); return result; } @@ -1219,12 +1225,11 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) PyObject *result; rf.fp = NULL; rf.readable = NULL; + rf.current_filename = 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; } @@ -1232,7 +1237,6 @@ PyObject * PyMarshal_WriteObjectToString(PyObject *x, int version) { WFILE wf; - PyObject *res = NULL; wf.fp = NULL; wf.readable = NULL; @@ -1244,9 +1248,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) 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) { @@ -1268,12 +1270,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) :"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; + return wf.str; } /* And an interface for Python programs... */ @@ -1287,12 +1284,14 @@ marshal_dump(PyObject *self, PyObject *args) int version = Py_MARSHAL_VERSION; PyObject *s; PyObject *res; + _Py_IDENTIFIER(write); + 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); + res = _PyObject_CallMethodId(f, &PyId_write, "O", s); Py_DECREF(s); return res; } @@ -1314,6 +1313,7 @@ static PyObject * marshal_load(PyObject *self, PyObject *f) { PyObject *data, *result; + _Py_IDENTIFIER(read); RFILE rf; /* @@ -1321,7 +1321,7 @@ marshal_load(PyObject *self, PyObject *f) * This is to ensure that the object passed in at least * has a read method which returns bytes. */ - data = PyObject_CallMethod(f, "read", "i", 0); + data = _PyObject_CallMethodId(f, &PyId_read, "i", 0); if (data == NULL) return NULL; if (!PyBytes_Check(data)) { @@ -1331,12 +1331,11 @@ marshal_load(PyObject *self, PyObject *f) result = NULL; } else { - rf.strings = PyList_New(0); rf.depth = 0; rf.fp = NULL; rf.readable = f; + rf.current_filename = NULL; result = read_object(&rf); - Py_DECREF(rf.strings); } Py_DECREF(data); return result; @@ -1389,12 +1388,11 @@ marshal_loads(PyObject *self, PyObject *args) n = p.len; rf.fp = NULL; rf.readable = NULL; + rf.current_filename = 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; } |