summaryrefslogtreecommitdiff
path: root/Python/marshal.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/marshal.c')
-rw-r--r--Python/marshal.c136
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;
}