/* Write Python objects to files and read them back.This is intended for writing and reading compiled Python code only;a true persistent storage facility would be much harder, sinceit would have to take circular links and sharing into account. */#define PY_SSIZE_T_CLEAN#include "Python.h"#include "longintrepr.h"#include "code.h"#include "marshal.h"/* High water mark to determine when the marshalled object is dangerously deep* and risks coring the interpreter. When the object stack gets this deep,* raise an exception instead of continuing.*/#define MAX_MARSHAL_STACK_DEPTH 2000#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_INTERNED 't'#define TYPE_STRINGREF 'R'#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 '>'typedef struct {FILE *fp;int error;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)static voidw_more(int c, WFILE *p){Py_ssize_t size, newsize;if (p->str == NULL)return; /* An error already occurred */size = PyString_Size(p->str);newsize = size + size + 1024;if (newsize > 32*1024*1024) {newsize = size + (size >> 3); /* 12.5% overallocation */}if (_PyString_Resize(&p->str, newsize) != 0) {p->ptr = p->end = NULL;}else {p->ptr = PyString_AS_STRING((PyStringObject *)p->str) + size;p->end =PyString_AS_STRING((PyStringObject *)p->str) + newsize;*p->ptr++ = Py_SAFE_DOWNCAST(c, int, char);}}static voidw_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++;}}}static voidw_short(int x, WFILE *p){w_byte((char)( x & 0xff), p);w_byte((char)((x>> 8) & 0xff), p);}static voidw_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);}#if SIZEOF_LONG > 4static voidw_long64(long x, WFILE *p){w_long(x, p);w_long(x>>32, p);}#endifstatic voidw_object(PyObject *v, WFILE *p){Py_ssize_t i, n;p->depth++;if (p->depth > MAX_MARSHAL_STACK_DEPTH) {p->error = 2;}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 (PyInt_CheckExact(v)) {long x = PyInt_AS_LONG((PyIntObject *)v);#if SIZEOF_LONG > 4long 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 (PyLong_CheckExact(v)) {PyLongObject *ob = (PyLongObject *)v;w_byte(TYPE_LONG, p);n = ob->ob_size;w_long((long)n, p);if (n < 0)n = -n;for (i = 0; i < n; i++)w_short(ob->ob_digit[i], 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 = 1;return;}w_byte(TYPE_BINARY_FLOAT, p);w_string((char*)buf, 8, p);}else {char buf[256]; /* Plenty to format any double */PyFloat_AsReprString(buf, (PyFloatObject *)v);n = strlen(buf);w_byte(TYPE_FLOAT, p);w_byte((int)n, p);w_string(buf, (int)n, p);}}#ifndef WITHOUT_COMPLEXelse if (PyComplex_CheckExact(v)) {if (p->version > 1) {unsigned char buf[8];if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),buf, 1) < 0) {p->error = 1;return;}w_byte(TYPE_BINARY_COMPLEX, p);w_string((char*)buf, 8, p);if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v),buf, 1) < 0) {p->error = 1;return;}w_string((char*)buf, 8, p);}else {char buf[256]; /* Plenty to format any double */PyFloatObject *temp;w_byte(TYPE_COMPLEX, p);temp = (PyFloatObject*)PyFloat_FromDouble(PyComplex_RealAsDouble(v));if (!temp) {p->error = 1;return;}PyFloat_AsReprString(buf, temp);Py_DECREF(temp);n = strlen(buf);w_byte((int)n, p);w_string(buf, (int)n, p);temp = (PyFloatObject*)PyFloat_FromDouble(PyComplex_ImagAsDouble(v));if (!temp) {p->error = 1;return;}PyFloat_AsReprString(buf, temp);Py_DECREF(temp);n = strlen(buf);w_byte((int)n, p);w_string(buf, (int)n, p);}}#endifelse if (PyString_CheckExact(v)) {if (p->strings && PyString_CHECK_INTERNED(v)) {PyObject *o = PyDict_GetItem(p->strings, v);if (o) {long w = PyInt_AsLong(o);w_byte(TYPE_STRINGREF, p);w_long(w, p);goto exit;}else {int ok;o = PyInt_FromSsize_t(PyDict_Size(p->strings));ok = o &&PyDict_SetItem(p->strings, v, o) >= 0;Py_XDECREF(o);if (!ok) {p->depth--;p->error = 1;return;}w_byte(TYPE_INTERNED, p);}}else {w_byte(TYPE_STRING, p);}n = PyString_GET_SIZE(v);if (n > INT_MAX) {/* huge strings are not supported */p->depth--;p->error = 1;return;}w_long((long)n, p);w_string(PyString_AS_STRING(v), (int)n, p);}#ifdef Py_USING_UNICODEelse if (PyUnicode_CheckExact(v)) {PyObject *utf8;utf8 = PyUnicode_AsUTF8String(v);if (utf8 == NULL) {p->depth--;p->error = 1;return;}w_byte(TYPE_UNICODE, p);n = PyString_GET_SIZE(utf8);if (n > INT_MAX) {p->depth--;p->error = 1;return;}w_long((long)n, p);w_string(PyString_AS_STRING(utf8), (int)n, p);Py_DECREF(utf8);}#endifelse 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);elsew_byte(TYPE_FROZENSET, p);n = PyObject_Size(v);if (n == -1) {p->depth--;p->error = 1;return;}w_long((long)n, p);it = PyObject_GetIter(v);if (it == NULL) {p->depth--;p->error = 1;return;}while ((value = PyIter_Next(it)) != NULL) {w_object(value, p);Py_DECREF(value);}Py_DECREF(it);if (PyErr_Occurred()) {p->depth--;p->error = 1;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_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_CheckReadBuffer(v)) {/* Write unknown buffer-style objects as a string */char *s;PyBufferProcs *pb = v->ob_type->tp_as_buffer;w_byte(TYPE_STRING, p);n = (*pb->bf_getreadbuffer)(v, 0, (void **)&s);if (n > INT_MAX) {p->depth--;p->error = 1;return;}w_long((long)n, p);w_string(s, (int)n, p);}else {w_byte(TYPE_UNKNOWN, p);p->error = 1;}exit:p->depth--;}/* version currently has no effect for writing longs. */voidPyMarshal_WriteLongToFile(long x, FILE *fp, int version){WFILE wf;wf.fp = fp;wf.error = 0;wf.depth = 0;wf.strings = NULL;wf.version = version;w_long(x, &wf);}voidPyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version){WFILE wf;wf.fp = fp;wf.error = 0;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 */#define rs_byte(p) (((p)->ptr < (p)->end) ? (unsigned char)*(p)->ptr++ : EOF)#define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p))static intr_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;}static intr_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;}static longr_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;}#if SIZEOF_LONG > 4/* Sign extension for 64-bit machines */x |= -(x & 0x80000000L);#endifreturn x;}/* r_long64 deals with the TYPE_INT64 code. On a machine withsizeof(long) > 4, it returns a Python int object, else a Python longobject. Note that w_long64 writes out TYPE_INT if 32 bits is enough,so there's no inefficiency here in returning a PyLong on 32-bit boxesfor everything written via TYPE_INT64 (i.e., if an int is written viaTYPE_INT64, it *needs* more than 32 bits).*/static PyObject *r_long64(RFILE *p){long lo4 = r_long(p);long hi4 = r_long(p);#if SIZEOF_LONG > 4long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL);return PyInt_FromLong(x);#elseunsigned 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_object(RFILE *p){/* NULL is a valid return value, it does not necessarily means thatan 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 = PyInt_FromLong(r_long(p));break;case TYPE_INT64:retval = r_long64(p);break;case TYPE_LONG:{int size;PyLongObject *ob;n = r_long(p);if (n < -INT_MAX || n > INT_MAX) {PyErr_SetString(PyExc_ValueError,"bad marshal data");retval = NULL;break;}size = n<0 ? -n : n;ob = _PyLong_New(size);if (ob == NULL) {retval = NULL;break;}ob->ob_size = n;for (i = 0; i < size; i++) {int digit = r_short(p);if (digit < 0) {Py_DECREF(ob);PyErr_SetString(PyExc_ValueError,"bad marshal data");ob = NULL;break;}if (ob != NULL)ob->ob_digit[i] = digit;}retval = (PyObject *)ob;break;}case TYPE_FLOAT:{char buf[256];double dx;n = r_byte(p);if (n == EOF || r_string(buf, (int)n, p) != n) {PyErr_SetString(PyExc_EOFError,"EOF read where object expected");retval = NULL;break;}buf[n] = '0円';retval = NULL;PyFPE_START_PROTECT("atof", break)dx = PyOS_ascii_atof(buf);PyFPE_END_PROTECT(dx)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;}#ifndef WITHOUT_COMPLEXcase TYPE_COMPLEX:{char buf[256];Py_complex c;n = r_byte(p);if (n == EOF || r_string(buf, (int)n, p) != n) {PyErr_SetString(PyExc_EOFError,"EOF read where object expected");retval = NULL;break;}buf[n] = '0円';retval = NULL;PyFPE_START_PROTECT("atof", break;)c.real = PyOS_ascii_atof(buf);PyFPE_END_PROTECT(c)n = r_byte(p);if (n == EOF || r_string(buf, (int)n, p) != n) {PyErr_SetString(PyExc_EOFError,"EOF read where object expected");retval = NULL;break;}buf[n] = '0円';PyFPE_START_PROTECT("atof", break)c.imag = PyOS_ascii_atof(buf);PyFPE_END_PROTECT(c)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;}#endifcase TYPE_INTERNED:case TYPE_STRING:n = r_long(p);if (n < 0 || n > INT_MAX) {PyErr_SetString(PyExc_ValueError, "bad marshal data");retval = NULL;break;}v = PyString_FromStringAndSize((char *)NULL, n);if (v == NULL) {retval = NULL;break;}if (r_string(PyString_AS_STRING(v), (int)n, p) != n) {Py_DECREF(v);PyErr_SetString(PyExc_EOFError,"EOF read where object expected");retval = NULL;break;}if (type == TYPE_INTERNED) {PyString_InternInPlace(&v);if (PyList_Append(p->strings, v) < 0) {retval = NULL;break;}}retval = v;break;case TYPE_STRINGREF:n = r_long(p);if (n < 0 || n >= PyList_GET_SIZE(p->strings)) {PyErr_SetString(PyExc_ValueError, "bad marshal data");retval = NULL;break;}v = PyList_GET_ITEM(p->strings, n);Py_INCREF(v);retval = v;break;#ifdef Py_USING_UNICODEcase TYPE_UNICODE:{char *buffer;n = r_long(p);if (n < 0 || n > INT_MAX) {PyErr_SetString(PyExc_ValueError, "bad marshal data");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, NULL);PyMem_DEL(buffer);retval = v;break;}#endifcase TYPE_TUPLE:n = r_long(p);if (n < 0 || n > INT_MAX) {PyErr_SetString(PyExc_ValueError, "bad marshal data");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");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");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");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");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");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:if (PyEval_GetRestricted()) {PyErr_SetString(PyExc_RuntimeError,"cannot unmarshal code objects in ""restricted execution mode");retval = NULL;break;}else {int argcount;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);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, 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");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");return v;}intPyMarshal_ReadShortFromFile(FILE *fp){RFILE rf;assert(fp);rf.fp = fp;rf.strings = NULL;rf.end = rf.ptr = NULL;return r_short(&rf);}longPyMarshal_ReadLongFromFile(FILE *fp){RFILE rf;rf.fp = fp;rf.strings = NULL;rf.ptr = rf.end = NULL;return r_long(&rf);}#ifdef HAVE_FSTAT/* Return size of file in bytes; < 0 if unknown. */static off_tgetfilesize(FILE *fp){struct stat st;if (fstat(fileno(fp), &st) != 0)return -1;elsereturn st.st_size;}#endif/* 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* 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 *PyMarshal_ReadLastObjectFromFile(FILE *fp){/* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT.* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc.*/#define SMALL_FILE_LIMIT (1L << 14)#define REASONABLE_FILE_LIMIT (1L << 18)#ifdef HAVE_FSTAToff_t filesize;#endif#ifdef HAVE_FSTATfilesize = getfilesize(fp);if (filesize > 0) {char buf[SMALL_FILE_LIMIT];char* pBuf = NULL;if (filesize <= SMALL_FILE_LIMIT)pBuf = buf;else if (filesize <= REASONABLE_FILE_LIMIT)pBuf = (char *)PyMem_MALLOC(filesize);if (pBuf != NULL) {PyObject* v;size_t n;/* filesize must fit into an int, because itis smaller than REASONABLE_FILE_LIMIT */n = fread(pBuf, 1, (int)filesize, fp);v = PyMarshal_ReadObjectFromString(pBuf, n);if (pBuf != buf)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);#undef SMALL_FILE_LIMIT#undef REASONABLE_FILE_LIMIT}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;}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;}PyObject *PyMarshal_WriteObjectToString(PyObject *x, int version){WFILE wf;wf.fp = NULL;wf.str = PyString_FromStringAndSize((char *)NULL, 50);if (wf.str == NULL)return NULL;wf.ptr = PyString_AS_STRING((PyStringObject *)wf.str);wf.end = wf.ptr + PyString_Size(wf.str);wf.error = 0;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 = PyString_AS_STRING((PyStringObject *)wf.str);if (wf.ptr - base > PY_SSIZE_T_MAX) {Py_DECREF(wf.str);PyErr_SetString(PyExc_OverflowError,"too much marshall data for a string");return NULL;}_PyString_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base));}if (wf.error) {Py_XDECREF(wf.str);PyErr_SetString(PyExc_ValueError,(wf.error==1)?"unmarshallable object":"object too deeply nested to marshal");return NULL;}return wf.str;}/* And an interface for Python programs... */static PyObject *marshal_dump(PyObject *self, PyObject *args){WFILE wf;PyObject *x;PyObject *f;int version = Py_MARSHAL_VERSION;if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version))return NULL;if (!PyFile_Check(f)) {PyErr_SetString(PyExc_TypeError,"marshal.dump() 2nd arg must be file");return NULL;}wf.fp = PyFile_AsFile(f);wf.str = NULL;wf.ptr = wf.end = NULL;wf.error = 0;wf.depth = 0;wf.strings = (version > 0) ? PyDict_New() : 0;wf.version = version;w_object(x, &wf);Py_XDECREF(wf.strings);if (wf.error) {PyErr_SetString(PyExc_ValueError,(wf.error==1)?"unmarshallable object":"object too deeply nested to marshal");return NULL;}Py_INCREF(Py_None);return Py_None;}static PyObject *marshal_load(PyObject *self, PyObject *f){RFILE rf;PyObject *result;if (!PyFile_Check(f)) {PyErr_SetString(PyExc_TypeError,"marshal.load() arg must be file");return NULL;}rf.fp = PyFile_AsFile(f);rf.strings = PyList_New(0);rf.depth = 0;result = read_object(&rf);Py_DECREF(rf.strings);return result;}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);}static PyObject *marshal_loads(PyObject *self, PyObject *args){RFILE rf;char *s;Py_ssize_t n;PyObject* result;if (!PyArg_ParseTuple(args, "s#:loads", &s, &n))return NULL;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);return result;}static PyMethodDef marshal_methods[] = {{"dump", marshal_dump, METH_VARARGS},{"load", marshal_load, METH_O},{"dumps", marshal_dumps, METH_VARARGS},{"loads", marshal_loads, METH_VARARGS},{NULL, NULL} /* sentinel */};PyMODINIT_FUNCPyMarshal_Init(void){PyObject *mod = Py_InitModule("marshal", marshal_methods);if (mod == NULL)return;PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION);}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。