It's unclear whether PyMarshal_XXX() are part of the public or private API.

They're named as if public, so I did a Bad Thing by changing
PyMarshal_ReadObjectFromFile() to suck up the remainder of the file in one
gulp:  anyone who counted on that leaving the file pointer merely at the
end of the next object would be screwed.  So restored
PyMarshal_ReadObjectFromFile() to its earlier state, renamed the new greedy
code to PyMarshal_ReadLastObjectFromFile(), and changed Python internals to
call the latter instead.
This commit is contained in:
Tim Peters 2001-01-28 00:27:39 +00:00
parent 09ac1fde1c
commit d9b9ac855c
4 changed files with 52 additions and 35 deletions

View File

@ -15,6 +15,7 @@ DL_IMPORT(PyObject *) PyMarshal_WriteObjectToString(PyObject *);
DL_IMPORT(long) PyMarshal_ReadLongFromFile(FILE *); DL_IMPORT(long) PyMarshal_ReadLongFromFile(FILE *);
DL_IMPORT(int) PyMarshal_ReadShortFromFile(FILE *); DL_IMPORT(int) PyMarshal_ReadShortFromFile(FILE *);
DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromFile(FILE *); DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromFile(FILE *);
DL_IMPORT(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *);
DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromString(char *, int); DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromString(char *, int);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -555,7 +555,7 @@ read_compiled_module(char *cpathname, FILE *fp)
{ {
PyObject *co; PyObject *co;
co = PyMarshal_ReadObjectFromFile(fp); co = PyMarshal_ReadLastObjectFromFile(fp);
/* Ugly: rd_object() may return NULL with or without error */ /* Ugly: rd_object() may return NULL with or without error */
if (co == NULL || !PyCode_Check(co)) { if (co == NULL || !PyCode_Check(co)) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())

View File

@ -110,10 +110,10 @@ w_object(PyObject *v, WFILE *p)
PyBufferProcs *pb; PyBufferProcs *pb;
p->depth++; p->depth++;
if (p->depth > MAX_MARSHAL_STACK_DEPTH) { if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
p->error = 2; p->error = 2;
} }
else if (v == NULL) { else if (v == NULL) {
w_byte(TYPE_NULL, p); w_byte(TYPE_NULL, p);
} }
@ -363,31 +363,31 @@ r_object(RFILE *p)
PyObject *v, *v2; PyObject *v, *v2;
long i, n; long i, n;
int type = r_byte(p); int type = r_byte(p);
switch (type) { switch (type) {
case EOF: case EOF:
PyErr_SetString(PyExc_EOFError, PyErr_SetString(PyExc_EOFError,
"EOF read where object expected"); "EOF read where object expected");
return NULL; return NULL;
case TYPE_NULL: case TYPE_NULL:
return NULL; return NULL;
case TYPE_NONE: case TYPE_NONE:
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
case TYPE_ELLIPSIS: case TYPE_ELLIPSIS:
Py_INCREF(Py_Ellipsis); Py_INCREF(Py_Ellipsis);
return Py_Ellipsis; return Py_Ellipsis;
case TYPE_INT: case TYPE_INT:
return PyInt_FromLong(r_long(p)); return PyInt_FromLong(r_long(p));
case TYPE_INT64: case TYPE_INT64:
return PyInt_FromLong(r_long64(p)); return PyInt_FromLong(r_long64(p));
case TYPE_LONG: case TYPE_LONG:
{ {
int size; int size;
@ -402,7 +402,7 @@ r_object(RFILE *p)
ob->ob_digit[i] = r_short(p); ob->ob_digit[i] = r_short(p);
return (PyObject *)ob; return (PyObject *)ob;
} }
case TYPE_FLOAT: case TYPE_FLOAT:
{ {
char buf[256]; char buf[256];
@ -419,7 +419,7 @@ r_object(RFILE *p)
PyFPE_END_PROTECT(dx) PyFPE_END_PROTECT(dx)
return PyFloat_FromDouble(dx); return PyFloat_FromDouble(dx);
} }
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
case TYPE_COMPLEX: case TYPE_COMPLEX:
{ {
@ -448,7 +448,7 @@ r_object(RFILE *p)
return PyComplex_FromCComplex(c); return PyComplex_FromCComplex(c);
} }
#endif #endif
case TYPE_STRING: case TYPE_STRING:
n = r_long(p); n = r_long(p);
if (n < 0) { if (n < 0) {
@ -465,7 +465,7 @@ r_object(RFILE *p)
} }
} }
return v; return v;
case TYPE_UNICODE: case TYPE_UNICODE:
{ {
char *buffer; char *buffer;
@ -488,7 +488,7 @@ r_object(RFILE *p)
PyMem_DEL(buffer); PyMem_DEL(buffer);
return v; return v;
} }
case TYPE_TUPLE: case TYPE_TUPLE:
n = r_long(p); n = r_long(p);
if (n < 0) { if (n < 0) {
@ -508,7 +508,7 @@ r_object(RFILE *p)
PyTuple_SET_ITEM(v, (int)i, v2); PyTuple_SET_ITEM(v, (int)i, v2);
} }
return v; return v;
case TYPE_LIST: case TYPE_LIST:
n = r_long(p); n = r_long(p);
if (n < 0) { if (n < 0) {
@ -528,7 +528,7 @@ r_object(RFILE *p)
PyList_SetItem(v, (int)i, v2); PyList_SetItem(v, (int)i, v2);
} }
return v; return v;
case TYPE_DICT: case TYPE_DICT:
v = PyDict_New(); v = PyDict_New();
if (v == NULL) if (v == NULL)
@ -545,7 +545,7 @@ r_object(RFILE *p)
Py_XDECREF(val); Py_XDECREF(val);
} }
return v; return v;
case TYPE_CODE: case TYPE_CODE:
{ {
int argcount = r_short(p); int argcount = r_short(p);
@ -562,7 +562,7 @@ r_object(RFILE *p)
PyObject *name = NULL; PyObject *name = NULL;
int firstlineno = 0; int firstlineno = 0;
PyObject *lnotab = NULL; PyObject *lnotab = NULL;
code = r_object(p); code = r_object(p);
if (code) consts = r_object(p); if (code) consts = r_object(p);
if (consts) names = r_object(p); if (consts) names = r_object(p);
@ -575,13 +575,13 @@ r_object(RFILE *p)
firstlineno = r_short(p); firstlineno = r_short(p);
lnotab = r_object(p); lnotab = r_object(p);
} }
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
v = (PyObject *) PyCode_New( v = (PyObject *) PyCode_New(
argcount, nlocals, stacksize, flags, argcount, nlocals, stacksize, flags,
code, consts, names, varnames, code, consts, names, varnames,
freevars, cellvars, filename, name, freevars, cellvars, filename, name,
firstlineno, lnotab); firstlineno, lnotab);
} }
else else
v = NULL; v = NULL;
@ -597,13 +597,13 @@ r_object(RFILE *p)
} }
return v; return v;
default: default:
/* Bogus data got written, which isn't ideal. /* Bogus data got written, which isn't ideal.
This will let you keep working and recover. */ This will let you keep working and recover. */
PyErr_SetString(PyExc_ValueError, "bad marshal data"); PyErr_SetString(PyExc_ValueError, "bad marshal data");
return NULL; return NULL;
} }
} }
@ -627,20 +627,21 @@ getfilesize(FILE *fp)
return st.st_size; return st.st_size;
} }
#endif #endif
/* If we can get the size of the file up-front, and it's reasonably small, /* If we can get the size of the file up-front, and it's reasonably small,
* read it in one gulp and delegate to ...FromString() instead. Much quicker * read it in one gulp and delegate to ...FromString() instead. Much quicker
* than reading a byte at a time from file; speeds .pyc imports. * than reading a byte at a time from file; speeds .pyc imports.
* CAUTION: since this may read the entire remainder of the file, don't
* call it unless you know you're done with the file.
*/ */
PyObject * PyObject *
PyMarshal_ReadObjectFromFile(FILE *fp) PyMarshal_ReadLastObjectFromFile(FILE *fp)
{ {
/* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT. /* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT.
* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. * REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc.
*/ */
#define SMALL_FILE_LIMIT (1L << 14) #define SMALL_FILE_LIMIT (1L << 14)
#define REASONABLE_FILE_LIMIT (1L << 18) #define REASONABLE_FILE_LIMIT (1L << 18)
RFILE rf;
#ifdef HAVE_FSTAT #ifdef HAVE_FSTAT
off_t filesize; off_t filesize;
#endif #endif
@ -665,15 +666,30 @@ PyMarshal_ReadObjectFromFile(FILE *fp)
PyMem_FREE(pBuf); PyMem_FREE(pBuf);
return v; return v;
} }
} }
#endif #endif
rf.fp = fp; /* We don't have fstat, or we do but the file is larger than
return r_object(&rf); * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time.
*/
return PyMarshal_ReadObjectFromFile(fp);
#undef SMALL_FILE_LIMIT #undef SMALL_FILE_LIMIT
#undef REASONABLE_FILE_LIMIT #undef REASONABLE_FILE_LIMIT
} }
PyObject *
PyMarshal_ReadObjectFromFile(FILE *fp)
{
RFILE rf;
if (PyErr_Occurred()) {
fprintf(stderr, "XXX rd_object called with exception set\n");
return NULL;
}
rf.fp = fp;
return r_object(&rf);
}
PyObject * PyObject *
PyMarshal_ReadObjectFromString(char *str, int len) PyMarshal_ReadObjectFromString(char *str, int len)
{ {
@ -708,7 +724,7 @@ PyMarshal_WriteObjectToString(PyObject *x) /* wrs_object() */
PyString_AS_STRING((PyStringObject *)wf.str))); PyString_AS_STRING((PyStringObject *)wf.str)));
if (wf.error) { if (wf.error) {
Py_XDECREF(wf.str); Py_XDECREF(wf.str);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
(wf.error==1)?"unmarshallable object" (wf.error==1)?"unmarshallable object"
:"object too deeply nested to marshal"); :"object too deeply nested to marshal");
return NULL; return NULL;
@ -738,7 +754,7 @@ marshal_dump(PyObject *self, PyObject *args)
wf.depth = 0; wf.depth = 0;
w_object(x, &wf); w_object(x, &wf);
if (wf.error) { if (wf.error) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
(wf.error==1)?"unmarshallable object" (wf.error==1)?"unmarshallable object"
:"object too deeply nested to marshal"); :"object too deeply nested to marshal");
return NULL; return NULL;

View File

@ -936,7 +936,7 @@ run_pyc_file(FILE *fp, char *filename, PyObject *globals, PyObject *locals)
return NULL; return NULL;
} }
(void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp);
v = PyMarshal_ReadObjectFromFile(fp); v = PyMarshal_ReadLastObjectFromFile(fp);
fclose(fp); fclose(fp);
if (v == NULL || !PyCode_Check(v)) { if (v == NULL || !PyCode_Check(v)) {
Py_XDECREF(v); Py_XDECREF(v);