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:
parent
09ac1fde1c
commit
d9b9ac855c
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue