1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903 |
- /* Write Python objects to files and read them back.
- This is primarily intended for writing and reading compiled Python code,
- even though dicts, lists, sets and frozensets, not commonly seen in
- code objects, are supported.
- Version 3 of this protocol properly supports circular links
- and sharing. */
- #define PY_SSIZE_T_CLEAN
- #include "Python.h"
- #include "pycore_call.h" // _PyObject_CallNoArgs()
- #include "pycore_code.h" // _PyCode_New()
- #include "pycore_long.h" // _PyLong_DigitCount
- #include "pycore_hashtable.h" // _Py_hashtable_t
- #include "marshal.h" // Py_MARSHAL_VERSION
- /*[clinic input]
- module marshal
- [clinic start generated code]*/
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c982b7930dee17db]*/
- #include "clinic/marshal.c.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.
- * On Windows debug builds, reduce this value.
- *
- * BUG: https://bugs.python.org/issue33720
- * On Windows PGO builds, the r_object function overallocates its stack and
- * can cause a stack overflow. We reduce the maximum depth for all Windows
- * releases to protect against this.
- * #if defined(MS_WINDOWS) && defined(_DEBUG)
- */
- #if defined(MS_WINDOWS)
- #define MAX_MARSHAL_STACK_DEPTH 1000
- #elif defined(__wasi__)
- #define MAX_MARSHAL_STACK_DEPTH 1500
- #else
- #define MAX_MARSHAL_STACK_DEPTH 2000
- #endif
- #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'
- /* TYPE_INT64 is not generated anymore.
- Supported for backward compatibility only. */
- #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_REF '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 '>'
- #define FLAG_REF '\x80' /* with a type, add obj to index */
- #define TYPE_ASCII 'a'
- #define TYPE_ASCII_INTERNED 'A'
- #define TYPE_SMALL_TUPLE ')'
- #define TYPE_SHORT_ASCII 'z'
- #define TYPE_SHORT_ASCII_INTERNED 'Z'
- #define WFERR_OK 0
- #define WFERR_UNMARSHALLABLE 1
- #define WFERR_NESTEDTOODEEP 2
- #define WFERR_NOMEMORY 3
- typedef struct {
- FILE *fp;
- int error; /* see WFERR_* values */
- int depth;
- PyObject *str;
- char *ptr;
- const char *end;
- char *buf;
- _Py_hashtable_t *hashtable;
- int version;
- } WFILE;
- #define w_byte(c, p) do { \
- if ((p)->ptr != (p)->end || w_reserve((p), 1)) \
- *(p)->ptr++ = (c); \
- } while(0)
- static void
- w_flush(WFILE *p)
- {
- assert(p->fp != NULL);
- fwrite(p->buf, 1, p->ptr - p->buf, p->fp);
- p->ptr = p->buf;
- }
- static int
- w_reserve(WFILE *p, Py_ssize_t needed)
- {
- Py_ssize_t pos, size, delta;
- if (p->ptr == NULL)
- return 0; /* An error already occurred */
- if (p->fp != NULL) {
- w_flush(p);
- return needed <= p->end - p->ptr;
- }
- assert(p->str != NULL);
- pos = p->ptr - p->buf;
- size = PyBytes_GET_SIZE(p->str);
- if (size > 16*1024*1024)
- delta = (size >> 3); /* 12.5% overallocation */
- else
- delta = size + 1024;
- delta = Py_MAX(delta, needed);
- if (delta > PY_SSIZE_T_MAX - size) {
- p->error = WFERR_NOMEMORY;
- return 0;
- }
- size += delta;
- if (_PyBytes_Resize(&p->str, size) != 0) {
- p->end = p->ptr = p->buf = NULL;
- return 0;
- }
- else {
- p->buf = PyBytes_AS_STRING(p->str);
- p->ptr = p->buf + pos;
- p->end = p->buf + size;
- return 1;
- }
- }
- static void
- w_string(const void *s, Py_ssize_t n, WFILE *p)
- {
- Py_ssize_t m;
- if (!n || p->ptr == NULL)
- return;
- m = p->end - p->ptr;
- if (p->fp != NULL) {
- if (n <= m) {
- memcpy(p->ptr, s, n);
- p->ptr += n;
- }
- else {
- w_flush(p);
- fwrite(s, 1, n, p->fp);
- }
- }
- else {
- if (n <= m || w_reserve(p, n - m)) {
- memcpy(p->ptr, s, n);
- p->ptr += n;
- }
- }
- }
- static void
- w_short(int x, WFILE *p)
- {
- w_byte((char)( x & 0xff), p);
- w_byte((char)((x>> 8) & 0xff), p);
- }
- static void
- w_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);
- }
- #define SIZE32_MAX 0x7FFFFFFF
- #if SIZEOF_SIZE_T > 4
- # define W_SIZE(n, p) do { \
- if ((n) > SIZE32_MAX) { \
- (p)->depth--; \
- (p)->error = WFERR_UNMARSHALLABLE; \
- return; \
- } \
- w_long((long)(n), p); \
- } while(0)
- #else
- # define W_SIZE w_long
- #endif
- static void
- w_pstring(const void *s, Py_ssize_t n, WFILE *p)
- {
- W_SIZE(n, p);
- w_string(s, n, p);
- }
- static void
- w_short_pstring(const void *s, Py_ssize_t n, WFILE *p)
- {
- w_byte(Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char), 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. */
- #define PyLong_MARSHAL_SHIFT 15
- #define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT)
- #define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1)
- #if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0
- #error "PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT"
- #endif
- #define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT)
- #define W_TYPE(t, p) do { \
- w_byte((t) | flag, (p)); \
- } while(0)
- static void
- w_PyLong(const PyLongObject *ob, char flag, WFILE *p)
- {
- Py_ssize_t i, j, n, l;
- digit d;
- W_TYPE(TYPE_LONG, p);
- if (_PyLong_IsZero(ob)) {
- w_long((long)0, p);
- return;
- }
- /* set l to number of base PyLong_MARSHAL_BASE digits */
- n = _PyLong_DigitCount(ob);
- l = (n-1) * PyLong_MARSHAL_RATIO;
- d = ob->long_value.ob_digit[n-1];
- assert(d != 0); /* a PyLong is always normalized */
- do {
- d >>= PyLong_MARSHAL_SHIFT;
- l++;
- } while (d != 0);
- if (l > SIZE32_MAX) {
- p->depth--;
- p->error = WFERR_UNMARSHALLABLE;
- return;
- }
- w_long((long)(_PyLong_IsNegative(ob) ? -l : l), p);
- for (i=0; i < n-1; i++) {
- d = ob->long_value.ob_digit[i];
- for (j=0; j < PyLong_MARSHAL_RATIO; j++) {
- w_short(d & PyLong_MARSHAL_MASK, p);
- d >>= PyLong_MARSHAL_SHIFT;
- }
- assert (d == 0);
- }
- d = ob->long_value.ob_digit[n-1];
- do {
- w_short(d & PyLong_MARSHAL_MASK, p);
- d >>= PyLong_MARSHAL_SHIFT;
- } while (d != 0);
- }
- static void
- w_float_bin(double v, WFILE *p)
- {
- char buf[8];
- if (PyFloat_Pack8(v, buf, 1) < 0) {
- p->error = WFERR_UNMARSHALLABLE;
- return;
- }
- w_string(buf, 8, p);
- }
- static void
- w_float_str(double v, WFILE *p)
- {
- char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL);
- if (!buf) {
- p->error = WFERR_NOMEMORY;
- return;
- }
- w_short_pstring(buf, strlen(buf), p);
- PyMem_Free(buf);
- }
- static int
- w_ref(PyObject *v, char *flag, WFILE *p)
- {
- _Py_hashtable_entry_t *entry;
- int w;
- if (p->version < 3 || p->hashtable == NULL)
- return 0; /* not writing object references */
- /* If it has only one reference, it definitely isn't shared.
- * But we use TYPE_REF always for interned string, to PYC file stable
- * as possible.
- */
- if (Py_REFCNT(v) == 1 &&
- !(PyUnicode_CheckExact(v) && PyUnicode_CHECK_INTERNED(v))) {
- return 0;
- }
- entry = _Py_hashtable_get_entry(p->hashtable, v);
- if (entry != NULL) {
- /* write the reference index to the stream */
- w = (int)(uintptr_t)entry->value;
- /* we don't store "long" indices in the dict */
- assert(0 <= w && w <= 0x7fffffff);
- w_byte(TYPE_REF, p);
- w_long(w, p);
- return 1;
- } else {
- size_t s = p->hashtable->nentries;
- /* we don't support long indices */
- if (s >= 0x7fffffff) {
- PyErr_SetString(PyExc_ValueError, "too many objects");
- goto err;
- }
- w = (int)s;
- if (_Py_hashtable_set(p->hashtable, Py_NewRef(v),
- (void *)(uintptr_t)w) < 0) {
- Py_DECREF(v);
- goto err;
- }
- *flag |= FLAG_REF;
- return 0;
- }
- err:
- p->error = WFERR_UNMARSHALLABLE;
- return 1;
- }
- static void
- w_complex_object(PyObject *v, char flag, WFILE *p);
- static void
- w_object(PyObject *v, WFILE *p)
- {
- char flag = '\0';
- p->depth++;
- if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
- p->error = WFERR_NESTEDTOODEEP;
- }
- 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 (!w_ref(v, &flag, p))
- w_complex_object(v, flag, p);
- p->depth--;
- }
- static void
- w_complex_object(PyObject *v, char flag, WFILE *p)
- {
- Py_ssize_t i, n;
- if (PyLong_CheckExact(v)) {
- int overflow;
- long x = PyLong_AsLongAndOverflow(v, &overflow);
- if (overflow) {
- w_PyLong((PyLongObject *)v, flag, p);
- }
- else {
- #if SIZEOF_LONG > 4
- long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);
- if (y && y != -1) {
- /* Too large for TYPE_INT */
- w_PyLong((PyLongObject*)v, flag, p);
- }
- else
- #endif
- {
- W_TYPE(TYPE_INT, p);
- w_long(x, p);
- }
- }
- }
- else if (PyFloat_CheckExact(v)) {
- if (p->version > 1) {
- W_TYPE(TYPE_BINARY_FLOAT, p);
- w_float_bin(PyFloat_AS_DOUBLE(v), p);
- }
- else {
- W_TYPE(TYPE_FLOAT, p);
- w_float_str(PyFloat_AS_DOUBLE(v), p);
- }
- }
- else if (PyComplex_CheckExact(v)) {
- if (p->version > 1) {
- W_TYPE(TYPE_BINARY_COMPLEX, p);
- w_float_bin(PyComplex_RealAsDouble(v), p);
- w_float_bin(PyComplex_ImagAsDouble(v), p);
- }
- else {
- W_TYPE(TYPE_COMPLEX, p);
- w_float_str(PyComplex_RealAsDouble(v), p);
- w_float_str(PyComplex_ImagAsDouble(v), p);
- }
- }
- else if (PyBytes_CheckExact(v)) {
- W_TYPE(TYPE_STRING, p);
- w_pstring(PyBytes_AS_STRING(v), PyBytes_GET_SIZE(v), p);
- }
- else if (PyUnicode_CheckExact(v)) {
- if (p->version >= 4 && PyUnicode_IS_ASCII(v)) {
- int is_short = PyUnicode_GET_LENGTH(v) < 256;
- if (is_short) {
- if (PyUnicode_CHECK_INTERNED(v))
- W_TYPE(TYPE_SHORT_ASCII_INTERNED, p);
- else
- W_TYPE(TYPE_SHORT_ASCII, p);
- w_short_pstring(PyUnicode_1BYTE_DATA(v),
- PyUnicode_GET_LENGTH(v), p);
- }
- else {
- if (PyUnicode_CHECK_INTERNED(v))
- W_TYPE(TYPE_ASCII_INTERNED, p);
- else
- W_TYPE(TYPE_ASCII, p);
- w_pstring(PyUnicode_1BYTE_DATA(v),
- PyUnicode_GET_LENGTH(v), p);
- }
- }
- else {
- PyObject *utf8;
- utf8 = PyUnicode_AsEncodedString(v, "utf8", "surrogatepass");
- if (utf8 == NULL) {
- p->depth--;
- p->error = WFERR_UNMARSHALLABLE;
- return;
- }
- if (p->version >= 3 && PyUnicode_CHECK_INTERNED(v))
- W_TYPE(TYPE_INTERNED, p);
- else
- W_TYPE(TYPE_UNICODE, p);
- w_pstring(PyBytes_AS_STRING(utf8), PyBytes_GET_SIZE(utf8), p);
- Py_DECREF(utf8);
- }
- }
- else if (PyTuple_CheckExact(v)) {
- n = PyTuple_GET_SIZE(v);
- if (p->version >= 4 && n < 256) {
- W_TYPE(TYPE_SMALL_TUPLE, p);
- w_byte((unsigned char)n, p);
- }
- else {
- W_TYPE(TYPE_TUPLE, p);
- W_SIZE(n, p);
- }
- for (i = 0; i < n; i++) {
- w_object(PyTuple_GET_ITEM(v, i), p);
- }
- }
- else if (PyList_CheckExact(v)) {
- W_TYPE(TYPE_LIST, p);
- n = PyList_GET_SIZE(v);
- W_SIZE(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_TYPE(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;
- Py_ssize_t pos = 0;
- Py_hash_t hash;
- if (PyFrozenSet_CheckExact(v))
- W_TYPE(TYPE_FROZENSET, p);
- else
- W_TYPE(TYPE_SET, p);
- n = PySet_GET_SIZE(v);
- W_SIZE(n, p);
- // bpo-37596: To support reproducible builds, sets and frozensets need
- // to have their elements serialized in a consistent order (even when
- // they have been scrambled by hash randomization). To ensure this, we
- // use an order equivalent to sorted(v, key=marshal.dumps):
- PyObject *pairs = PyList_New(n);
- if (pairs == NULL) {
- p->error = WFERR_NOMEMORY;
- return;
- }
- Py_ssize_t i = 0;
- while (_PySet_NextEntry(v, &pos, &value, &hash)) {
- PyObject *dump = PyMarshal_WriteObjectToString(value, p->version);
- if (dump == NULL) {
- p->error = WFERR_UNMARSHALLABLE;
- Py_DECREF(pairs);
- return;
- }
- PyObject *pair = PyTuple_Pack(2, dump, value);
- Py_DECREF(dump);
- if (pair == NULL) {
- p->error = WFERR_NOMEMORY;
- Py_DECREF(pairs);
- return;
- }
- PyList_SET_ITEM(pairs, i++, pair);
- }
- assert(i == n);
- if (PyList_Sort(pairs)) {
- p->error = WFERR_NOMEMORY;
- Py_DECREF(pairs);
- return;
- }
- for (Py_ssize_t i = 0; i < n; i++) {
- PyObject *pair = PyList_GET_ITEM(pairs, i);
- value = PyTuple_GET_ITEM(pair, 1);
- w_object(value, p);
- }
- Py_DECREF(pairs);
- }
- else if (PyCode_Check(v)) {
- PyCodeObject *co = (PyCodeObject *)v;
- PyObject *co_code = _PyCode_GetCode(co);
- if (co_code == NULL) {
- p->error = WFERR_NOMEMORY;
- return;
- }
- W_TYPE(TYPE_CODE, p);
- w_long(co->co_argcount, p);
- w_long(co->co_posonlyargcount, p);
- w_long(co->co_kwonlyargcount, p);
- w_long(co->co_stacksize, p);
- w_long(co->co_flags, p);
- w_object(co_code, p);
- w_object(co->co_consts, p);
- w_object(co->co_names, p);
- w_object(co->co_localsplusnames, p);
- w_object(co->co_localspluskinds, p);
- w_object(co->co_filename, p);
- w_object(co->co_name, p);
- w_object(co->co_qualname, p);
- w_long(co->co_firstlineno, p);
- w_object(co->co_linetable, p);
- w_object(co->co_exceptiontable, p);
- Py_DECREF(co_code);
- }
- else if (PyObject_CheckBuffer(v)) {
- /* Write unknown bytes-like objects as a bytes object */
- Py_buffer view;
- if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) {
- w_byte(TYPE_UNKNOWN, p);
- p->depth--;
- p->error = WFERR_UNMARSHALLABLE;
- return;
- }
- W_TYPE(TYPE_STRING, p);
- w_pstring(view.buf, view.len, p);
- PyBuffer_Release(&view);
- }
- else {
- W_TYPE(TYPE_UNKNOWN, p);
- p->error = WFERR_UNMARSHALLABLE;
- }
- }
- static void
- w_decref_entry(void *key)
- {
- PyObject *entry_key = (PyObject *)key;
- Py_XDECREF(entry_key);
- }
- static int
- w_init_refs(WFILE *wf, int version)
- {
- if (version >= 3) {
- wf->hashtable = _Py_hashtable_new_full(_Py_hashtable_hash_ptr,
- _Py_hashtable_compare_direct,
- w_decref_entry, NULL, NULL);
- if (wf->hashtable == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- }
- return 0;
- }
- static void
- w_clear_refs(WFILE *wf)
- {
- if (wf->hashtable != NULL) {
- _Py_hashtable_destroy(wf->hashtable);
- }
- }
- /* version currently has no effect for writing ints. */
- /* Note that while the documentation states that this function
- * can error, currently it never does. Setting an exception in
- * this function should be regarded as an API-breaking change.
- */
- void
- PyMarshal_WriteLongToFile(long x, FILE *fp, int version)
- {
- char buf[4];
- WFILE wf;
- memset(&wf, 0, sizeof(wf));
- wf.fp = fp;
- wf.ptr = wf.buf = buf;
- wf.end = wf.ptr + sizeof(buf);
- wf.error = WFERR_OK;
- wf.version = version;
- w_long(x, &wf);
- w_flush(&wf);
- }
- void
- PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
- {
- char buf[BUFSIZ];
- WFILE wf;
- if (PySys_Audit("marshal.dumps", "Oi", x, version) < 0) {
- return; /* caller must check PyErr_Occurred() */
- }
- memset(&wf, 0, sizeof(wf));
- wf.fp = fp;
- wf.ptr = wf.buf = buf;
- wf.end = wf.ptr + sizeof(buf);
- wf.error = WFERR_OK;
- wf.version = version;
- if (w_init_refs(&wf, version)) {
- return; /* caller must check PyErr_Occurred() */
- }
- w_object(x, &wf);
- w_clear_refs(&wf);
- w_flush(&wf);
- }
- typedef struct {
- FILE *fp;
- int depth;
- PyObject *readable; /* Stream-like object being read from */
- const char *ptr;
- const char *end;
- char *buf;
- Py_ssize_t buf_size;
- PyObject *refs; /* a list */
- } RFILE;
- static const char *
- r_string(Py_ssize_t n, RFILE *p)
- {
- Py_ssize_t read = -1;
- if (p->ptr != NULL) {
- /* Fast path for loads() */
- const char *res = p->ptr;
- Py_ssize_t left = p->end - p->ptr;
- if (left < n) {
- PyErr_SetString(PyExc_EOFError,
- "marshal data too short");
- return NULL;
- }
- p->ptr += n;
- return res;
- }
- if (p->buf == NULL) {
- p->buf = PyMem_Malloc(n);
- if (p->buf == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- p->buf_size = n;
- }
- else if (p->buf_size < n) {
- char *tmp = PyMem_Realloc(p->buf, n);
- if (tmp == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- p->buf = tmp;
- p->buf_size = n;
- }
- if (!p->readable) {
- assert(p->fp != NULL);
- read = fread(p->buf, 1, n, p->fp);
- }
- else {
- PyObject *res, *mview;
- Py_buffer buf;
- if (PyBuffer_FillInfo(&buf, NULL, p->buf, n, 0, PyBUF_CONTIG) == -1)
- return NULL;
- mview = PyMemoryView_FromBuffer(&buf);
- if (mview == NULL)
- return NULL;
- res = _PyObject_CallMethod(p->readable, &_Py_ID(readinto), "N", mview);
- if (res != NULL) {
- read = PyNumber_AsSsize_t(res, PyExc_ValueError);
- Py_DECREF(res);
- }
- }
- if (read != n) {
- if (!PyErr_Occurred()) {
- if (read > n)
- PyErr_Format(PyExc_ValueError,
- "read() returned too much data: "
- "%zd bytes requested, %zd returned",
- n, read);
- else
- PyErr_SetString(PyExc_EOFError,
- "EOF read where not expected");
- }
- return NULL;
- }
- return p->buf;
- }
- static int
- r_byte(RFILE *p)
- {
- if (p->ptr != NULL) {
- if (p->ptr < p->end) {
- return (unsigned char) *p->ptr++;
- }
- }
- else if (!p->readable) {
- assert(p->fp);
- int c = getc(p->fp);
- if (c != EOF) {
- return c;
- }
- }
- else {
- const char *ptr = r_string(1, p);
- if (ptr != NULL) {
- return *(const unsigned char *) ptr;
- }
- return EOF;
- }
- PyErr_SetString(PyExc_EOFError,
- "EOF read where not expected");
- return EOF;
- }
- static int
- r_short(RFILE *p)
- {
- short x = -1;
- const unsigned char *buffer;
- buffer = (const unsigned char *) r_string(2, p);
- if (buffer != NULL) {
- x = buffer[0];
- x |= buffer[1] << 8;
- /* Sign-extension, in case short greater than 16 bits */
- x |= -(x & 0x8000);
- }
- return x;
- }
- static long
- r_long(RFILE *p)
- {
- long x = -1;
- const unsigned char *buffer;
- buffer = (const unsigned char *) r_string(4, p);
- if (buffer != NULL) {
- x = buffer[0];
- x |= (long)buffer[1] << 8;
- x |= (long)buffer[2] << 16;
- x |= (long)buffer[3] << 24;
- #if SIZEOF_LONG > 4
- /* Sign extension for 64-bit machines */
- x |= -(x & 0x80000000L);
- #endif
- }
- return x;
- }
- /* r_long64 deals with the TYPE_INT64 code. */
- static PyObject *
- r_long64(RFILE *p)
- {
- const unsigned char *buffer = (const unsigned char *) r_string(8, p);
- if (buffer == NULL) {
- return NULL;
- }
- return _PyLong_FromByteArray(buffer, 8,
- 1 /* little endian */,
- 1 /* signed */);
- }
- static PyObject *
- r_PyLong(RFILE *p)
- {
- PyLongObject *ob;
- long n, size, i;
- int j, md, shorts_in_top_digit;
- digit d;
- n = r_long(p);
- if (n == 0)
- return (PyObject *)_PyLong_New(0);
- if (n == -1 && PyErr_Occurred()) {
- return NULL;
- }
- if (n < -SIZE32_MAX || n > SIZE32_MAX) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (long size out of range)");
- return NULL;
- }
- size = 1 + (Py_ABS(n) - 1) / PyLong_MARSHAL_RATIO;
- shorts_in_top_digit = 1 + (Py_ABS(n) - 1) % PyLong_MARSHAL_RATIO;
- ob = _PyLong_New(size);
- if (ob == NULL)
- return NULL;
- _PyLong_SetSignAndDigitCount(ob, n < 0 ? -1 : 1, size);
- for (i = 0; i < size-1; i++) {
- d = 0;
- for (j=0; j < PyLong_MARSHAL_RATIO; j++) {
- md = r_short(p);
- if (md < 0 || md > PyLong_MARSHAL_BASE)
- goto bad_digit;
- d += (digit)md << j*PyLong_MARSHAL_SHIFT;
- }
- ob->long_value.ob_digit[i] = d;
- }
- d = 0;
- for (j=0; j < shorts_in_top_digit; j++) {
- md = r_short(p);
- if (md < 0 || md > PyLong_MARSHAL_BASE)
- goto bad_digit;
- /* topmost marshal digit should be nonzero */
- if (md == 0 && j == shorts_in_top_digit - 1) {
- Py_DECREF(ob);
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (unnormalized long data)");
- return NULL;
- }
- d += (digit)md << j*PyLong_MARSHAL_SHIFT;
- }
- assert(!PyErr_Occurred());
- /* top digit should be nonzero, else the resulting PyLong won't be
- normalized */
- ob->long_value.ob_digit[size-1] = d;
- return (PyObject *)ob;
- bad_digit:
- Py_DECREF(ob);
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (digit out of range in long)");
- }
- return NULL;
- }
- static double
- r_float_bin(RFILE *p)
- {
- const char *buf = r_string(8, p);
- if (buf == NULL)
- return -1;
- return PyFloat_Unpack8(buf, 1);
- }
- /* Issue #33720: Disable inlining for reducing the C stack consumption
- on PGO builds. */
- Py_NO_INLINE static double
- r_float_str(RFILE *p)
- {
- int n;
- char buf[256];
- const char *ptr;
- n = r_byte(p);
- if (n == EOF) {
- return -1;
- }
- ptr = r_string(n, p);
- if (ptr == NULL) {
- return -1;
- }
- memcpy(buf, ptr, n);
- buf[n] = '\0';
- return PyOS_string_to_double(buf, NULL, NULL);
- }
- /* allocate the reflist index for a new object. Return -1 on failure */
- static Py_ssize_t
- r_ref_reserve(int flag, RFILE *p)
- {
- if (flag) { /* currently only FLAG_REF is defined */
- Py_ssize_t idx = PyList_GET_SIZE(p->refs);
- if (idx >= 0x7ffffffe) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (index list too large)");
- return -1;
- }
- if (PyList_Append(p->refs, Py_None) < 0)
- return -1;
- return idx;
- } else
- return 0;
- }
- /* insert the new object 'o' to the reflist at previously
- * allocated index 'idx'.
- * 'o' can be NULL, in which case nothing is done.
- * if 'o' was non-NULL, and the function succeeds, 'o' is returned.
- * if 'o' was non-NULL, and the function fails, 'o' is released and
- * NULL returned. This simplifies error checking at the call site since
- * a single test for NULL for the function result is enough.
- */
- static PyObject *
- r_ref_insert(PyObject *o, Py_ssize_t idx, int flag, RFILE *p)
- {
- if (o != NULL && flag) { /* currently only FLAG_REF is defined */
- PyObject *tmp = PyList_GET_ITEM(p->refs, idx);
- PyList_SET_ITEM(p->refs, idx, Py_NewRef(o));
- Py_DECREF(tmp);
- }
- return o;
- }
- /* combination of both above, used when an object can be
- * created whenever it is seen in the file, as opposed to
- * after having loaded its sub-objects.
- */
- static PyObject *
- r_ref(PyObject *o, int flag, RFILE *p)
- {
- assert(flag & FLAG_REF);
- if (o == NULL)
- return NULL;
- if (PyList_Append(p->refs, o) < 0) {
- Py_DECREF(o); /* release the new object */
- return NULL;
- }
- return o;
- }
- static PyObject *
- r_object(RFILE *p)
- {
- /* NULL is a valid return value, it does not necessarily means that
- an exception is set. */
- PyObject *v, *v2;
- Py_ssize_t idx = 0;
- long i, n;
- int type, code = r_byte(p);
- int flag, is_interned = 0;
- PyObject *retval = NULL;
- if (code == EOF) {
- if (PyErr_ExceptionMatches(PyExc_EOFError)) {
- PyErr_SetString(PyExc_EOFError,
- "EOF read where object expected");
- }
- return NULL;
- }
- p->depth++;
- if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
- p->depth--;
- PyErr_SetString(PyExc_ValueError, "recursion limit exceeded");
- return NULL;
- }
- flag = code & FLAG_REF;
- type = code & ~FLAG_REF;
- #define R_REF(O) do{\
- if (flag) \
- O = r_ref(O, flag, p);\
- } while (0)
- switch (type) {
- case TYPE_NULL:
- break;
- case TYPE_NONE:
- retval = Py_NewRef(Py_None);
- break;
- case TYPE_STOPITER:
- retval = Py_NewRef(PyExc_StopIteration);
- break;
- case TYPE_ELLIPSIS:
- retval = Py_NewRef(Py_Ellipsis);
- break;
- case TYPE_FALSE:
- retval = Py_NewRef(Py_False);
- break;
- case TYPE_TRUE:
- retval = Py_NewRef(Py_True);
- break;
- case TYPE_INT:
- n = r_long(p);
- if (n == -1 && PyErr_Occurred()) {
- break;
- }
- retval = PyLong_FromLong(n);
- R_REF(retval);
- break;
- case TYPE_INT64:
- retval = r_long64(p);
- R_REF(retval);
- break;
- case TYPE_LONG:
- retval = r_PyLong(p);
- R_REF(retval);
- break;
- case TYPE_FLOAT:
- {
- double x = r_float_str(p);
- if (x == -1.0 && PyErr_Occurred())
- break;
- retval = PyFloat_FromDouble(x);
- R_REF(retval);
- break;
- }
- case TYPE_BINARY_FLOAT:
- {
- double x = r_float_bin(p);
- if (x == -1.0 && PyErr_Occurred())
- break;
- retval = PyFloat_FromDouble(x);
- R_REF(retval);
- break;
- }
- case TYPE_COMPLEX:
- {
- Py_complex c;
- c.real = r_float_str(p);
- if (c.real == -1.0 && PyErr_Occurred())
- break;
- c.imag = r_float_str(p);
- if (c.imag == -1.0 && PyErr_Occurred())
- break;
- retval = PyComplex_FromCComplex(c);
- R_REF(retval);
- break;
- }
- case TYPE_BINARY_COMPLEX:
- {
- Py_complex c;
- c.real = r_float_bin(p);
- if (c.real == -1.0 && PyErr_Occurred())
- break;
- c.imag = r_float_bin(p);
- if (c.imag == -1.0 && PyErr_Occurred())
- break;
- retval = PyComplex_FromCComplex(c);
- R_REF(retval);
- break;
- }
- case TYPE_STRING:
- {
- const char *ptr;
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (bytes object size out of range)");
- }
- break;
- }
- v = PyBytes_FromStringAndSize((char *)NULL, n);
- if (v == NULL)
- break;
- ptr = r_string(n, p);
- if (ptr == NULL) {
- Py_DECREF(v);
- break;
- }
- memcpy(PyBytes_AS_STRING(v), ptr, n);
- retval = v;
- R_REF(retval);
- break;
- }
- case TYPE_ASCII_INTERNED:
- is_interned = 1;
- /* fall through */
- case TYPE_ASCII:
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (string size out of range)");
- }
- break;
- }
- goto _read_ascii;
- case TYPE_SHORT_ASCII_INTERNED:
- is_interned = 1;
- /* fall through */
- case TYPE_SHORT_ASCII:
- n = r_byte(p);
- if (n == EOF) {
- break;
- }
- _read_ascii:
- {
- const char *ptr;
- ptr = r_string(n, p);
- if (ptr == NULL)
- break;
- v = PyUnicode_FromKindAndData(PyUnicode_1BYTE_KIND, ptr, n);
- if (v == NULL)
- break;
- if (is_interned)
- PyUnicode_InternInPlace(&v);
- retval = v;
- R_REF(retval);
- break;
- }
- case TYPE_INTERNED:
- is_interned = 1;
- /* fall through */
- case TYPE_UNICODE:
- {
- const char *buffer;
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (string size out of range)");
- }
- break;
- }
- if (n != 0) {
- buffer = r_string(n, p);
- if (buffer == NULL)
- break;
- v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass");
- }
- else {
- v = PyUnicode_New(0, 0);
- }
- if (v == NULL)
- break;
- if (is_interned)
- PyUnicode_InternInPlace(&v);
- retval = v;
- R_REF(retval);
- break;
- }
- case TYPE_SMALL_TUPLE:
- n = r_byte(p);
- if (n == EOF) {
- break;
- }
- goto _read_tuple;
- case TYPE_TUPLE:
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (tuple size out of range)");
- }
- break;
- }
- _read_tuple:
- v = PyTuple_New(n);
- R_REF(v);
- if (v == 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 for tuple");
- Py_SETREF(v, NULL);
- break;
- }
- PyTuple_SET_ITEM(v, i, v2);
- }
- retval = v;
- break;
- case TYPE_LIST:
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (list size out of range)");
- }
- break;
- }
- v = PyList_New(n);
- R_REF(v);
- if (v == 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 for list");
- Py_SETREF(v, NULL);
- break;
- }
- PyList_SET_ITEM(v, i, v2);
- }
- retval = v;
- break;
- case TYPE_DICT:
- v = PyDict_New();
- R_REF(v);
- if (v == NULL)
- break;
- for (;;) {
- PyObject *key, *val;
- key = r_object(p);
- if (key == NULL)
- break;
- val = r_object(p);
- if (val == NULL) {
- Py_DECREF(key);
- break;
- }
- if (PyDict_SetItem(v, key, val) < 0) {
- Py_DECREF(key);
- Py_DECREF(val);
- break;
- }
- Py_DECREF(key);
- Py_DECREF(val);
- }
- if (PyErr_Occurred()) {
- Py_SETREF(v, NULL);
- }
- retval = v;
- break;
- case TYPE_SET:
- case TYPE_FROZENSET:
- n = r_long(p);
- if (n < 0 || n > SIZE32_MAX) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (set size out of range)");
- }
- break;
- }
- if (n == 0 && type == TYPE_FROZENSET) {
- /* call frozenset() to get the empty frozenset singleton */
- v = _PyObject_CallNoArgs((PyObject*)&PyFrozenSet_Type);
- if (v == NULL)
- break;
- R_REF(v);
- retval = v;
- }
- else {
- v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL);
- if (type == TYPE_SET) {
- R_REF(v);
- } else {
- /* must use delayed registration of frozensets because they must
- * be init with a refcount of 1
- */
- idx = r_ref_reserve(flag, p);
- if (idx < 0)
- Py_CLEAR(v); /* signal error */
- }
- if (v == 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 for set");
- Py_SETREF(v, NULL);
- break;
- }
- if (PySet_Add(v, v2) == -1) {
- Py_DECREF(v);
- Py_DECREF(v2);
- v = NULL;
- break;
- }
- Py_DECREF(v2);
- }
- if (type != TYPE_SET)
- v = r_ref_insert(v, idx, flag, p);
- retval = v;
- }
- break;
- case TYPE_CODE:
- {
- int argcount;
- int posonlyargcount;
- int kwonlyargcount;
- int stacksize;
- int flags;
- PyObject *code = NULL;
- PyObject *consts = NULL;
- PyObject *names = NULL;
- PyObject *localsplusnames = NULL;
- PyObject *localspluskinds = NULL;
- PyObject *filename = NULL;
- PyObject *name = NULL;
- PyObject *qualname = NULL;
- int firstlineno;
- PyObject* linetable = NULL;
- PyObject *exceptiontable = NULL;
- idx = r_ref_reserve(flag, p);
- if (idx < 0)
- break;
- v = NULL;
- /* XXX ignore long->int overflows for now */
- argcount = (int)r_long(p);
- if (argcount == -1 && PyErr_Occurred())
- goto code_error;
- posonlyargcount = (int)r_long(p);
- if (posonlyargcount == -1 && PyErr_Occurred()) {
- goto code_error;
- }
- kwonlyargcount = (int)r_long(p);
- if (kwonlyargcount == -1 && PyErr_Occurred())
- goto code_error;
- stacksize = (int)r_long(p);
- if (stacksize == -1 && PyErr_Occurred())
- goto code_error;
- flags = (int)r_long(p);
- if (flags == -1 && PyErr_Occurred())
- goto code_error;
- 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;
- localsplusnames = r_object(p);
- if (localsplusnames == NULL)
- goto code_error;
- localspluskinds = r_object(p);
- if (localspluskinds == NULL)
- goto code_error;
- filename = r_object(p);
- if (filename == NULL)
- goto code_error;
- name = r_object(p);
- if (name == NULL)
- goto code_error;
- qualname = r_object(p);
- if (qualname == NULL)
- goto code_error;
- firstlineno = (int)r_long(p);
- if (firstlineno == -1 && PyErr_Occurred())
- break;
- linetable = r_object(p);
- if (linetable == NULL)
- goto code_error;
- exceptiontable = r_object(p);
- if (exceptiontable == NULL)
- goto code_error;
- struct _PyCodeConstructor con = {
- .filename = filename,
- .name = name,
- .qualname = qualname,
- .flags = flags,
- .code = code,
- .firstlineno = firstlineno,
- .linetable = linetable,
- .consts = consts,
- .names = names,
- .localsplusnames = localsplusnames,
- .localspluskinds = localspluskinds,
- .argcount = argcount,
- .posonlyargcount = posonlyargcount,
- .kwonlyargcount = kwonlyargcount,
- .stacksize = stacksize,
- .exceptiontable = exceptiontable,
- };
- if (_PyCode_Validate(&con) < 0) {
- goto code_error;
- }
- v = (PyObject *)_PyCode_New(&con);
- if (v == NULL) {
- goto code_error;
- }
- v = r_ref_insert(v, idx, flag, p);
- code_error:
- if (v == NULL && !PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "NULL object in marshal data for code object");
- }
- Py_XDECREF(code);
- Py_XDECREF(consts);
- Py_XDECREF(names);
- Py_XDECREF(localsplusnames);
- Py_XDECREF(localspluskinds);
- Py_XDECREF(filename);
- Py_XDECREF(name);
- Py_XDECREF(qualname);
- Py_XDECREF(linetable);
- Py_XDECREF(exceptiontable);
- }
- retval = v;
- break;
- case TYPE_REF:
- n = r_long(p);
- if (n < 0 || n >= PyList_GET_SIZE(p->refs)) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "bad marshal data (invalid reference)");
- }
- break;
- }
- v = PyList_GET_ITEM(p->refs, n);
- if (v == Py_None) {
- PyErr_SetString(PyExc_ValueError, "bad marshal data (invalid reference)");
- break;
- }
- retval = Py_NewRef(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 (unknown type code)");
- 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;
- }
- if (p->ptr && p->end) {
- if (PySys_Audit("marshal.loads", "y#", p->ptr, (Py_ssize_t)(p->end - p->ptr)) < 0) {
- return NULL;
- }
- } else if (p->fp || p->readable) {
- if (PySys_Audit("marshal.load", NULL) < 0) {
- return NULL;
- }
- }
- v = r_object(p);
- if (v == NULL && !PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError, "NULL object in marshal data for object");
- return v;
- }
- int
- PyMarshal_ReadShortFromFile(FILE *fp)
- {
- RFILE rf;
- int res;
- assert(fp);
- rf.readable = NULL;
- rf.fp = fp;
- rf.end = rf.ptr = NULL;
- rf.buf = NULL;
- res = r_short(&rf);
- if (rf.buf != NULL)
- PyMem_Free(rf.buf);
- return res;
- }
- long
- PyMarshal_ReadLongFromFile(FILE *fp)
- {
- RFILE rf;
- long res;
- rf.fp = fp;
- rf.readable = NULL;
- rf.ptr = rf.end = NULL;
- rf.buf = NULL;
- res = r_long(&rf);
- if (rf.buf != NULL)
- PyMem_Free(rf.buf);
- return res;
- }
- /* Return size of file in bytes; < 0 if unknown or INT_MAX if too big */
- static off_t
- getfilesize(FILE *fp)
- {
- struct _Py_stat_struct st;
- if (_Py_fstat_noraise(fileno(fp), &st) != 0)
- return -1;
- #if SIZEOF_OFF_T == 4
- else if (st.st_size >= INT_MAX)
- return (off_t)INT_MAX;
- #endif
- else
- return (off_t)st.st_size;
- }
- /* 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)
- {
- /* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. */
- #define REASONABLE_FILE_LIMIT (1L << 18)
- off_t filesize;
- filesize = getfilesize(fp);
- if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) {
- char* pBuf = (char *)PyMem_Malloc(filesize);
- if (pBuf != NULL) {
- size_t n = fread(pBuf, 1, (size_t)filesize, fp);
- PyObject* v = PyMarshal_ReadObjectFromString(pBuf, n);
- PyMem_Free(pBuf);
- return v;
- }
- }
- /* 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 REASONABLE_FILE_LIMIT
- }
- PyObject *
- PyMarshal_ReadObjectFromFile(FILE *fp)
- {
- RFILE rf;
- PyObject *result;
- rf.fp = fp;
- rf.readable = NULL;
- rf.depth = 0;
- rf.ptr = rf.end = NULL;
- rf.buf = NULL;
- rf.refs = PyList_New(0);
- if (rf.refs == NULL)
- return NULL;
- result = read_object(&rf);
- Py_DECREF(rf.refs);
- if (rf.buf != NULL)
- PyMem_Free(rf.buf);
- return result;
- }
- PyObject *
- PyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len)
- {
- RFILE rf;
- PyObject *result;
- rf.fp = NULL;
- rf.readable = NULL;
- rf.ptr = str;
- rf.end = str + len;
- rf.buf = NULL;
- rf.depth = 0;
- rf.refs = PyList_New(0);
- if (rf.refs == NULL)
- return NULL;
- result = read_object(&rf);
- Py_DECREF(rf.refs);
- if (rf.buf != NULL)
- PyMem_Free(rf.buf);
- return result;
- }
- PyObject *
- PyMarshal_WriteObjectToString(PyObject *x, int version)
- {
- WFILE wf;
- if (PySys_Audit("marshal.dumps", "Oi", x, version) < 0) {
- return NULL;
- }
- memset(&wf, 0, sizeof(wf));
- wf.str = PyBytes_FromStringAndSize((char *)NULL, 50);
- if (wf.str == NULL)
- return NULL;
- wf.ptr = wf.buf = PyBytes_AS_STRING(wf.str);
- wf.end = wf.ptr + PyBytes_GET_SIZE(wf.str);
- wf.error = WFERR_OK;
- wf.version = version;
- if (w_init_refs(&wf, version)) {
- Py_DECREF(wf.str);
- return NULL;
- }
- w_object(x, &wf);
- w_clear_refs(&wf);
- if (wf.str != NULL) {
- const char *base = PyBytes_AS_STRING(wf.str);
- if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)
- return NULL;
- }
- if (wf.error != WFERR_OK) {
- Py_XDECREF(wf.str);
- if (wf.error == WFERR_NOMEMORY)
- PyErr_NoMemory();
- else
- PyErr_SetString(PyExc_ValueError,
- (wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object"
- :"object too deeply nested to marshal");
- return NULL;
- }
- return wf.str;
- }
- /* And an interface for Python programs... */
- /*[clinic input]
- marshal.dump
- value: object
- Must be a supported type.
- file: object
- Must be a writeable binary file.
- version: int(c_default="Py_MARSHAL_VERSION") = version
- Indicates the data format that dump should use.
- /
- Write the value on the open file.
- If the value has (or contains an object that has) an unsupported type, a
- ValueError exception is raised - but garbage data will also be written
- to the file. The object will not be properly read back by load().
- [clinic start generated code]*/
- static PyObject *
- marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file,
- int version)
- /*[clinic end generated code: output=aaee62c7028a7cb2 input=6c7a3c23c6fef556]*/
- {
- /* XXX Quick hack -- need to do this differently */
- PyObject *s;
- PyObject *res;
- s = PyMarshal_WriteObjectToString(value, version);
- if (s == NULL)
- return NULL;
- res = _PyObject_CallMethodOneArg(file, &_Py_ID(write), s);
- Py_DECREF(s);
- return res;
- }
- /*[clinic input]
- marshal.load
- file: object
- Must be readable binary file.
- /
- Read one value from the open file and return it.
- If no valid value is read (e.g. because the data has a different Python
- version's incompatible marshal format), raise EOFError, ValueError or
- TypeError.
- Note: If an object containing an unsupported type was marshalled with
- dump(), load() will substitute None for the unmarshallable type.
- [clinic start generated code]*/
- static PyObject *
- marshal_load(PyObject *module, PyObject *file)
- /*[clinic end generated code: output=f8e5c33233566344 input=c85c2b594cd8124a]*/
- {
- PyObject *data, *result;
- RFILE rf;
- /*
- * Make a call to the read method, but read zero bytes.
- * This is to ensure that the object passed in at least
- * has a read method which returns bytes.
- * This can be removed if we guarantee good error handling
- * for r_string()
- */
- data = _PyObject_CallMethod(file, &_Py_ID(read), "i", 0);
- if (data == NULL)
- return NULL;
- if (!PyBytes_Check(data)) {
- PyErr_Format(PyExc_TypeError,
- "file.read() returned not bytes but %.100s",
- Py_TYPE(data)->tp_name);
- result = NULL;
- }
- else {
- rf.depth = 0;
- rf.fp = NULL;
- rf.readable = file;
- rf.ptr = rf.end = NULL;
- rf.buf = NULL;
- if ((rf.refs = PyList_New(0)) != NULL) {
- result = read_object(&rf);
- Py_DECREF(rf.refs);
- if (rf.buf != NULL)
- PyMem_Free(rf.buf);
- } else
- result = NULL;
- }
- Py_DECREF(data);
- return result;
- }
- /*[clinic input]
- marshal.dumps
- value: object
- Must be a supported type.
- version: int(c_default="Py_MARSHAL_VERSION") = version
- Indicates the data format that dumps should use.
- /
- Return the bytes object that would be written to a file by dump(value, file).
- Raise a ValueError exception if value has (or contains an object that has) an
- unsupported type.
- [clinic start generated code]*/
- static PyObject *
- marshal_dumps_impl(PyObject *module, PyObject *value, int version)
- /*[clinic end generated code: output=9c200f98d7256cad input=a2139ea8608e9b27]*/
- {
- return PyMarshal_WriteObjectToString(value, version);
- }
- /*[clinic input]
- marshal.loads
- bytes: Py_buffer
- /
- Convert the bytes-like object to a value.
- If no valid value is found, raise EOFError, ValueError or TypeError. Extra
- bytes in the input are ignored.
- [clinic start generated code]*/
- static PyObject *
- marshal_loads_impl(PyObject *module, Py_buffer *bytes)
- /*[clinic end generated code: output=9fc65985c93d1bb1 input=6f426518459c8495]*/
- {
- RFILE rf;
- char *s = bytes->buf;
- Py_ssize_t n = bytes->len;
- PyObject* result;
- rf.fp = NULL;
- rf.readable = NULL;
- rf.ptr = s;
- rf.end = s + n;
- rf.depth = 0;
- if ((rf.refs = PyList_New(0)) == NULL)
- return NULL;
- result = read_object(&rf);
- Py_DECREF(rf.refs);
- return result;
- }
- static PyMethodDef marshal_methods[] = {
- MARSHAL_DUMP_METHODDEF
- MARSHAL_LOAD_METHODDEF
- MARSHAL_DUMPS_METHODDEF
- MARSHAL_LOADS_METHODDEF
- {NULL, NULL} /* sentinel */
- };
- PyDoc_STRVAR(module_doc,
- "This module contains functions that can read and write Python values in\n\
- a binary format. The format is specific to Python, but independent of\n\
- machine architecture issues.\n\
- \n\
- Not all Python object types are supported; in general, only objects\n\
- whose value is independent from a particular invocation of Python can be\n\
- written and read by this module. The following types are supported:\n\
- None, integers, floating-point numbers, strings, bytes, bytearrays,\n\
- tuples, lists, sets, dictionaries, and code objects, where it\n\
- should be understood that tuples, lists and dictionaries are only\n\
- supported as long as the values contained therein are themselves\n\
- supported; and recursive lists and dictionaries should not be written\n\
- (they will cause infinite loops).\n\
- \n\
- Variables:\n\
- \n\
- version -- indicates the format that the module uses. Version 0 is the\n\
- historical format, version 1 shares interned strings and version 2\n\
- uses a binary format for floating-point numbers.\n\
- Version 3 shares common object references (New in version 3.4).\n\
- \n\
- Functions:\n\
- \n\
- dump() -- write value to a file\n\
- load() -- read value from a file\n\
- dumps() -- marshal value as a bytes object\n\
- loads() -- read value from a bytes-like object");
- static int
- marshal_module_exec(PyObject *mod)
- {
- if (PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION) < 0) {
- return -1;
- }
- return 0;
- }
- static PyModuleDef_Slot marshalmodule_slots[] = {
- {Py_mod_exec, marshal_module_exec},
- {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
- {0, NULL}
- };
- static struct PyModuleDef marshalmodule = {
- PyModuleDef_HEAD_INIT,
- .m_name = "marshal",
- .m_doc = module_doc,
- .m_methods = marshal_methods,
- .m_slots = marshalmodule_slots,
- };
- PyMODINIT_FUNC
- PyMarshal_Init(void)
- {
- return PyModuleDef_Init(&marshalmodule);
- }
|