17db96d56Sopenharmony_ci/* pickle accelerator C extensor: _pickle module. 27db96d56Sopenharmony_ci * 37db96d56Sopenharmony_ci * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows 47db96d56Sopenharmony_ci * and as an extension module (Py_BUILD_CORE_MODULE define) on other 57db96d56Sopenharmony_ci * platforms. */ 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 87db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 97db96d56Sopenharmony_ci#endif 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci#include "Python.h" 127db96d56Sopenharmony_ci#include "pycore_ceval.h" // _Py_EnterRecursiveCall() 137db96d56Sopenharmony_ci#include "pycore_moduleobject.h" // _PyModule_GetState() 147db96d56Sopenharmony_ci#include "pycore_runtime.h" // _Py_ID() 157db96d56Sopenharmony_ci#include "pycore_pystate.h" // _PyThreadState_GET() 167db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci#include <stdlib.h> // strtol() 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ciPyDoc_STRVAR(pickle_module_doc, 217db96d56Sopenharmony_ci"Optimized C implementation for the Python pickle module."); 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci/*[clinic input] 247db96d56Sopenharmony_cimodule _pickle 257db96d56Sopenharmony_ciclass _pickle.Pickler "PicklerObject *" "&Pickler_Type" 267db96d56Sopenharmony_ciclass _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" "&PicklerMemoProxyType" 277db96d56Sopenharmony_ciclass _pickle.Unpickler "UnpicklerObject *" "&Unpickler_Type" 287db96d56Sopenharmony_ciclass _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" "&UnpicklerMemoProxyType" 297db96d56Sopenharmony_ci[clinic start generated code]*/ 307db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b3e113468a58e6c]*/ 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci/* Bump HIGHEST_PROTOCOL when new opcodes are added to the pickle protocol. 337db96d56Sopenharmony_ci Bump DEFAULT_PROTOCOL only when the oldest still supported version of Python 347db96d56Sopenharmony_ci already includes it. */ 357db96d56Sopenharmony_cienum { 367db96d56Sopenharmony_ci HIGHEST_PROTOCOL = 5, 377db96d56Sopenharmony_ci DEFAULT_PROTOCOL = 4 387db96d56Sopenharmony_ci}; 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci#ifdef MS_WINDOWS 417db96d56Sopenharmony_ci// These are already typedefs from windows.h, pulled in via pycore_runtime.h. 427db96d56Sopenharmony_ci#define FLOAT FLOAT_ 437db96d56Sopenharmony_ci#define INT INT_ 447db96d56Sopenharmony_ci#define LONG LONG_ 457db96d56Sopenharmony_ci#endif 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci/* Pickle opcodes. These must be kept updated with pickle.py. 487db96d56Sopenharmony_ci Extensive docs are in pickletools.py. */ 497db96d56Sopenharmony_cienum opcode { 507db96d56Sopenharmony_ci MARK = '(', 517db96d56Sopenharmony_ci STOP = '.', 527db96d56Sopenharmony_ci POP = '0', 537db96d56Sopenharmony_ci POP_MARK = '1', 547db96d56Sopenharmony_ci DUP = '2', 557db96d56Sopenharmony_ci FLOAT = 'F', 567db96d56Sopenharmony_ci INT = 'I', 577db96d56Sopenharmony_ci BININT = 'J', 587db96d56Sopenharmony_ci BININT1 = 'K', 597db96d56Sopenharmony_ci LONG = 'L', 607db96d56Sopenharmony_ci BININT2 = 'M', 617db96d56Sopenharmony_ci NONE = 'N', 627db96d56Sopenharmony_ci PERSID = 'P', 637db96d56Sopenharmony_ci BINPERSID = 'Q', 647db96d56Sopenharmony_ci REDUCE = 'R', 657db96d56Sopenharmony_ci STRING = 'S', 667db96d56Sopenharmony_ci BINSTRING = 'T', 677db96d56Sopenharmony_ci SHORT_BINSTRING = 'U', 687db96d56Sopenharmony_ci UNICODE = 'V', 697db96d56Sopenharmony_ci BINUNICODE = 'X', 707db96d56Sopenharmony_ci APPEND = 'a', 717db96d56Sopenharmony_ci BUILD = 'b', 727db96d56Sopenharmony_ci GLOBAL = 'c', 737db96d56Sopenharmony_ci DICT = 'd', 747db96d56Sopenharmony_ci EMPTY_DICT = '}', 757db96d56Sopenharmony_ci APPENDS = 'e', 767db96d56Sopenharmony_ci GET = 'g', 777db96d56Sopenharmony_ci BINGET = 'h', 787db96d56Sopenharmony_ci INST = 'i', 797db96d56Sopenharmony_ci LONG_BINGET = 'j', 807db96d56Sopenharmony_ci LIST = 'l', 817db96d56Sopenharmony_ci EMPTY_LIST = ']', 827db96d56Sopenharmony_ci OBJ = 'o', 837db96d56Sopenharmony_ci PUT = 'p', 847db96d56Sopenharmony_ci BINPUT = 'q', 857db96d56Sopenharmony_ci LONG_BINPUT = 'r', 867db96d56Sopenharmony_ci SETITEM = 's', 877db96d56Sopenharmony_ci TUPLE = 't', 887db96d56Sopenharmony_ci EMPTY_TUPLE = ')', 897db96d56Sopenharmony_ci SETITEMS = 'u', 907db96d56Sopenharmony_ci BINFLOAT = 'G', 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci /* Protocol 2. */ 937db96d56Sopenharmony_ci PROTO = '\x80', 947db96d56Sopenharmony_ci NEWOBJ = '\x81', 957db96d56Sopenharmony_ci EXT1 = '\x82', 967db96d56Sopenharmony_ci EXT2 = '\x83', 977db96d56Sopenharmony_ci EXT4 = '\x84', 987db96d56Sopenharmony_ci TUPLE1 = '\x85', 997db96d56Sopenharmony_ci TUPLE2 = '\x86', 1007db96d56Sopenharmony_ci TUPLE3 = '\x87', 1017db96d56Sopenharmony_ci NEWTRUE = '\x88', 1027db96d56Sopenharmony_ci NEWFALSE = '\x89', 1037db96d56Sopenharmony_ci LONG1 = '\x8a', 1047db96d56Sopenharmony_ci LONG4 = '\x8b', 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci /* Protocol 3 (Python 3.x) */ 1077db96d56Sopenharmony_ci BINBYTES = 'B', 1087db96d56Sopenharmony_ci SHORT_BINBYTES = 'C', 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci /* Protocol 4 */ 1117db96d56Sopenharmony_ci SHORT_BINUNICODE = '\x8c', 1127db96d56Sopenharmony_ci BINUNICODE8 = '\x8d', 1137db96d56Sopenharmony_ci BINBYTES8 = '\x8e', 1147db96d56Sopenharmony_ci EMPTY_SET = '\x8f', 1157db96d56Sopenharmony_ci ADDITEMS = '\x90', 1167db96d56Sopenharmony_ci FROZENSET = '\x91', 1177db96d56Sopenharmony_ci NEWOBJ_EX = '\x92', 1187db96d56Sopenharmony_ci STACK_GLOBAL = '\x93', 1197db96d56Sopenharmony_ci MEMOIZE = '\x94', 1207db96d56Sopenharmony_ci FRAME = '\x95', 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci /* Protocol 5 */ 1237db96d56Sopenharmony_ci BYTEARRAY8 = '\x96', 1247db96d56Sopenharmony_ci NEXT_BUFFER = '\x97', 1257db96d56Sopenharmony_ci READONLY_BUFFER = '\x98' 1267db96d56Sopenharmony_ci}; 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_cienum { 1297db96d56Sopenharmony_ci /* Keep in synch with pickle.Pickler._BATCHSIZE. This is how many elements 1307db96d56Sopenharmony_ci batch_list/dict() pumps out before doing APPENDS/SETITEMS. Nothing will 1317db96d56Sopenharmony_ci break if this gets out of synch with pickle.py, but it's unclear that would 1327db96d56Sopenharmony_ci help anything either. */ 1337db96d56Sopenharmony_ci BATCHSIZE = 1000, 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci /* Nesting limit until Pickler, when running in "fast mode", starts 1367db96d56Sopenharmony_ci checking for self-referential data-structures. */ 1377db96d56Sopenharmony_ci FAST_NESTING_LIMIT = 50, 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci /* Initial size of the write buffer of Pickler. */ 1407db96d56Sopenharmony_ci WRITE_BUF_SIZE = 4096, 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci /* Prefetch size when unpickling (disabled on unpeekable streams) */ 1437db96d56Sopenharmony_ci PREFETCH = 8192 * 16, 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci FRAME_SIZE_MIN = 4, 1467db96d56Sopenharmony_ci FRAME_SIZE_TARGET = 64 * 1024, 1477db96d56Sopenharmony_ci FRAME_HEADER_SIZE = 9 1487db96d56Sopenharmony_ci}; 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci/*************************************************************************/ 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci/* State of the pickle module, per PEP 3121. */ 1537db96d56Sopenharmony_citypedef struct { 1547db96d56Sopenharmony_ci /* Exception classes for pickle. */ 1557db96d56Sopenharmony_ci PyObject *PickleError; 1567db96d56Sopenharmony_ci PyObject *PicklingError; 1577db96d56Sopenharmony_ci PyObject *UnpicklingError; 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci /* copyreg.dispatch_table, {type_object: pickling_function} */ 1607db96d56Sopenharmony_ci PyObject *dispatch_table; 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci /* For the extension opcodes EXT1, EXT2 and EXT4. */ 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci /* copyreg._extension_registry, {(module_name, function_name): code} */ 1657db96d56Sopenharmony_ci PyObject *extension_registry; 1667db96d56Sopenharmony_ci /* copyreg._extension_cache, {code: object} */ 1677db96d56Sopenharmony_ci PyObject *extension_cache; 1687db96d56Sopenharmony_ci /* copyreg._inverted_registry, {code: (module_name, function_name)} */ 1697db96d56Sopenharmony_ci PyObject *inverted_registry; 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci /* Import mappings for compatibility with Python 2.x */ 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci /* _compat_pickle.NAME_MAPPING, 1747db96d56Sopenharmony_ci {(oldmodule, oldname): (newmodule, newname)} */ 1757db96d56Sopenharmony_ci PyObject *name_mapping_2to3; 1767db96d56Sopenharmony_ci /* _compat_pickle.IMPORT_MAPPING, {oldmodule: newmodule} */ 1777db96d56Sopenharmony_ci PyObject *import_mapping_2to3; 1787db96d56Sopenharmony_ci /* Same, but with REVERSE_NAME_MAPPING / REVERSE_IMPORT_MAPPING */ 1797db96d56Sopenharmony_ci PyObject *name_mapping_3to2; 1807db96d56Sopenharmony_ci PyObject *import_mapping_3to2; 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci /* codecs.encode, used for saving bytes in older protocols */ 1837db96d56Sopenharmony_ci PyObject *codecs_encode; 1847db96d56Sopenharmony_ci /* builtins.getattr, used for saving nested names with protocol < 4 */ 1857db96d56Sopenharmony_ci PyObject *getattr; 1867db96d56Sopenharmony_ci /* functools.partial, used for implementing __newobj_ex__ with protocols 1877db96d56Sopenharmony_ci 2 and 3 */ 1887db96d56Sopenharmony_ci PyObject *partial; 1897db96d56Sopenharmony_ci} PickleState; 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci/* Forward declaration of the _pickle module definition. */ 1927db96d56Sopenharmony_cistatic struct PyModuleDef _picklemodule; 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci/* Given a module object, get its per-module state. */ 1957db96d56Sopenharmony_cistatic PickleState * 1967db96d56Sopenharmony_ci_Pickle_GetState(PyObject *module) 1977db96d56Sopenharmony_ci{ 1987db96d56Sopenharmony_ci return (PickleState *)_PyModule_GetState(module); 1997db96d56Sopenharmony_ci} 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci/* Find the module instance imported in the currently running sub-interpreter 2027db96d56Sopenharmony_ci and get its state. */ 2037db96d56Sopenharmony_cistatic PickleState * 2047db96d56Sopenharmony_ci_Pickle_GetGlobalState(void) 2057db96d56Sopenharmony_ci{ 2067db96d56Sopenharmony_ci return _Pickle_GetState(PyState_FindModule(&_picklemodule)); 2077db96d56Sopenharmony_ci} 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci/* Clear the given pickle module state. */ 2107db96d56Sopenharmony_cistatic void 2117db96d56Sopenharmony_ci_Pickle_ClearState(PickleState *st) 2127db96d56Sopenharmony_ci{ 2137db96d56Sopenharmony_ci Py_CLEAR(st->PickleError); 2147db96d56Sopenharmony_ci Py_CLEAR(st->PicklingError); 2157db96d56Sopenharmony_ci Py_CLEAR(st->UnpicklingError); 2167db96d56Sopenharmony_ci Py_CLEAR(st->dispatch_table); 2177db96d56Sopenharmony_ci Py_CLEAR(st->extension_registry); 2187db96d56Sopenharmony_ci Py_CLEAR(st->extension_cache); 2197db96d56Sopenharmony_ci Py_CLEAR(st->inverted_registry); 2207db96d56Sopenharmony_ci Py_CLEAR(st->name_mapping_2to3); 2217db96d56Sopenharmony_ci Py_CLEAR(st->import_mapping_2to3); 2227db96d56Sopenharmony_ci Py_CLEAR(st->name_mapping_3to2); 2237db96d56Sopenharmony_ci Py_CLEAR(st->import_mapping_3to2); 2247db96d56Sopenharmony_ci Py_CLEAR(st->codecs_encode); 2257db96d56Sopenharmony_ci Py_CLEAR(st->getattr); 2267db96d56Sopenharmony_ci Py_CLEAR(st->partial); 2277db96d56Sopenharmony_ci} 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci/* Initialize the given pickle module state. */ 2307db96d56Sopenharmony_cistatic int 2317db96d56Sopenharmony_ci_Pickle_InitState(PickleState *st) 2327db96d56Sopenharmony_ci{ 2337db96d56Sopenharmony_ci PyObject *copyreg = NULL; 2347db96d56Sopenharmony_ci PyObject *compat_pickle = NULL; 2357db96d56Sopenharmony_ci PyObject *codecs = NULL; 2367db96d56Sopenharmony_ci PyObject *functools = NULL; 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci st->getattr = _PyEval_GetBuiltin(&_Py_ID(getattr)); 2397db96d56Sopenharmony_ci if (st->getattr == NULL) 2407db96d56Sopenharmony_ci goto error; 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci copyreg = PyImport_ImportModule("copyreg"); 2437db96d56Sopenharmony_ci if (!copyreg) 2447db96d56Sopenharmony_ci goto error; 2457db96d56Sopenharmony_ci st->dispatch_table = PyObject_GetAttrString(copyreg, "dispatch_table"); 2467db96d56Sopenharmony_ci if (!st->dispatch_table) 2477db96d56Sopenharmony_ci goto error; 2487db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->dispatch_table)) { 2497db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 2507db96d56Sopenharmony_ci "copyreg.dispatch_table should be a dict, not %.200s", 2517db96d56Sopenharmony_ci Py_TYPE(st->dispatch_table)->tp_name); 2527db96d56Sopenharmony_ci goto error; 2537db96d56Sopenharmony_ci } 2547db96d56Sopenharmony_ci st->extension_registry = \ 2557db96d56Sopenharmony_ci PyObject_GetAttrString(copyreg, "_extension_registry"); 2567db96d56Sopenharmony_ci if (!st->extension_registry) 2577db96d56Sopenharmony_ci goto error; 2587db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->extension_registry)) { 2597db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 2607db96d56Sopenharmony_ci "copyreg._extension_registry should be a dict, " 2617db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->extension_registry)->tp_name); 2627db96d56Sopenharmony_ci goto error; 2637db96d56Sopenharmony_ci } 2647db96d56Sopenharmony_ci st->inverted_registry = \ 2657db96d56Sopenharmony_ci PyObject_GetAttrString(copyreg, "_inverted_registry"); 2667db96d56Sopenharmony_ci if (!st->inverted_registry) 2677db96d56Sopenharmony_ci goto error; 2687db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->inverted_registry)) { 2697db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 2707db96d56Sopenharmony_ci "copyreg._inverted_registry should be a dict, " 2717db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->inverted_registry)->tp_name); 2727db96d56Sopenharmony_ci goto error; 2737db96d56Sopenharmony_ci } 2747db96d56Sopenharmony_ci st->extension_cache = PyObject_GetAttrString(copyreg, "_extension_cache"); 2757db96d56Sopenharmony_ci if (!st->extension_cache) 2767db96d56Sopenharmony_ci goto error; 2777db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->extension_cache)) { 2787db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 2797db96d56Sopenharmony_ci "copyreg._extension_cache should be a dict, " 2807db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->extension_cache)->tp_name); 2817db96d56Sopenharmony_ci goto error; 2827db96d56Sopenharmony_ci } 2837db96d56Sopenharmony_ci Py_CLEAR(copyreg); 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_ci /* Load the 2.x -> 3.x stdlib module mapping tables */ 2867db96d56Sopenharmony_ci compat_pickle = PyImport_ImportModule("_compat_pickle"); 2877db96d56Sopenharmony_ci if (!compat_pickle) 2887db96d56Sopenharmony_ci goto error; 2897db96d56Sopenharmony_ci st->name_mapping_2to3 = \ 2907db96d56Sopenharmony_ci PyObject_GetAttrString(compat_pickle, "NAME_MAPPING"); 2917db96d56Sopenharmony_ci if (!st->name_mapping_2to3) 2927db96d56Sopenharmony_ci goto error; 2937db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->name_mapping_2to3)) { 2947db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 2957db96d56Sopenharmony_ci "_compat_pickle.NAME_MAPPING should be a dict, not %.200s", 2967db96d56Sopenharmony_ci Py_TYPE(st->name_mapping_2to3)->tp_name); 2977db96d56Sopenharmony_ci goto error; 2987db96d56Sopenharmony_ci } 2997db96d56Sopenharmony_ci st->import_mapping_2to3 = \ 3007db96d56Sopenharmony_ci PyObject_GetAttrString(compat_pickle, "IMPORT_MAPPING"); 3017db96d56Sopenharmony_ci if (!st->import_mapping_2to3) 3027db96d56Sopenharmony_ci goto error; 3037db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->import_mapping_2to3)) { 3047db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 3057db96d56Sopenharmony_ci "_compat_pickle.IMPORT_MAPPING should be a dict, " 3067db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->import_mapping_2to3)->tp_name); 3077db96d56Sopenharmony_ci goto error; 3087db96d56Sopenharmony_ci } 3097db96d56Sopenharmony_ci /* ... and the 3.x -> 2.x mapping tables */ 3107db96d56Sopenharmony_ci st->name_mapping_3to2 = \ 3117db96d56Sopenharmony_ci PyObject_GetAttrString(compat_pickle, "REVERSE_NAME_MAPPING"); 3127db96d56Sopenharmony_ci if (!st->name_mapping_3to2) 3137db96d56Sopenharmony_ci goto error; 3147db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->name_mapping_3to2)) { 3157db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 3167db96d56Sopenharmony_ci "_compat_pickle.REVERSE_NAME_MAPPING should be a dict, " 3177db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->name_mapping_3to2)->tp_name); 3187db96d56Sopenharmony_ci goto error; 3197db96d56Sopenharmony_ci } 3207db96d56Sopenharmony_ci st->import_mapping_3to2 = \ 3217db96d56Sopenharmony_ci PyObject_GetAttrString(compat_pickle, "REVERSE_IMPORT_MAPPING"); 3227db96d56Sopenharmony_ci if (!st->import_mapping_3to2) 3237db96d56Sopenharmony_ci goto error; 3247db96d56Sopenharmony_ci if (!PyDict_CheckExact(st->import_mapping_3to2)) { 3257db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 3267db96d56Sopenharmony_ci "_compat_pickle.REVERSE_IMPORT_MAPPING should be a dict, " 3277db96d56Sopenharmony_ci "not %.200s", Py_TYPE(st->import_mapping_3to2)->tp_name); 3287db96d56Sopenharmony_ci goto error; 3297db96d56Sopenharmony_ci } 3307db96d56Sopenharmony_ci Py_CLEAR(compat_pickle); 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci codecs = PyImport_ImportModule("codecs"); 3337db96d56Sopenharmony_ci if (codecs == NULL) 3347db96d56Sopenharmony_ci goto error; 3357db96d56Sopenharmony_ci st->codecs_encode = PyObject_GetAttrString(codecs, "encode"); 3367db96d56Sopenharmony_ci if (st->codecs_encode == NULL) { 3377db96d56Sopenharmony_ci goto error; 3387db96d56Sopenharmony_ci } 3397db96d56Sopenharmony_ci if (!PyCallable_Check(st->codecs_encode)) { 3407db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 3417db96d56Sopenharmony_ci "codecs.encode should be a callable, not %.200s", 3427db96d56Sopenharmony_ci Py_TYPE(st->codecs_encode)->tp_name); 3437db96d56Sopenharmony_ci goto error; 3447db96d56Sopenharmony_ci } 3457db96d56Sopenharmony_ci Py_CLEAR(codecs); 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci functools = PyImport_ImportModule("functools"); 3487db96d56Sopenharmony_ci if (!functools) 3497db96d56Sopenharmony_ci goto error; 3507db96d56Sopenharmony_ci st->partial = PyObject_GetAttrString(functools, "partial"); 3517db96d56Sopenharmony_ci if (!st->partial) 3527db96d56Sopenharmony_ci goto error; 3537db96d56Sopenharmony_ci Py_CLEAR(functools); 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci return 0; 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_ci error: 3587db96d56Sopenharmony_ci Py_CLEAR(copyreg); 3597db96d56Sopenharmony_ci Py_CLEAR(compat_pickle); 3607db96d56Sopenharmony_ci Py_CLEAR(codecs); 3617db96d56Sopenharmony_ci Py_CLEAR(functools); 3627db96d56Sopenharmony_ci _Pickle_ClearState(st); 3637db96d56Sopenharmony_ci return -1; 3647db96d56Sopenharmony_ci} 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci/* Helper for calling a function with a single argument quickly. 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci This function steals the reference of the given argument. */ 3697db96d56Sopenharmony_cistatic PyObject * 3707db96d56Sopenharmony_ci_Pickle_FastCall(PyObject *func, PyObject *obj) 3717db96d56Sopenharmony_ci{ 3727db96d56Sopenharmony_ci PyObject *result; 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci result = PyObject_CallOneArg(func, obj); 3757db96d56Sopenharmony_ci Py_DECREF(obj); 3767db96d56Sopenharmony_ci return result; 3777db96d56Sopenharmony_ci} 3787db96d56Sopenharmony_ci 3797db96d56Sopenharmony_ci/*************************************************************************/ 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ci/* Retrieve and deconstruct a method for avoiding a reference cycle 3827db96d56Sopenharmony_ci (pickler -> bound method of pickler -> pickler) */ 3837db96d56Sopenharmony_cistatic int 3847db96d56Sopenharmony_ciinit_method_ref(PyObject *self, PyObject *name, 3857db96d56Sopenharmony_ci PyObject **method_func, PyObject **method_self) 3867db96d56Sopenharmony_ci{ 3877db96d56Sopenharmony_ci PyObject *func, *func2; 3887db96d56Sopenharmony_ci int ret; 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci /* *method_func and *method_self should be consistent. All refcount decrements 3917db96d56Sopenharmony_ci should be occurred after setting *method_self and *method_func. */ 3927db96d56Sopenharmony_ci ret = _PyObject_LookupAttr(self, name, &func); 3937db96d56Sopenharmony_ci if (func == NULL) { 3947db96d56Sopenharmony_ci *method_self = NULL; 3957db96d56Sopenharmony_ci Py_CLEAR(*method_func); 3967db96d56Sopenharmony_ci return ret; 3977db96d56Sopenharmony_ci } 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) { 4007db96d56Sopenharmony_ci /* Deconstruct a bound Python method */ 4017db96d56Sopenharmony_ci func2 = PyMethod_GET_FUNCTION(func); 4027db96d56Sopenharmony_ci Py_INCREF(func2); 4037db96d56Sopenharmony_ci *method_self = self; /* borrowed */ 4047db96d56Sopenharmony_ci Py_XSETREF(*method_func, func2); 4057db96d56Sopenharmony_ci Py_DECREF(func); 4067db96d56Sopenharmony_ci return 0; 4077db96d56Sopenharmony_ci } 4087db96d56Sopenharmony_ci else { 4097db96d56Sopenharmony_ci *method_self = NULL; 4107db96d56Sopenharmony_ci Py_XSETREF(*method_func, func); 4117db96d56Sopenharmony_ci return 0; 4127db96d56Sopenharmony_ci } 4137db96d56Sopenharmony_ci} 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci/* Bind a method if it was deconstructed */ 4167db96d56Sopenharmony_cistatic PyObject * 4177db96d56Sopenharmony_cireconstruct_method(PyObject *func, PyObject *self) 4187db96d56Sopenharmony_ci{ 4197db96d56Sopenharmony_ci if (self) { 4207db96d56Sopenharmony_ci return PyMethod_New(func, self); 4217db96d56Sopenharmony_ci } 4227db96d56Sopenharmony_ci else { 4237db96d56Sopenharmony_ci Py_INCREF(func); 4247db96d56Sopenharmony_ci return func; 4257db96d56Sopenharmony_ci } 4267db96d56Sopenharmony_ci} 4277db96d56Sopenharmony_ci 4287db96d56Sopenharmony_cistatic PyObject * 4297db96d56Sopenharmony_cicall_method(PyObject *func, PyObject *self, PyObject *obj) 4307db96d56Sopenharmony_ci{ 4317db96d56Sopenharmony_ci if (self) { 4327db96d56Sopenharmony_ci return PyObject_CallFunctionObjArgs(func, self, obj, NULL); 4337db96d56Sopenharmony_ci } 4347db96d56Sopenharmony_ci else { 4357db96d56Sopenharmony_ci return PyObject_CallOneArg(func, obj); 4367db96d56Sopenharmony_ci } 4377db96d56Sopenharmony_ci} 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci/*************************************************************************/ 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci/* Internal data type used as the unpickling stack. */ 4427db96d56Sopenharmony_citypedef struct { 4437db96d56Sopenharmony_ci PyObject_VAR_HEAD 4447db96d56Sopenharmony_ci PyObject **data; 4457db96d56Sopenharmony_ci int mark_set; /* is MARK set? */ 4467db96d56Sopenharmony_ci Py_ssize_t fence; /* position of top MARK or 0 */ 4477db96d56Sopenharmony_ci Py_ssize_t allocated; /* number of slots in data allocated */ 4487db96d56Sopenharmony_ci} Pdata; 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_cistatic void 4517db96d56Sopenharmony_ciPdata_dealloc(Pdata *self) 4527db96d56Sopenharmony_ci{ 4537db96d56Sopenharmony_ci Py_ssize_t i = Py_SIZE(self); 4547db96d56Sopenharmony_ci while (--i >= 0) { 4557db96d56Sopenharmony_ci Py_DECREF(self->data[i]); 4567db96d56Sopenharmony_ci } 4577db96d56Sopenharmony_ci PyMem_Free(self->data); 4587db96d56Sopenharmony_ci PyObject_Free(self); 4597db96d56Sopenharmony_ci} 4607db96d56Sopenharmony_ci 4617db96d56Sopenharmony_cistatic PyTypeObject Pdata_Type = { 4627db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 4637db96d56Sopenharmony_ci "_pickle.Pdata", /*tp_name*/ 4647db96d56Sopenharmony_ci sizeof(Pdata), /*tp_basicsize*/ 4657db96d56Sopenharmony_ci sizeof(PyObject *), /*tp_itemsize*/ 4667db96d56Sopenharmony_ci (destructor)Pdata_dealloc, /*tp_dealloc*/ 4677db96d56Sopenharmony_ci}; 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_cistatic PyObject * 4707db96d56Sopenharmony_ciPdata_New(void) 4717db96d56Sopenharmony_ci{ 4727db96d56Sopenharmony_ci Pdata *self; 4737db96d56Sopenharmony_ci 4747db96d56Sopenharmony_ci if (!(self = PyObject_New(Pdata, &Pdata_Type))) 4757db96d56Sopenharmony_ci return NULL; 4767db96d56Sopenharmony_ci Py_SET_SIZE(self, 0); 4777db96d56Sopenharmony_ci self->mark_set = 0; 4787db96d56Sopenharmony_ci self->fence = 0; 4797db96d56Sopenharmony_ci self->allocated = 8; 4807db96d56Sopenharmony_ci self->data = PyMem_Malloc(self->allocated * sizeof(PyObject *)); 4817db96d56Sopenharmony_ci if (self->data) 4827db96d56Sopenharmony_ci return (PyObject *)self; 4837db96d56Sopenharmony_ci Py_DECREF(self); 4847db96d56Sopenharmony_ci return PyErr_NoMemory(); 4857db96d56Sopenharmony_ci} 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci/* Retain only the initial clearto items. If clearto >= the current 4897db96d56Sopenharmony_ci * number of items, this is a (non-erroneous) NOP. 4907db96d56Sopenharmony_ci */ 4917db96d56Sopenharmony_cistatic int 4927db96d56Sopenharmony_ciPdata_clear(Pdata *self, Py_ssize_t clearto) 4937db96d56Sopenharmony_ci{ 4947db96d56Sopenharmony_ci Py_ssize_t i = Py_SIZE(self); 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_ci assert(clearto >= self->fence); 4977db96d56Sopenharmony_ci if (clearto >= i) 4987db96d56Sopenharmony_ci return 0; 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ci while (--i >= clearto) { 5017db96d56Sopenharmony_ci Py_CLEAR(self->data[i]); 5027db96d56Sopenharmony_ci } 5037db96d56Sopenharmony_ci Py_SET_SIZE(self, clearto); 5047db96d56Sopenharmony_ci return 0; 5057db96d56Sopenharmony_ci} 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_cistatic int 5087db96d56Sopenharmony_ciPdata_grow(Pdata *self) 5097db96d56Sopenharmony_ci{ 5107db96d56Sopenharmony_ci PyObject **data = self->data; 5117db96d56Sopenharmony_ci size_t allocated = (size_t)self->allocated; 5127db96d56Sopenharmony_ci size_t new_allocated; 5137db96d56Sopenharmony_ci 5147db96d56Sopenharmony_ci new_allocated = (allocated >> 3) + 6; 5157db96d56Sopenharmony_ci /* check for integer overflow */ 5167db96d56Sopenharmony_ci if (new_allocated > (size_t)PY_SSIZE_T_MAX - allocated) 5177db96d56Sopenharmony_ci goto nomemory; 5187db96d56Sopenharmony_ci new_allocated += allocated; 5197db96d56Sopenharmony_ci PyMem_RESIZE(data, PyObject *, new_allocated); 5207db96d56Sopenharmony_ci if (data == NULL) 5217db96d56Sopenharmony_ci goto nomemory; 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci self->data = data; 5247db96d56Sopenharmony_ci self->allocated = (Py_ssize_t)new_allocated; 5257db96d56Sopenharmony_ci return 0; 5267db96d56Sopenharmony_ci 5277db96d56Sopenharmony_ci nomemory: 5287db96d56Sopenharmony_ci PyErr_NoMemory(); 5297db96d56Sopenharmony_ci return -1; 5307db96d56Sopenharmony_ci} 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_cistatic int 5337db96d56Sopenharmony_ciPdata_stack_underflow(Pdata *self) 5347db96d56Sopenharmony_ci{ 5357db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 5367db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 5377db96d56Sopenharmony_ci self->mark_set ? 5387db96d56Sopenharmony_ci "unexpected MARK found" : 5397db96d56Sopenharmony_ci "unpickling stack underflow"); 5407db96d56Sopenharmony_ci return -1; 5417db96d56Sopenharmony_ci} 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci/* D is a Pdata*. Pop the topmost element and store it into V, which 5447db96d56Sopenharmony_ci * must be an lvalue holding PyObject*. On stack underflow, UnpicklingError 5457db96d56Sopenharmony_ci * is raised and V is set to NULL. 5467db96d56Sopenharmony_ci */ 5477db96d56Sopenharmony_cistatic PyObject * 5487db96d56Sopenharmony_ciPdata_pop(Pdata *self) 5497db96d56Sopenharmony_ci{ 5507db96d56Sopenharmony_ci if (Py_SIZE(self) <= self->fence) { 5517db96d56Sopenharmony_ci Pdata_stack_underflow(self); 5527db96d56Sopenharmony_ci return NULL; 5537db96d56Sopenharmony_ci } 5547db96d56Sopenharmony_ci Py_SET_SIZE(self, Py_SIZE(self) - 1); 5557db96d56Sopenharmony_ci return self->data[Py_SIZE(self)]; 5567db96d56Sopenharmony_ci} 5577db96d56Sopenharmony_ci#define PDATA_POP(D, V) do { (V) = Pdata_pop((D)); } while (0) 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_cistatic int 5607db96d56Sopenharmony_ciPdata_push(Pdata *self, PyObject *obj) 5617db96d56Sopenharmony_ci{ 5627db96d56Sopenharmony_ci if (Py_SIZE(self) == self->allocated && Pdata_grow(self) < 0) { 5637db96d56Sopenharmony_ci return -1; 5647db96d56Sopenharmony_ci } 5657db96d56Sopenharmony_ci self->data[Py_SIZE(self)] = obj; 5667db96d56Sopenharmony_ci Py_SET_SIZE(self, Py_SIZE(self) + 1); 5677db96d56Sopenharmony_ci return 0; 5687db96d56Sopenharmony_ci} 5697db96d56Sopenharmony_ci 5707db96d56Sopenharmony_ci/* Push an object on stack, transferring its ownership to the stack. */ 5717db96d56Sopenharmony_ci#define PDATA_PUSH(D, O, ER) do { \ 5727db96d56Sopenharmony_ci if (Pdata_push((D), (O)) < 0) return (ER); } while(0) 5737db96d56Sopenharmony_ci 5747db96d56Sopenharmony_ci/* Push an object on stack, adding a new reference to the object. */ 5757db96d56Sopenharmony_ci#define PDATA_APPEND(D, O, ER) do { \ 5767db96d56Sopenharmony_ci Py_INCREF((O)); \ 5777db96d56Sopenharmony_ci if (Pdata_push((D), (O)) < 0) return (ER); } while(0) 5787db96d56Sopenharmony_ci 5797db96d56Sopenharmony_cistatic PyObject * 5807db96d56Sopenharmony_ciPdata_poptuple(Pdata *self, Py_ssize_t start) 5817db96d56Sopenharmony_ci{ 5827db96d56Sopenharmony_ci PyObject *tuple; 5837db96d56Sopenharmony_ci Py_ssize_t len, i, j; 5847db96d56Sopenharmony_ci 5857db96d56Sopenharmony_ci if (start < self->fence) { 5867db96d56Sopenharmony_ci Pdata_stack_underflow(self); 5877db96d56Sopenharmony_ci return NULL; 5887db96d56Sopenharmony_ci } 5897db96d56Sopenharmony_ci len = Py_SIZE(self) - start; 5907db96d56Sopenharmony_ci tuple = PyTuple_New(len); 5917db96d56Sopenharmony_ci if (tuple == NULL) 5927db96d56Sopenharmony_ci return NULL; 5937db96d56Sopenharmony_ci for (i = start, j = 0; j < len; i++, j++) 5947db96d56Sopenharmony_ci PyTuple_SET_ITEM(tuple, j, self->data[i]); 5957db96d56Sopenharmony_ci 5967db96d56Sopenharmony_ci Py_SET_SIZE(self, start); 5977db96d56Sopenharmony_ci return tuple; 5987db96d56Sopenharmony_ci} 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_cistatic PyObject * 6017db96d56Sopenharmony_ciPdata_poplist(Pdata *self, Py_ssize_t start) 6027db96d56Sopenharmony_ci{ 6037db96d56Sopenharmony_ci PyObject *list; 6047db96d56Sopenharmony_ci Py_ssize_t len, i, j; 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci len = Py_SIZE(self) - start; 6077db96d56Sopenharmony_ci list = PyList_New(len); 6087db96d56Sopenharmony_ci if (list == NULL) 6097db96d56Sopenharmony_ci return NULL; 6107db96d56Sopenharmony_ci for (i = start, j = 0; j < len; i++, j++) 6117db96d56Sopenharmony_ci PyList_SET_ITEM(list, j, self->data[i]); 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci Py_SET_SIZE(self, start); 6147db96d56Sopenharmony_ci return list; 6157db96d56Sopenharmony_ci} 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_citypedef struct { 6187db96d56Sopenharmony_ci PyObject *me_key; 6197db96d56Sopenharmony_ci Py_ssize_t me_value; 6207db96d56Sopenharmony_ci} PyMemoEntry; 6217db96d56Sopenharmony_ci 6227db96d56Sopenharmony_citypedef struct { 6237db96d56Sopenharmony_ci size_t mt_mask; 6247db96d56Sopenharmony_ci size_t mt_used; 6257db96d56Sopenharmony_ci size_t mt_allocated; 6267db96d56Sopenharmony_ci PyMemoEntry *mt_table; 6277db96d56Sopenharmony_ci} PyMemoTable; 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_citypedef struct PicklerObject { 6307db96d56Sopenharmony_ci PyObject_HEAD 6317db96d56Sopenharmony_ci PyMemoTable *memo; /* Memo table, keep track of the seen 6327db96d56Sopenharmony_ci objects to support self-referential objects 6337db96d56Sopenharmony_ci pickling. */ 6347db96d56Sopenharmony_ci PyObject *pers_func; /* persistent_id() method, can be NULL */ 6357db96d56Sopenharmony_ci PyObject *pers_func_self; /* borrowed reference to self if pers_func 6367db96d56Sopenharmony_ci is an unbound method, NULL otherwise */ 6377db96d56Sopenharmony_ci PyObject *dispatch_table; /* private dispatch_table, can be NULL */ 6387db96d56Sopenharmony_ci PyObject *reducer_override; /* hook for invoking user-defined callbacks 6397db96d56Sopenharmony_ci instead of save_global when pickling 6407db96d56Sopenharmony_ci functions and classes*/ 6417db96d56Sopenharmony_ci 6427db96d56Sopenharmony_ci PyObject *write; /* write() method of the output stream. */ 6437db96d56Sopenharmony_ci PyObject *output_buffer; /* Write into a local bytearray buffer before 6447db96d56Sopenharmony_ci flushing to the stream. */ 6457db96d56Sopenharmony_ci Py_ssize_t output_len; /* Length of output_buffer. */ 6467db96d56Sopenharmony_ci Py_ssize_t max_output_len; /* Allocation size of output_buffer. */ 6477db96d56Sopenharmony_ci int proto; /* Pickle protocol number, >= 0 */ 6487db96d56Sopenharmony_ci int bin; /* Boolean, true if proto > 0 */ 6497db96d56Sopenharmony_ci int framing; /* True when framing is enabled, proto >= 4 */ 6507db96d56Sopenharmony_ci Py_ssize_t frame_start; /* Position in output_buffer where the 6517db96d56Sopenharmony_ci current frame begins. -1 if there 6527db96d56Sopenharmony_ci is no frame currently open. */ 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci Py_ssize_t buf_size; /* Size of the current buffered pickle data */ 6557db96d56Sopenharmony_ci int fast; /* Enable fast mode if set to a true value. 6567db96d56Sopenharmony_ci The fast mode disable the usage of memo, 6577db96d56Sopenharmony_ci therefore speeding the pickling process by 6587db96d56Sopenharmony_ci not generating superfluous PUT opcodes. It 6597db96d56Sopenharmony_ci should not be used if with self-referential 6607db96d56Sopenharmony_ci objects. */ 6617db96d56Sopenharmony_ci int fast_nesting; 6627db96d56Sopenharmony_ci int fix_imports; /* Indicate whether Pickler should fix 6637db96d56Sopenharmony_ci the name of globals for Python 2.x. */ 6647db96d56Sopenharmony_ci PyObject *fast_memo; 6657db96d56Sopenharmony_ci PyObject *buffer_callback; /* Callback for out-of-band buffers, or NULL */ 6667db96d56Sopenharmony_ci} PicklerObject; 6677db96d56Sopenharmony_ci 6687db96d56Sopenharmony_citypedef struct UnpicklerObject { 6697db96d56Sopenharmony_ci PyObject_HEAD 6707db96d56Sopenharmony_ci Pdata *stack; /* Pickle data stack, store unpickled objects. */ 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci /* The unpickler memo is just an array of PyObject *s. Using a dict 6737db96d56Sopenharmony_ci is unnecessary, since the keys are contiguous ints. */ 6747db96d56Sopenharmony_ci PyObject **memo; 6757db96d56Sopenharmony_ci size_t memo_size; /* Capacity of the memo array */ 6767db96d56Sopenharmony_ci size_t memo_len; /* Number of objects in the memo */ 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ci PyObject *pers_func; /* persistent_load() method, can be NULL. */ 6797db96d56Sopenharmony_ci PyObject *pers_func_self; /* borrowed reference to self if pers_func 6807db96d56Sopenharmony_ci is an unbound method, NULL otherwise */ 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci Py_buffer buffer; 6837db96d56Sopenharmony_ci char *input_buffer; 6847db96d56Sopenharmony_ci char *input_line; 6857db96d56Sopenharmony_ci Py_ssize_t input_len; 6867db96d56Sopenharmony_ci Py_ssize_t next_read_idx; 6877db96d56Sopenharmony_ci Py_ssize_t prefetched_idx; /* index of first prefetched byte */ 6887db96d56Sopenharmony_ci 6897db96d56Sopenharmony_ci PyObject *read; /* read() method of the input stream. */ 6907db96d56Sopenharmony_ci PyObject *readinto; /* readinto() method of the input stream. */ 6917db96d56Sopenharmony_ci PyObject *readline; /* readline() method of the input stream. */ 6927db96d56Sopenharmony_ci PyObject *peek; /* peek() method of the input stream, or NULL */ 6937db96d56Sopenharmony_ci PyObject *buffers; /* iterable of out-of-band buffers, or NULL */ 6947db96d56Sopenharmony_ci 6957db96d56Sopenharmony_ci char *encoding; /* Name of the encoding to be used for 6967db96d56Sopenharmony_ci decoding strings pickled using Python 6977db96d56Sopenharmony_ci 2.x. The default value is "ASCII" */ 6987db96d56Sopenharmony_ci char *errors; /* Name of errors handling scheme to used when 6997db96d56Sopenharmony_ci decoding strings. The default value is 7007db96d56Sopenharmony_ci "strict". */ 7017db96d56Sopenharmony_ci Py_ssize_t *marks; /* Mark stack, used for unpickling container 7027db96d56Sopenharmony_ci objects. */ 7037db96d56Sopenharmony_ci Py_ssize_t num_marks; /* Number of marks in the mark stack. */ 7047db96d56Sopenharmony_ci Py_ssize_t marks_size; /* Current allocated size of the mark stack. */ 7057db96d56Sopenharmony_ci int proto; /* Protocol of the pickle loaded. */ 7067db96d56Sopenharmony_ci int fix_imports; /* Indicate whether Unpickler should fix 7077db96d56Sopenharmony_ci the name of globals pickled by Python 2.x. */ 7087db96d56Sopenharmony_ci} UnpicklerObject; 7097db96d56Sopenharmony_ci 7107db96d56Sopenharmony_citypedef struct { 7117db96d56Sopenharmony_ci PyObject_HEAD 7127db96d56Sopenharmony_ci PicklerObject *pickler; /* Pickler whose memo table we're proxying. */ 7137db96d56Sopenharmony_ci} PicklerMemoProxyObject; 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_citypedef struct { 7167db96d56Sopenharmony_ci PyObject_HEAD 7177db96d56Sopenharmony_ci UnpicklerObject *unpickler; 7187db96d56Sopenharmony_ci} UnpicklerMemoProxyObject; 7197db96d56Sopenharmony_ci 7207db96d56Sopenharmony_ci/* Forward declarations */ 7217db96d56Sopenharmony_cistatic int save(PicklerObject *, PyObject *, int); 7227db96d56Sopenharmony_cistatic int save_reduce(PicklerObject *, PyObject *, PyObject *); 7237db96d56Sopenharmony_cistatic PyTypeObject Pickler_Type; 7247db96d56Sopenharmony_cistatic PyTypeObject Unpickler_Type; 7257db96d56Sopenharmony_ci 7267db96d56Sopenharmony_ci#include "clinic/_pickle.c.h" 7277db96d56Sopenharmony_ci 7287db96d56Sopenharmony_ci/************************************************************************* 7297db96d56Sopenharmony_ci A custom hashtable mapping void* to Python ints. This is used by the pickler 7307db96d56Sopenharmony_ci for memoization. Using a custom hashtable rather than PyDict allows us to skip 7317db96d56Sopenharmony_ci a bunch of unnecessary object creation. This makes a huge performance 7327db96d56Sopenharmony_ci difference. */ 7337db96d56Sopenharmony_ci 7347db96d56Sopenharmony_ci#define MT_MINSIZE 8 7357db96d56Sopenharmony_ci#define PERTURB_SHIFT 5 7367db96d56Sopenharmony_ci 7377db96d56Sopenharmony_ci 7387db96d56Sopenharmony_cistatic PyMemoTable * 7397db96d56Sopenharmony_ciPyMemoTable_New(void) 7407db96d56Sopenharmony_ci{ 7417db96d56Sopenharmony_ci PyMemoTable *memo = PyMem_Malloc(sizeof(PyMemoTable)); 7427db96d56Sopenharmony_ci if (memo == NULL) { 7437db96d56Sopenharmony_ci PyErr_NoMemory(); 7447db96d56Sopenharmony_ci return NULL; 7457db96d56Sopenharmony_ci } 7467db96d56Sopenharmony_ci 7477db96d56Sopenharmony_ci memo->mt_used = 0; 7487db96d56Sopenharmony_ci memo->mt_allocated = MT_MINSIZE; 7497db96d56Sopenharmony_ci memo->mt_mask = MT_MINSIZE - 1; 7507db96d56Sopenharmony_ci memo->mt_table = PyMem_Malloc(MT_MINSIZE * sizeof(PyMemoEntry)); 7517db96d56Sopenharmony_ci if (memo->mt_table == NULL) { 7527db96d56Sopenharmony_ci PyMem_Free(memo); 7537db96d56Sopenharmony_ci PyErr_NoMemory(); 7547db96d56Sopenharmony_ci return NULL; 7557db96d56Sopenharmony_ci } 7567db96d56Sopenharmony_ci memset(memo->mt_table, 0, MT_MINSIZE * sizeof(PyMemoEntry)); 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci return memo; 7597db96d56Sopenharmony_ci} 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_cistatic PyMemoTable * 7627db96d56Sopenharmony_ciPyMemoTable_Copy(PyMemoTable *self) 7637db96d56Sopenharmony_ci{ 7647db96d56Sopenharmony_ci PyMemoTable *new = PyMemoTable_New(); 7657db96d56Sopenharmony_ci if (new == NULL) 7667db96d56Sopenharmony_ci return NULL; 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci new->mt_used = self->mt_used; 7697db96d56Sopenharmony_ci new->mt_allocated = self->mt_allocated; 7707db96d56Sopenharmony_ci new->mt_mask = self->mt_mask; 7717db96d56Sopenharmony_ci /* The table we get from _New() is probably smaller than we wanted. 7727db96d56Sopenharmony_ci Free it and allocate one that's the right size. */ 7737db96d56Sopenharmony_ci PyMem_Free(new->mt_table); 7747db96d56Sopenharmony_ci new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated); 7757db96d56Sopenharmony_ci if (new->mt_table == NULL) { 7767db96d56Sopenharmony_ci PyMem_Free(new); 7777db96d56Sopenharmony_ci PyErr_NoMemory(); 7787db96d56Sopenharmony_ci return NULL; 7797db96d56Sopenharmony_ci } 7807db96d56Sopenharmony_ci for (size_t i = 0; i < self->mt_allocated; i++) { 7817db96d56Sopenharmony_ci Py_XINCREF(self->mt_table[i].me_key); 7827db96d56Sopenharmony_ci } 7837db96d56Sopenharmony_ci memcpy(new->mt_table, self->mt_table, 7847db96d56Sopenharmony_ci sizeof(PyMemoEntry) * self->mt_allocated); 7857db96d56Sopenharmony_ci 7867db96d56Sopenharmony_ci return new; 7877db96d56Sopenharmony_ci} 7887db96d56Sopenharmony_ci 7897db96d56Sopenharmony_cistatic Py_ssize_t 7907db96d56Sopenharmony_ciPyMemoTable_Size(PyMemoTable *self) 7917db96d56Sopenharmony_ci{ 7927db96d56Sopenharmony_ci return self->mt_used; 7937db96d56Sopenharmony_ci} 7947db96d56Sopenharmony_ci 7957db96d56Sopenharmony_cistatic int 7967db96d56Sopenharmony_ciPyMemoTable_Clear(PyMemoTable *self) 7977db96d56Sopenharmony_ci{ 7987db96d56Sopenharmony_ci Py_ssize_t i = self->mt_allocated; 7997db96d56Sopenharmony_ci 8007db96d56Sopenharmony_ci while (--i >= 0) { 8017db96d56Sopenharmony_ci Py_XDECREF(self->mt_table[i].me_key); 8027db96d56Sopenharmony_ci } 8037db96d56Sopenharmony_ci self->mt_used = 0; 8047db96d56Sopenharmony_ci memset(self->mt_table, 0, self->mt_allocated * sizeof(PyMemoEntry)); 8057db96d56Sopenharmony_ci return 0; 8067db96d56Sopenharmony_ci} 8077db96d56Sopenharmony_ci 8087db96d56Sopenharmony_cistatic void 8097db96d56Sopenharmony_ciPyMemoTable_Del(PyMemoTable *self) 8107db96d56Sopenharmony_ci{ 8117db96d56Sopenharmony_ci if (self == NULL) 8127db96d56Sopenharmony_ci return; 8137db96d56Sopenharmony_ci PyMemoTable_Clear(self); 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci PyMem_Free(self->mt_table); 8167db96d56Sopenharmony_ci PyMem_Free(self); 8177db96d56Sopenharmony_ci} 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci/* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup() 8207db96d56Sopenharmony_ci can be considerably simpler than dictobject.c's lookdict(). */ 8217db96d56Sopenharmony_cistatic PyMemoEntry * 8227db96d56Sopenharmony_ci_PyMemoTable_Lookup(PyMemoTable *self, PyObject *key) 8237db96d56Sopenharmony_ci{ 8247db96d56Sopenharmony_ci size_t i; 8257db96d56Sopenharmony_ci size_t perturb; 8267db96d56Sopenharmony_ci size_t mask = self->mt_mask; 8277db96d56Sopenharmony_ci PyMemoEntry *table = self->mt_table; 8287db96d56Sopenharmony_ci PyMemoEntry *entry; 8297db96d56Sopenharmony_ci Py_hash_t hash = (Py_hash_t)key >> 3; 8307db96d56Sopenharmony_ci 8317db96d56Sopenharmony_ci i = hash & mask; 8327db96d56Sopenharmony_ci entry = &table[i]; 8337db96d56Sopenharmony_ci if (entry->me_key == NULL || entry->me_key == key) 8347db96d56Sopenharmony_ci return entry; 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { 8377db96d56Sopenharmony_ci i = (i << 2) + i + perturb + 1; 8387db96d56Sopenharmony_ci entry = &table[i & mask]; 8397db96d56Sopenharmony_ci if (entry->me_key == NULL || entry->me_key == key) 8407db96d56Sopenharmony_ci return entry; 8417db96d56Sopenharmony_ci } 8427db96d56Sopenharmony_ci Py_UNREACHABLE(); 8437db96d56Sopenharmony_ci} 8447db96d56Sopenharmony_ci 8457db96d56Sopenharmony_ci/* Returns -1 on failure, 0 on success. */ 8467db96d56Sopenharmony_cistatic int 8477db96d56Sopenharmony_ci_PyMemoTable_ResizeTable(PyMemoTable *self, size_t min_size) 8487db96d56Sopenharmony_ci{ 8497db96d56Sopenharmony_ci PyMemoEntry *oldtable = NULL; 8507db96d56Sopenharmony_ci PyMemoEntry *oldentry, *newentry; 8517db96d56Sopenharmony_ci size_t new_size = MT_MINSIZE; 8527db96d56Sopenharmony_ci size_t to_process; 8537db96d56Sopenharmony_ci 8547db96d56Sopenharmony_ci assert(min_size > 0); 8557db96d56Sopenharmony_ci 8567db96d56Sopenharmony_ci if (min_size > PY_SSIZE_T_MAX) { 8577db96d56Sopenharmony_ci PyErr_NoMemory(); 8587db96d56Sopenharmony_ci return -1; 8597db96d56Sopenharmony_ci } 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci /* Find the smallest valid table size >= min_size. */ 8627db96d56Sopenharmony_ci while (new_size < min_size) { 8637db96d56Sopenharmony_ci new_size <<= 1; 8647db96d56Sopenharmony_ci } 8657db96d56Sopenharmony_ci /* new_size needs to be a power of two. */ 8667db96d56Sopenharmony_ci assert((new_size & (new_size - 1)) == 0); 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci /* Allocate new table. */ 8697db96d56Sopenharmony_ci oldtable = self->mt_table; 8707db96d56Sopenharmony_ci self->mt_table = PyMem_NEW(PyMemoEntry, new_size); 8717db96d56Sopenharmony_ci if (self->mt_table == NULL) { 8727db96d56Sopenharmony_ci self->mt_table = oldtable; 8737db96d56Sopenharmony_ci PyErr_NoMemory(); 8747db96d56Sopenharmony_ci return -1; 8757db96d56Sopenharmony_ci } 8767db96d56Sopenharmony_ci self->mt_allocated = new_size; 8777db96d56Sopenharmony_ci self->mt_mask = new_size - 1; 8787db96d56Sopenharmony_ci memset(self->mt_table, 0, sizeof(PyMemoEntry) * new_size); 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_ci /* Copy entries from the old table. */ 8817db96d56Sopenharmony_ci to_process = self->mt_used; 8827db96d56Sopenharmony_ci for (oldentry = oldtable; to_process > 0; oldentry++) { 8837db96d56Sopenharmony_ci if (oldentry->me_key != NULL) { 8847db96d56Sopenharmony_ci to_process--; 8857db96d56Sopenharmony_ci /* newentry is a pointer to a chunk of the new 8867db96d56Sopenharmony_ci mt_table, so we're setting the key:value pair 8877db96d56Sopenharmony_ci in-place. */ 8887db96d56Sopenharmony_ci newentry = _PyMemoTable_Lookup(self, oldentry->me_key); 8897db96d56Sopenharmony_ci newentry->me_key = oldentry->me_key; 8907db96d56Sopenharmony_ci newentry->me_value = oldentry->me_value; 8917db96d56Sopenharmony_ci } 8927db96d56Sopenharmony_ci } 8937db96d56Sopenharmony_ci 8947db96d56Sopenharmony_ci /* Deallocate the old table. */ 8957db96d56Sopenharmony_ci PyMem_Free(oldtable); 8967db96d56Sopenharmony_ci return 0; 8977db96d56Sopenharmony_ci} 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ci/* Returns NULL on failure, a pointer to the value otherwise. */ 9007db96d56Sopenharmony_cistatic Py_ssize_t * 9017db96d56Sopenharmony_ciPyMemoTable_Get(PyMemoTable *self, PyObject *key) 9027db96d56Sopenharmony_ci{ 9037db96d56Sopenharmony_ci PyMemoEntry *entry = _PyMemoTable_Lookup(self, key); 9047db96d56Sopenharmony_ci if (entry->me_key == NULL) 9057db96d56Sopenharmony_ci return NULL; 9067db96d56Sopenharmony_ci return &entry->me_value; 9077db96d56Sopenharmony_ci} 9087db96d56Sopenharmony_ci 9097db96d56Sopenharmony_ci/* Returns -1 on failure, 0 on success. */ 9107db96d56Sopenharmony_cistatic int 9117db96d56Sopenharmony_ciPyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value) 9127db96d56Sopenharmony_ci{ 9137db96d56Sopenharmony_ci PyMemoEntry *entry; 9147db96d56Sopenharmony_ci 9157db96d56Sopenharmony_ci assert(key != NULL); 9167db96d56Sopenharmony_ci 9177db96d56Sopenharmony_ci entry = _PyMemoTable_Lookup(self, key); 9187db96d56Sopenharmony_ci if (entry->me_key != NULL) { 9197db96d56Sopenharmony_ci entry->me_value = value; 9207db96d56Sopenharmony_ci return 0; 9217db96d56Sopenharmony_ci } 9227db96d56Sopenharmony_ci Py_INCREF(key); 9237db96d56Sopenharmony_ci entry->me_key = key; 9247db96d56Sopenharmony_ci entry->me_value = value; 9257db96d56Sopenharmony_ci self->mt_used++; 9267db96d56Sopenharmony_ci 9277db96d56Sopenharmony_ci /* If we added a key, we can safely resize. Otherwise just return! 9287db96d56Sopenharmony_ci * If used >= 2/3 size, adjust size. Normally, this quaduples the size. 9297db96d56Sopenharmony_ci * 9307db96d56Sopenharmony_ci * Quadrupling the size improves average table sparseness 9317db96d56Sopenharmony_ci * (reducing collisions) at the cost of some memory. It also halves 9327db96d56Sopenharmony_ci * the number of expensive resize operations in a growing memo table. 9337db96d56Sopenharmony_ci * 9347db96d56Sopenharmony_ci * Very large memo tables (over 50K items) use doubling instead. 9357db96d56Sopenharmony_ci * This may help applications with severe memory constraints. 9367db96d56Sopenharmony_ci */ 9377db96d56Sopenharmony_ci if (SIZE_MAX / 3 >= self->mt_used && self->mt_used * 3 < self->mt_allocated * 2) { 9387db96d56Sopenharmony_ci return 0; 9397db96d56Sopenharmony_ci } 9407db96d56Sopenharmony_ci // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow. 9417db96d56Sopenharmony_ci size_t desired_size = (self->mt_used > 50000 ? 2 : 4) * self->mt_used; 9427db96d56Sopenharmony_ci return _PyMemoTable_ResizeTable(self, desired_size); 9437db96d56Sopenharmony_ci} 9447db96d56Sopenharmony_ci 9457db96d56Sopenharmony_ci#undef MT_MINSIZE 9467db96d56Sopenharmony_ci#undef PERTURB_SHIFT 9477db96d56Sopenharmony_ci 9487db96d56Sopenharmony_ci/*************************************************************************/ 9497db96d56Sopenharmony_ci 9507db96d56Sopenharmony_ci 9517db96d56Sopenharmony_cistatic int 9527db96d56Sopenharmony_ci_Pickler_ClearBuffer(PicklerObject *self) 9537db96d56Sopenharmony_ci{ 9547db96d56Sopenharmony_ci Py_XSETREF(self->output_buffer, 9557db96d56Sopenharmony_ci PyBytes_FromStringAndSize(NULL, self->max_output_len)); 9567db96d56Sopenharmony_ci if (self->output_buffer == NULL) 9577db96d56Sopenharmony_ci return -1; 9587db96d56Sopenharmony_ci self->output_len = 0; 9597db96d56Sopenharmony_ci self->frame_start = -1; 9607db96d56Sopenharmony_ci return 0; 9617db96d56Sopenharmony_ci} 9627db96d56Sopenharmony_ci 9637db96d56Sopenharmony_cistatic void 9647db96d56Sopenharmony_ci_write_size64(char *out, size_t value) 9657db96d56Sopenharmony_ci{ 9667db96d56Sopenharmony_ci size_t i; 9677db96d56Sopenharmony_ci 9687db96d56Sopenharmony_ci static_assert(sizeof(size_t) <= 8, "size_t is larger than 64-bit"); 9697db96d56Sopenharmony_ci 9707db96d56Sopenharmony_ci for (i = 0; i < sizeof(size_t); i++) { 9717db96d56Sopenharmony_ci out[i] = (unsigned char)((value >> (8 * i)) & 0xff); 9727db96d56Sopenharmony_ci } 9737db96d56Sopenharmony_ci for (i = sizeof(size_t); i < 8; i++) { 9747db96d56Sopenharmony_ci out[i] = 0; 9757db96d56Sopenharmony_ci } 9767db96d56Sopenharmony_ci} 9777db96d56Sopenharmony_ci 9787db96d56Sopenharmony_cistatic int 9797db96d56Sopenharmony_ci_Pickler_CommitFrame(PicklerObject *self) 9807db96d56Sopenharmony_ci{ 9817db96d56Sopenharmony_ci size_t frame_len; 9827db96d56Sopenharmony_ci char *qdata; 9837db96d56Sopenharmony_ci 9847db96d56Sopenharmony_ci if (!self->framing || self->frame_start == -1) 9857db96d56Sopenharmony_ci return 0; 9867db96d56Sopenharmony_ci frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE; 9877db96d56Sopenharmony_ci qdata = PyBytes_AS_STRING(self->output_buffer) + self->frame_start; 9887db96d56Sopenharmony_ci if (frame_len >= FRAME_SIZE_MIN) { 9897db96d56Sopenharmony_ci qdata[0] = FRAME; 9907db96d56Sopenharmony_ci _write_size64(qdata + 1, frame_len); 9917db96d56Sopenharmony_ci } 9927db96d56Sopenharmony_ci else { 9937db96d56Sopenharmony_ci memmove(qdata, qdata + FRAME_HEADER_SIZE, frame_len); 9947db96d56Sopenharmony_ci self->output_len -= FRAME_HEADER_SIZE; 9957db96d56Sopenharmony_ci } 9967db96d56Sopenharmony_ci self->frame_start = -1; 9977db96d56Sopenharmony_ci return 0; 9987db96d56Sopenharmony_ci} 9997db96d56Sopenharmony_ci 10007db96d56Sopenharmony_cistatic PyObject * 10017db96d56Sopenharmony_ci_Pickler_GetString(PicklerObject *self) 10027db96d56Sopenharmony_ci{ 10037db96d56Sopenharmony_ci PyObject *output_buffer = self->output_buffer; 10047db96d56Sopenharmony_ci 10057db96d56Sopenharmony_ci assert(self->output_buffer != NULL); 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci if (_Pickler_CommitFrame(self)) 10087db96d56Sopenharmony_ci return NULL; 10097db96d56Sopenharmony_ci 10107db96d56Sopenharmony_ci self->output_buffer = NULL; 10117db96d56Sopenharmony_ci /* Resize down to exact size */ 10127db96d56Sopenharmony_ci if (_PyBytes_Resize(&output_buffer, self->output_len) < 0) 10137db96d56Sopenharmony_ci return NULL; 10147db96d56Sopenharmony_ci return output_buffer; 10157db96d56Sopenharmony_ci} 10167db96d56Sopenharmony_ci 10177db96d56Sopenharmony_cistatic int 10187db96d56Sopenharmony_ci_Pickler_FlushToFile(PicklerObject *self) 10197db96d56Sopenharmony_ci{ 10207db96d56Sopenharmony_ci PyObject *output, *result; 10217db96d56Sopenharmony_ci 10227db96d56Sopenharmony_ci assert(self->write != NULL); 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci /* This will commit the frame first */ 10257db96d56Sopenharmony_ci output = _Pickler_GetString(self); 10267db96d56Sopenharmony_ci if (output == NULL) 10277db96d56Sopenharmony_ci return -1; 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ci result = _Pickle_FastCall(self->write, output); 10307db96d56Sopenharmony_ci Py_XDECREF(result); 10317db96d56Sopenharmony_ci return (result == NULL) ? -1 : 0; 10327db96d56Sopenharmony_ci} 10337db96d56Sopenharmony_ci 10347db96d56Sopenharmony_cistatic int 10357db96d56Sopenharmony_ci_Pickler_OpcodeBoundary(PicklerObject *self) 10367db96d56Sopenharmony_ci{ 10377db96d56Sopenharmony_ci Py_ssize_t frame_len; 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci if (!self->framing || self->frame_start == -1) { 10407db96d56Sopenharmony_ci return 0; 10417db96d56Sopenharmony_ci } 10427db96d56Sopenharmony_ci frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE; 10437db96d56Sopenharmony_ci if (frame_len >= FRAME_SIZE_TARGET) { 10447db96d56Sopenharmony_ci if(_Pickler_CommitFrame(self)) { 10457db96d56Sopenharmony_ci return -1; 10467db96d56Sopenharmony_ci } 10477db96d56Sopenharmony_ci /* Flush the content of the committed frame to the underlying 10487db96d56Sopenharmony_ci * file and reuse the pickler buffer for the next frame so as 10497db96d56Sopenharmony_ci * to limit memory usage when dumping large complex objects to 10507db96d56Sopenharmony_ci * a file. 10517db96d56Sopenharmony_ci * 10527db96d56Sopenharmony_ci * self->write is NULL when called via dumps. 10537db96d56Sopenharmony_ci */ 10547db96d56Sopenharmony_ci if (self->write != NULL) { 10557db96d56Sopenharmony_ci if (_Pickler_FlushToFile(self) < 0) { 10567db96d56Sopenharmony_ci return -1; 10577db96d56Sopenharmony_ci } 10587db96d56Sopenharmony_ci if (_Pickler_ClearBuffer(self) < 0) { 10597db96d56Sopenharmony_ci return -1; 10607db96d56Sopenharmony_ci } 10617db96d56Sopenharmony_ci } 10627db96d56Sopenharmony_ci } 10637db96d56Sopenharmony_ci return 0; 10647db96d56Sopenharmony_ci} 10657db96d56Sopenharmony_ci 10667db96d56Sopenharmony_cistatic Py_ssize_t 10677db96d56Sopenharmony_ci_Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len) 10687db96d56Sopenharmony_ci{ 10697db96d56Sopenharmony_ci Py_ssize_t i, n, required; 10707db96d56Sopenharmony_ci char *buffer; 10717db96d56Sopenharmony_ci int need_new_frame; 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci assert(s != NULL); 10747db96d56Sopenharmony_ci need_new_frame = (self->framing && self->frame_start == -1); 10757db96d56Sopenharmony_ci 10767db96d56Sopenharmony_ci if (need_new_frame) 10777db96d56Sopenharmony_ci n = data_len + FRAME_HEADER_SIZE; 10787db96d56Sopenharmony_ci else 10797db96d56Sopenharmony_ci n = data_len; 10807db96d56Sopenharmony_ci 10817db96d56Sopenharmony_ci required = self->output_len + n; 10827db96d56Sopenharmony_ci if (required > self->max_output_len) { 10837db96d56Sopenharmony_ci /* Make place in buffer for the pickle chunk */ 10847db96d56Sopenharmony_ci if (self->output_len >= PY_SSIZE_T_MAX / 2 - n) { 10857db96d56Sopenharmony_ci PyErr_NoMemory(); 10867db96d56Sopenharmony_ci return -1; 10877db96d56Sopenharmony_ci } 10887db96d56Sopenharmony_ci self->max_output_len = (self->output_len + n) / 2 * 3; 10897db96d56Sopenharmony_ci if (_PyBytes_Resize(&self->output_buffer, self->max_output_len) < 0) 10907db96d56Sopenharmony_ci return -1; 10917db96d56Sopenharmony_ci } 10927db96d56Sopenharmony_ci buffer = PyBytes_AS_STRING(self->output_buffer); 10937db96d56Sopenharmony_ci if (need_new_frame) { 10947db96d56Sopenharmony_ci /* Setup new frame */ 10957db96d56Sopenharmony_ci Py_ssize_t frame_start = self->output_len; 10967db96d56Sopenharmony_ci self->frame_start = frame_start; 10977db96d56Sopenharmony_ci for (i = 0; i < FRAME_HEADER_SIZE; i++) { 10987db96d56Sopenharmony_ci /* Write an invalid value, for debugging */ 10997db96d56Sopenharmony_ci buffer[frame_start + i] = 0xFE; 11007db96d56Sopenharmony_ci } 11017db96d56Sopenharmony_ci self->output_len += FRAME_HEADER_SIZE; 11027db96d56Sopenharmony_ci } 11037db96d56Sopenharmony_ci if (data_len < 8) { 11047db96d56Sopenharmony_ci /* This is faster than memcpy when the string is short. */ 11057db96d56Sopenharmony_ci for (i = 0; i < data_len; i++) { 11067db96d56Sopenharmony_ci buffer[self->output_len + i] = s[i]; 11077db96d56Sopenharmony_ci } 11087db96d56Sopenharmony_ci } 11097db96d56Sopenharmony_ci else { 11107db96d56Sopenharmony_ci memcpy(buffer + self->output_len, s, data_len); 11117db96d56Sopenharmony_ci } 11127db96d56Sopenharmony_ci self->output_len += data_len; 11137db96d56Sopenharmony_ci return data_len; 11147db96d56Sopenharmony_ci} 11157db96d56Sopenharmony_ci 11167db96d56Sopenharmony_cistatic PicklerObject * 11177db96d56Sopenharmony_ci_Pickler_New(void) 11187db96d56Sopenharmony_ci{ 11197db96d56Sopenharmony_ci PicklerObject *self; 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci self = PyObject_GC_New(PicklerObject, &Pickler_Type); 11227db96d56Sopenharmony_ci if (self == NULL) 11237db96d56Sopenharmony_ci return NULL; 11247db96d56Sopenharmony_ci 11257db96d56Sopenharmony_ci self->pers_func = NULL; 11267db96d56Sopenharmony_ci self->dispatch_table = NULL; 11277db96d56Sopenharmony_ci self->buffer_callback = NULL; 11287db96d56Sopenharmony_ci self->write = NULL; 11297db96d56Sopenharmony_ci self->proto = 0; 11307db96d56Sopenharmony_ci self->bin = 0; 11317db96d56Sopenharmony_ci self->framing = 0; 11327db96d56Sopenharmony_ci self->frame_start = -1; 11337db96d56Sopenharmony_ci self->fast = 0; 11347db96d56Sopenharmony_ci self->fast_nesting = 0; 11357db96d56Sopenharmony_ci self->fix_imports = 0; 11367db96d56Sopenharmony_ci self->fast_memo = NULL; 11377db96d56Sopenharmony_ci self->max_output_len = WRITE_BUF_SIZE; 11387db96d56Sopenharmony_ci self->output_len = 0; 11397db96d56Sopenharmony_ci self->reducer_override = NULL; 11407db96d56Sopenharmony_ci 11417db96d56Sopenharmony_ci self->memo = PyMemoTable_New(); 11427db96d56Sopenharmony_ci self->output_buffer = PyBytes_FromStringAndSize(NULL, 11437db96d56Sopenharmony_ci self->max_output_len); 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci if (self->memo == NULL || self->output_buffer == NULL) { 11467db96d56Sopenharmony_ci Py_DECREF(self); 11477db96d56Sopenharmony_ci return NULL; 11487db96d56Sopenharmony_ci } 11497db96d56Sopenharmony_ci 11507db96d56Sopenharmony_ci PyObject_GC_Track(self); 11517db96d56Sopenharmony_ci return self; 11527db96d56Sopenharmony_ci} 11537db96d56Sopenharmony_ci 11547db96d56Sopenharmony_cistatic int 11557db96d56Sopenharmony_ci_Pickler_SetProtocol(PicklerObject *self, PyObject *protocol, int fix_imports) 11567db96d56Sopenharmony_ci{ 11577db96d56Sopenharmony_ci long proto; 11587db96d56Sopenharmony_ci 11597db96d56Sopenharmony_ci if (protocol == Py_None) { 11607db96d56Sopenharmony_ci proto = DEFAULT_PROTOCOL; 11617db96d56Sopenharmony_ci } 11627db96d56Sopenharmony_ci else { 11637db96d56Sopenharmony_ci proto = PyLong_AsLong(protocol); 11647db96d56Sopenharmony_ci if (proto < 0) { 11657db96d56Sopenharmony_ci if (proto == -1 && PyErr_Occurred()) 11667db96d56Sopenharmony_ci return -1; 11677db96d56Sopenharmony_ci proto = HIGHEST_PROTOCOL; 11687db96d56Sopenharmony_ci } 11697db96d56Sopenharmony_ci else if (proto > HIGHEST_PROTOCOL) { 11707db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d", 11717db96d56Sopenharmony_ci HIGHEST_PROTOCOL); 11727db96d56Sopenharmony_ci return -1; 11737db96d56Sopenharmony_ci } 11747db96d56Sopenharmony_ci } 11757db96d56Sopenharmony_ci self->proto = (int)proto; 11767db96d56Sopenharmony_ci self->bin = proto > 0; 11777db96d56Sopenharmony_ci self->fix_imports = fix_imports && proto < 3; 11787db96d56Sopenharmony_ci return 0; 11797db96d56Sopenharmony_ci} 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may 11827db96d56Sopenharmony_ci be called once on a freshly created Pickler. */ 11837db96d56Sopenharmony_cistatic int 11847db96d56Sopenharmony_ci_Pickler_SetOutputStream(PicklerObject *self, PyObject *file) 11857db96d56Sopenharmony_ci{ 11867db96d56Sopenharmony_ci assert(file != NULL); 11877db96d56Sopenharmony_ci if (_PyObject_LookupAttr(file, &_Py_ID(write), &self->write) < 0) { 11887db96d56Sopenharmony_ci return -1; 11897db96d56Sopenharmony_ci } 11907db96d56Sopenharmony_ci if (self->write == NULL) { 11917db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 11927db96d56Sopenharmony_ci "file must have a 'write' attribute"); 11937db96d56Sopenharmony_ci return -1; 11947db96d56Sopenharmony_ci } 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci return 0; 11977db96d56Sopenharmony_ci} 11987db96d56Sopenharmony_ci 11997db96d56Sopenharmony_cistatic int 12007db96d56Sopenharmony_ci_Pickler_SetBufferCallback(PicklerObject *self, PyObject *buffer_callback) 12017db96d56Sopenharmony_ci{ 12027db96d56Sopenharmony_ci if (buffer_callback == Py_None) { 12037db96d56Sopenharmony_ci buffer_callback = NULL; 12047db96d56Sopenharmony_ci } 12057db96d56Sopenharmony_ci if (buffer_callback != NULL && self->proto < 5) { 12067db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 12077db96d56Sopenharmony_ci "buffer_callback needs protocol >= 5"); 12087db96d56Sopenharmony_ci return -1; 12097db96d56Sopenharmony_ci } 12107db96d56Sopenharmony_ci 12117db96d56Sopenharmony_ci Py_XINCREF(buffer_callback); 12127db96d56Sopenharmony_ci self->buffer_callback = buffer_callback; 12137db96d56Sopenharmony_ci return 0; 12147db96d56Sopenharmony_ci} 12157db96d56Sopenharmony_ci 12167db96d56Sopenharmony_ci/* Returns the size of the input on success, -1 on failure. This takes its 12177db96d56Sopenharmony_ci own reference to `input`. */ 12187db96d56Sopenharmony_cistatic Py_ssize_t 12197db96d56Sopenharmony_ci_Unpickler_SetStringInput(UnpicklerObject *self, PyObject *input) 12207db96d56Sopenharmony_ci{ 12217db96d56Sopenharmony_ci if (self->buffer.buf != NULL) 12227db96d56Sopenharmony_ci PyBuffer_Release(&self->buffer); 12237db96d56Sopenharmony_ci if (PyObject_GetBuffer(input, &self->buffer, PyBUF_CONTIG_RO) < 0) 12247db96d56Sopenharmony_ci return -1; 12257db96d56Sopenharmony_ci self->input_buffer = self->buffer.buf; 12267db96d56Sopenharmony_ci self->input_len = self->buffer.len; 12277db96d56Sopenharmony_ci self->next_read_idx = 0; 12287db96d56Sopenharmony_ci self->prefetched_idx = self->input_len; 12297db96d56Sopenharmony_ci return self->input_len; 12307db96d56Sopenharmony_ci} 12317db96d56Sopenharmony_ci 12327db96d56Sopenharmony_cistatic int 12337db96d56Sopenharmony_cibad_readline(void) 12347db96d56Sopenharmony_ci{ 12357db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 12367db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "pickle data was truncated"); 12377db96d56Sopenharmony_ci return -1; 12387db96d56Sopenharmony_ci} 12397db96d56Sopenharmony_ci 12407db96d56Sopenharmony_ci/* Skip any consumed data that was only prefetched using peek() */ 12417db96d56Sopenharmony_cistatic int 12427db96d56Sopenharmony_ci_Unpickler_SkipConsumed(UnpicklerObject *self) 12437db96d56Sopenharmony_ci{ 12447db96d56Sopenharmony_ci Py_ssize_t consumed; 12457db96d56Sopenharmony_ci PyObject *r; 12467db96d56Sopenharmony_ci 12477db96d56Sopenharmony_ci consumed = self->next_read_idx - self->prefetched_idx; 12487db96d56Sopenharmony_ci if (consumed <= 0) 12497db96d56Sopenharmony_ci return 0; 12507db96d56Sopenharmony_ci 12517db96d56Sopenharmony_ci assert(self->peek); /* otherwise we did something wrong */ 12527db96d56Sopenharmony_ci /* This makes a useless copy... */ 12537db96d56Sopenharmony_ci r = PyObject_CallFunction(self->read, "n", consumed); 12547db96d56Sopenharmony_ci if (r == NULL) 12557db96d56Sopenharmony_ci return -1; 12567db96d56Sopenharmony_ci Py_DECREF(r); 12577db96d56Sopenharmony_ci 12587db96d56Sopenharmony_ci self->prefetched_idx = self->next_read_idx; 12597db96d56Sopenharmony_ci return 0; 12607db96d56Sopenharmony_ci} 12617db96d56Sopenharmony_ci 12627db96d56Sopenharmony_cistatic const Py_ssize_t READ_WHOLE_LINE = -1; 12637db96d56Sopenharmony_ci 12647db96d56Sopenharmony_ci/* If reading from a file, we need to only pull the bytes we need, since there 12657db96d56Sopenharmony_ci may be multiple pickle objects arranged contiguously in the same input 12667db96d56Sopenharmony_ci buffer. 12677db96d56Sopenharmony_ci 12687db96d56Sopenharmony_ci If `n` is READ_WHOLE_LINE, read a whole line. Otherwise, read up to `n` 12697db96d56Sopenharmony_ci bytes from the input stream/buffer. 12707db96d56Sopenharmony_ci 12717db96d56Sopenharmony_ci Update the unpickler's input buffer with the newly-read data. Returns -1 on 12727db96d56Sopenharmony_ci failure; on success, returns the number of bytes read from the file. 12737db96d56Sopenharmony_ci 12747db96d56Sopenharmony_ci On success, self->input_len will be 0; this is intentional so that when 12757db96d56Sopenharmony_ci unpickling from a file, the "we've run out of data" code paths will trigger, 12767db96d56Sopenharmony_ci causing the Unpickler to go back to the file for more data. Use the returned 12777db96d56Sopenharmony_ci size to tell you how much data you can process. */ 12787db96d56Sopenharmony_cistatic Py_ssize_t 12797db96d56Sopenharmony_ci_Unpickler_ReadFromFile(UnpicklerObject *self, Py_ssize_t n) 12807db96d56Sopenharmony_ci{ 12817db96d56Sopenharmony_ci PyObject *data; 12827db96d56Sopenharmony_ci Py_ssize_t read_size; 12837db96d56Sopenharmony_ci 12847db96d56Sopenharmony_ci assert(self->read != NULL); 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_ci if (_Unpickler_SkipConsumed(self) < 0) 12877db96d56Sopenharmony_ci return -1; 12887db96d56Sopenharmony_ci 12897db96d56Sopenharmony_ci if (n == READ_WHOLE_LINE) { 12907db96d56Sopenharmony_ci data = PyObject_CallNoArgs(self->readline); 12917db96d56Sopenharmony_ci } 12927db96d56Sopenharmony_ci else { 12937db96d56Sopenharmony_ci PyObject *len; 12947db96d56Sopenharmony_ci /* Prefetch some data without advancing the file pointer, if possible */ 12957db96d56Sopenharmony_ci if (self->peek && n < PREFETCH) { 12967db96d56Sopenharmony_ci len = PyLong_FromSsize_t(PREFETCH); 12977db96d56Sopenharmony_ci if (len == NULL) 12987db96d56Sopenharmony_ci return -1; 12997db96d56Sopenharmony_ci data = _Pickle_FastCall(self->peek, len); 13007db96d56Sopenharmony_ci if (data == NULL) { 13017db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_NotImplementedError)) 13027db96d56Sopenharmony_ci return -1; 13037db96d56Sopenharmony_ci /* peek() is probably not supported by the given file object */ 13047db96d56Sopenharmony_ci PyErr_Clear(); 13057db96d56Sopenharmony_ci Py_CLEAR(self->peek); 13067db96d56Sopenharmony_ci } 13077db96d56Sopenharmony_ci else { 13087db96d56Sopenharmony_ci read_size = _Unpickler_SetStringInput(self, data); 13097db96d56Sopenharmony_ci Py_DECREF(data); 13107db96d56Sopenharmony_ci self->prefetched_idx = 0; 13117db96d56Sopenharmony_ci if (n <= read_size) 13127db96d56Sopenharmony_ci return n; 13137db96d56Sopenharmony_ci } 13147db96d56Sopenharmony_ci } 13157db96d56Sopenharmony_ci len = PyLong_FromSsize_t(n); 13167db96d56Sopenharmony_ci if (len == NULL) 13177db96d56Sopenharmony_ci return -1; 13187db96d56Sopenharmony_ci data = _Pickle_FastCall(self->read, len); 13197db96d56Sopenharmony_ci } 13207db96d56Sopenharmony_ci if (data == NULL) 13217db96d56Sopenharmony_ci return -1; 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci read_size = _Unpickler_SetStringInput(self, data); 13247db96d56Sopenharmony_ci Py_DECREF(data); 13257db96d56Sopenharmony_ci return read_size; 13267db96d56Sopenharmony_ci} 13277db96d56Sopenharmony_ci 13287db96d56Sopenharmony_ci/* Don't call it directly: use _Unpickler_Read() */ 13297db96d56Sopenharmony_cistatic Py_ssize_t 13307db96d56Sopenharmony_ci_Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n) 13317db96d56Sopenharmony_ci{ 13327db96d56Sopenharmony_ci Py_ssize_t num_read; 13337db96d56Sopenharmony_ci 13347db96d56Sopenharmony_ci *s = NULL; 13357db96d56Sopenharmony_ci if (self->next_read_idx > PY_SSIZE_T_MAX - n) { 13367db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 13377db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 13387db96d56Sopenharmony_ci "read would overflow (invalid bytecode)"); 13397db96d56Sopenharmony_ci return -1; 13407db96d56Sopenharmony_ci } 13417db96d56Sopenharmony_ci 13427db96d56Sopenharmony_ci /* This case is handled by the _Unpickler_Read() macro for efficiency */ 13437db96d56Sopenharmony_ci assert(self->next_read_idx + n > self->input_len); 13447db96d56Sopenharmony_ci 13457db96d56Sopenharmony_ci if (!self->read) 13467db96d56Sopenharmony_ci return bad_readline(); 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ci /* Extend the buffer to satisfy desired size */ 13497db96d56Sopenharmony_ci num_read = _Unpickler_ReadFromFile(self, n); 13507db96d56Sopenharmony_ci if (num_read < 0) 13517db96d56Sopenharmony_ci return -1; 13527db96d56Sopenharmony_ci if (num_read < n) 13537db96d56Sopenharmony_ci return bad_readline(); 13547db96d56Sopenharmony_ci *s = self->input_buffer; 13557db96d56Sopenharmony_ci self->next_read_idx = n; 13567db96d56Sopenharmony_ci return n; 13577db96d56Sopenharmony_ci} 13587db96d56Sopenharmony_ci 13597db96d56Sopenharmony_ci/* Read `n` bytes from the unpickler's data source, storing the result in `buf`. 13607db96d56Sopenharmony_ci * 13617db96d56Sopenharmony_ci * This should only be used for non-small data reads where potentially 13627db96d56Sopenharmony_ci * avoiding a copy is beneficial. This method does not try to prefetch 13637db96d56Sopenharmony_ci * more data into the input buffer. 13647db96d56Sopenharmony_ci * 13657db96d56Sopenharmony_ci * _Unpickler_Read() is recommended in most cases. 13667db96d56Sopenharmony_ci */ 13677db96d56Sopenharmony_cistatic Py_ssize_t 13687db96d56Sopenharmony_ci_Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n) 13697db96d56Sopenharmony_ci{ 13707db96d56Sopenharmony_ci assert(n != READ_WHOLE_LINE); 13717db96d56Sopenharmony_ci 13727db96d56Sopenharmony_ci /* Read from available buffer data, if any */ 13737db96d56Sopenharmony_ci Py_ssize_t in_buffer = self->input_len - self->next_read_idx; 13747db96d56Sopenharmony_ci if (in_buffer > 0) { 13757db96d56Sopenharmony_ci Py_ssize_t to_read = Py_MIN(in_buffer, n); 13767db96d56Sopenharmony_ci memcpy(buf, self->input_buffer + self->next_read_idx, to_read); 13777db96d56Sopenharmony_ci self->next_read_idx += to_read; 13787db96d56Sopenharmony_ci buf += to_read; 13797db96d56Sopenharmony_ci n -= to_read; 13807db96d56Sopenharmony_ci if (n == 0) { 13817db96d56Sopenharmony_ci /* Entire read was satisfied from buffer */ 13827db96d56Sopenharmony_ci return n; 13837db96d56Sopenharmony_ci } 13847db96d56Sopenharmony_ci } 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci /* Read from file */ 13877db96d56Sopenharmony_ci if (!self->read) { 13887db96d56Sopenharmony_ci /* We're unpickling memory, this means the input is truncated */ 13897db96d56Sopenharmony_ci return bad_readline(); 13907db96d56Sopenharmony_ci } 13917db96d56Sopenharmony_ci if (_Unpickler_SkipConsumed(self) < 0) { 13927db96d56Sopenharmony_ci return -1; 13937db96d56Sopenharmony_ci } 13947db96d56Sopenharmony_ci 13957db96d56Sopenharmony_ci if (!self->readinto) { 13967db96d56Sopenharmony_ci /* readinto() not supported on file-like object, fall back to read() 13977db96d56Sopenharmony_ci * and copy into destination buffer (bpo-39681) */ 13987db96d56Sopenharmony_ci PyObject* len = PyLong_FromSsize_t(n); 13997db96d56Sopenharmony_ci if (len == NULL) { 14007db96d56Sopenharmony_ci return -1; 14017db96d56Sopenharmony_ci } 14027db96d56Sopenharmony_ci PyObject* data = _Pickle_FastCall(self->read, len); 14037db96d56Sopenharmony_ci if (data == NULL) { 14047db96d56Sopenharmony_ci return -1; 14057db96d56Sopenharmony_ci } 14067db96d56Sopenharmony_ci if (!PyBytes_Check(data)) { 14077db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 14087db96d56Sopenharmony_ci "read() returned non-bytes object (%R)", 14097db96d56Sopenharmony_ci Py_TYPE(data)); 14107db96d56Sopenharmony_ci Py_DECREF(data); 14117db96d56Sopenharmony_ci return -1; 14127db96d56Sopenharmony_ci } 14137db96d56Sopenharmony_ci Py_ssize_t read_size = PyBytes_GET_SIZE(data); 14147db96d56Sopenharmony_ci if (read_size < n) { 14157db96d56Sopenharmony_ci Py_DECREF(data); 14167db96d56Sopenharmony_ci return bad_readline(); 14177db96d56Sopenharmony_ci } 14187db96d56Sopenharmony_ci memcpy(buf, PyBytes_AS_STRING(data), n); 14197db96d56Sopenharmony_ci Py_DECREF(data); 14207db96d56Sopenharmony_ci return n; 14217db96d56Sopenharmony_ci } 14227db96d56Sopenharmony_ci 14237db96d56Sopenharmony_ci /* Call readinto() into user buffer */ 14247db96d56Sopenharmony_ci PyObject *buf_obj = PyMemoryView_FromMemory(buf, n, PyBUF_WRITE); 14257db96d56Sopenharmony_ci if (buf_obj == NULL) { 14267db96d56Sopenharmony_ci return -1; 14277db96d56Sopenharmony_ci } 14287db96d56Sopenharmony_ci PyObject *read_size_obj = _Pickle_FastCall(self->readinto, buf_obj); 14297db96d56Sopenharmony_ci if (read_size_obj == NULL) { 14307db96d56Sopenharmony_ci return -1; 14317db96d56Sopenharmony_ci } 14327db96d56Sopenharmony_ci Py_ssize_t read_size = PyLong_AsSsize_t(read_size_obj); 14337db96d56Sopenharmony_ci Py_DECREF(read_size_obj); 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci if (read_size < 0) { 14367db96d56Sopenharmony_ci if (!PyErr_Occurred()) { 14377db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 14387db96d56Sopenharmony_ci "readinto() returned negative size"); 14397db96d56Sopenharmony_ci } 14407db96d56Sopenharmony_ci return -1; 14417db96d56Sopenharmony_ci } 14427db96d56Sopenharmony_ci if (read_size < n) { 14437db96d56Sopenharmony_ci return bad_readline(); 14447db96d56Sopenharmony_ci } 14457db96d56Sopenharmony_ci return n; 14467db96d56Sopenharmony_ci} 14477db96d56Sopenharmony_ci 14487db96d56Sopenharmony_ci/* Read `n` bytes from the unpickler's data source, storing the result in `*s`. 14497db96d56Sopenharmony_ci 14507db96d56Sopenharmony_ci This should be used for all data reads, rather than accessing the unpickler's 14517db96d56Sopenharmony_ci input buffer directly. This method deals correctly with reading from input 14527db96d56Sopenharmony_ci streams, which the input buffer doesn't deal with. 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci Note that when reading from a file-like object, self->next_read_idx won't 14557db96d56Sopenharmony_ci be updated (it should remain at 0 for the entire unpickling process). You 14567db96d56Sopenharmony_ci should use this function's return value to know how many bytes you can 14577db96d56Sopenharmony_ci consume. 14587db96d56Sopenharmony_ci 14597db96d56Sopenharmony_ci Returns -1 (with an exception set) on failure. On success, return the 14607db96d56Sopenharmony_ci number of chars read. */ 14617db96d56Sopenharmony_ci#define _Unpickler_Read(self, s, n) \ 14627db96d56Sopenharmony_ci (((n) <= (self)->input_len - (self)->next_read_idx) \ 14637db96d56Sopenharmony_ci ? (*(s) = (self)->input_buffer + (self)->next_read_idx, \ 14647db96d56Sopenharmony_ci (self)->next_read_idx += (n), \ 14657db96d56Sopenharmony_ci (n)) \ 14667db96d56Sopenharmony_ci : _Unpickler_ReadImpl(self, (s), (n))) 14677db96d56Sopenharmony_ci 14687db96d56Sopenharmony_cistatic Py_ssize_t 14697db96d56Sopenharmony_ci_Unpickler_CopyLine(UnpicklerObject *self, char *line, Py_ssize_t len, 14707db96d56Sopenharmony_ci char **result) 14717db96d56Sopenharmony_ci{ 14727db96d56Sopenharmony_ci char *input_line = PyMem_Realloc(self->input_line, len + 1); 14737db96d56Sopenharmony_ci if (input_line == NULL) { 14747db96d56Sopenharmony_ci PyErr_NoMemory(); 14757db96d56Sopenharmony_ci return -1; 14767db96d56Sopenharmony_ci } 14777db96d56Sopenharmony_ci 14787db96d56Sopenharmony_ci memcpy(input_line, line, len); 14797db96d56Sopenharmony_ci input_line[len] = '\0'; 14807db96d56Sopenharmony_ci self->input_line = input_line; 14817db96d56Sopenharmony_ci *result = self->input_line; 14827db96d56Sopenharmony_ci return len; 14837db96d56Sopenharmony_ci} 14847db96d56Sopenharmony_ci 14857db96d56Sopenharmony_ci/* Read a line from the input stream/buffer. If we run off the end of the input 14867db96d56Sopenharmony_ci before hitting \n, raise an error. 14877db96d56Sopenharmony_ci 14887db96d56Sopenharmony_ci Returns the number of chars read, or -1 on failure. */ 14897db96d56Sopenharmony_cistatic Py_ssize_t 14907db96d56Sopenharmony_ci_Unpickler_Readline(UnpicklerObject *self, char **result) 14917db96d56Sopenharmony_ci{ 14927db96d56Sopenharmony_ci Py_ssize_t i, num_read; 14937db96d56Sopenharmony_ci 14947db96d56Sopenharmony_ci for (i = self->next_read_idx; i < self->input_len; i++) { 14957db96d56Sopenharmony_ci if (self->input_buffer[i] == '\n') { 14967db96d56Sopenharmony_ci char *line_start = self->input_buffer + self->next_read_idx; 14977db96d56Sopenharmony_ci num_read = i - self->next_read_idx + 1; 14987db96d56Sopenharmony_ci self->next_read_idx = i + 1; 14997db96d56Sopenharmony_ci return _Unpickler_CopyLine(self, line_start, num_read, result); 15007db96d56Sopenharmony_ci } 15017db96d56Sopenharmony_ci } 15027db96d56Sopenharmony_ci if (!self->read) 15037db96d56Sopenharmony_ci return bad_readline(); 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci num_read = _Unpickler_ReadFromFile(self, READ_WHOLE_LINE); 15067db96d56Sopenharmony_ci if (num_read < 0) 15077db96d56Sopenharmony_ci return -1; 15087db96d56Sopenharmony_ci if (num_read == 0 || self->input_buffer[num_read - 1] != '\n') 15097db96d56Sopenharmony_ci return bad_readline(); 15107db96d56Sopenharmony_ci self->next_read_idx = num_read; 15117db96d56Sopenharmony_ci return _Unpickler_CopyLine(self, self->input_buffer, num_read, result); 15127db96d56Sopenharmony_ci} 15137db96d56Sopenharmony_ci 15147db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. The memo array 15157db96d56Sopenharmony_ci will be modified in place. */ 15167db96d56Sopenharmony_cistatic int 15177db96d56Sopenharmony_ci_Unpickler_ResizeMemoList(UnpicklerObject *self, size_t new_size) 15187db96d56Sopenharmony_ci{ 15197db96d56Sopenharmony_ci size_t i; 15207db96d56Sopenharmony_ci 15217db96d56Sopenharmony_ci assert(new_size > self->memo_size); 15227db96d56Sopenharmony_ci 15237db96d56Sopenharmony_ci PyObject **memo_new = self->memo; 15247db96d56Sopenharmony_ci PyMem_RESIZE(memo_new, PyObject *, new_size); 15257db96d56Sopenharmony_ci if (memo_new == NULL) { 15267db96d56Sopenharmony_ci PyErr_NoMemory(); 15277db96d56Sopenharmony_ci return -1; 15287db96d56Sopenharmony_ci } 15297db96d56Sopenharmony_ci self->memo = memo_new; 15307db96d56Sopenharmony_ci for (i = self->memo_size; i < new_size; i++) 15317db96d56Sopenharmony_ci self->memo[i] = NULL; 15327db96d56Sopenharmony_ci self->memo_size = new_size; 15337db96d56Sopenharmony_ci return 0; 15347db96d56Sopenharmony_ci} 15357db96d56Sopenharmony_ci 15367db96d56Sopenharmony_ci/* Returns NULL if idx is out of bounds. */ 15377db96d56Sopenharmony_cistatic PyObject * 15387db96d56Sopenharmony_ci_Unpickler_MemoGet(UnpicklerObject *self, size_t idx) 15397db96d56Sopenharmony_ci{ 15407db96d56Sopenharmony_ci if (idx >= self->memo_size) 15417db96d56Sopenharmony_ci return NULL; 15427db96d56Sopenharmony_ci 15437db96d56Sopenharmony_ci return self->memo[idx]; 15447db96d56Sopenharmony_ci} 15457db96d56Sopenharmony_ci 15467db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. 15477db96d56Sopenharmony_ci This takes its own reference to `value`. */ 15487db96d56Sopenharmony_cistatic int 15497db96d56Sopenharmony_ci_Unpickler_MemoPut(UnpicklerObject *self, size_t idx, PyObject *value) 15507db96d56Sopenharmony_ci{ 15517db96d56Sopenharmony_ci PyObject *old_item; 15527db96d56Sopenharmony_ci 15537db96d56Sopenharmony_ci if (idx >= self->memo_size) { 15547db96d56Sopenharmony_ci if (_Unpickler_ResizeMemoList(self, idx * 2) < 0) 15557db96d56Sopenharmony_ci return -1; 15567db96d56Sopenharmony_ci assert(idx < self->memo_size); 15577db96d56Sopenharmony_ci } 15587db96d56Sopenharmony_ci Py_INCREF(value); 15597db96d56Sopenharmony_ci old_item = self->memo[idx]; 15607db96d56Sopenharmony_ci self->memo[idx] = value; 15617db96d56Sopenharmony_ci if (old_item != NULL) { 15627db96d56Sopenharmony_ci Py_DECREF(old_item); 15637db96d56Sopenharmony_ci } 15647db96d56Sopenharmony_ci else { 15657db96d56Sopenharmony_ci self->memo_len++; 15667db96d56Sopenharmony_ci } 15677db96d56Sopenharmony_ci return 0; 15687db96d56Sopenharmony_ci} 15697db96d56Sopenharmony_ci 15707db96d56Sopenharmony_cistatic PyObject ** 15717db96d56Sopenharmony_ci_Unpickler_NewMemo(Py_ssize_t new_size) 15727db96d56Sopenharmony_ci{ 15737db96d56Sopenharmony_ci PyObject **memo = PyMem_NEW(PyObject *, new_size); 15747db96d56Sopenharmony_ci if (memo == NULL) { 15757db96d56Sopenharmony_ci PyErr_NoMemory(); 15767db96d56Sopenharmony_ci return NULL; 15777db96d56Sopenharmony_ci } 15787db96d56Sopenharmony_ci memset(memo, 0, new_size * sizeof(PyObject *)); 15797db96d56Sopenharmony_ci return memo; 15807db96d56Sopenharmony_ci} 15817db96d56Sopenharmony_ci 15827db96d56Sopenharmony_ci/* Free the unpickler's memo, taking care to decref any items left in it. */ 15837db96d56Sopenharmony_cistatic void 15847db96d56Sopenharmony_ci_Unpickler_MemoCleanup(UnpicklerObject *self) 15857db96d56Sopenharmony_ci{ 15867db96d56Sopenharmony_ci Py_ssize_t i; 15877db96d56Sopenharmony_ci PyObject **memo = self->memo; 15887db96d56Sopenharmony_ci 15897db96d56Sopenharmony_ci if (self->memo == NULL) 15907db96d56Sopenharmony_ci return; 15917db96d56Sopenharmony_ci self->memo = NULL; 15927db96d56Sopenharmony_ci i = self->memo_size; 15937db96d56Sopenharmony_ci while (--i >= 0) { 15947db96d56Sopenharmony_ci Py_XDECREF(memo[i]); 15957db96d56Sopenharmony_ci } 15967db96d56Sopenharmony_ci PyMem_Free(memo); 15977db96d56Sopenharmony_ci} 15987db96d56Sopenharmony_ci 15997db96d56Sopenharmony_cistatic UnpicklerObject * 16007db96d56Sopenharmony_ci_Unpickler_New(void) 16017db96d56Sopenharmony_ci{ 16027db96d56Sopenharmony_ci UnpicklerObject *self; 16037db96d56Sopenharmony_ci 16047db96d56Sopenharmony_ci self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type); 16057db96d56Sopenharmony_ci if (self == NULL) 16067db96d56Sopenharmony_ci return NULL; 16077db96d56Sopenharmony_ci 16087db96d56Sopenharmony_ci self->pers_func = NULL; 16097db96d56Sopenharmony_ci self->input_buffer = NULL; 16107db96d56Sopenharmony_ci self->input_line = NULL; 16117db96d56Sopenharmony_ci self->input_len = 0; 16127db96d56Sopenharmony_ci self->next_read_idx = 0; 16137db96d56Sopenharmony_ci self->prefetched_idx = 0; 16147db96d56Sopenharmony_ci self->read = NULL; 16157db96d56Sopenharmony_ci self->readinto = NULL; 16167db96d56Sopenharmony_ci self->readline = NULL; 16177db96d56Sopenharmony_ci self->peek = NULL; 16187db96d56Sopenharmony_ci self->buffers = NULL; 16197db96d56Sopenharmony_ci self->encoding = NULL; 16207db96d56Sopenharmony_ci self->errors = NULL; 16217db96d56Sopenharmony_ci self->marks = NULL; 16227db96d56Sopenharmony_ci self->num_marks = 0; 16237db96d56Sopenharmony_ci self->marks_size = 0; 16247db96d56Sopenharmony_ci self->proto = 0; 16257db96d56Sopenharmony_ci self->fix_imports = 0; 16267db96d56Sopenharmony_ci memset(&self->buffer, 0, sizeof(Py_buffer)); 16277db96d56Sopenharmony_ci self->memo_size = 32; 16287db96d56Sopenharmony_ci self->memo_len = 0; 16297db96d56Sopenharmony_ci self->memo = _Unpickler_NewMemo(self->memo_size); 16307db96d56Sopenharmony_ci self->stack = (Pdata *)Pdata_New(); 16317db96d56Sopenharmony_ci 16327db96d56Sopenharmony_ci if (self->memo == NULL || self->stack == NULL) { 16337db96d56Sopenharmony_ci Py_DECREF(self); 16347db96d56Sopenharmony_ci return NULL; 16357db96d56Sopenharmony_ci } 16367db96d56Sopenharmony_ci 16377db96d56Sopenharmony_ci PyObject_GC_Track(self); 16387db96d56Sopenharmony_ci return self; 16397db96d56Sopenharmony_ci} 16407db96d56Sopenharmony_ci 16417db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may 16427db96d56Sopenharmony_ci be called once on a freshly created Unpickler. */ 16437db96d56Sopenharmony_cistatic int 16447db96d56Sopenharmony_ci_Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file) 16457db96d56Sopenharmony_ci{ 16467db96d56Sopenharmony_ci /* Optional file methods */ 16477db96d56Sopenharmony_ci if (_PyObject_LookupAttr(file, &_Py_ID(peek), &self->peek) < 0) { 16487db96d56Sopenharmony_ci return -1; 16497db96d56Sopenharmony_ci } 16507db96d56Sopenharmony_ci if (_PyObject_LookupAttr(file, &_Py_ID(readinto), &self->readinto) < 0) { 16517db96d56Sopenharmony_ci return -1; 16527db96d56Sopenharmony_ci } 16537db96d56Sopenharmony_ci (void)_PyObject_LookupAttr(file, &_Py_ID(read), &self->read); 16547db96d56Sopenharmony_ci (void)_PyObject_LookupAttr(file, &_Py_ID(readline), &self->readline); 16557db96d56Sopenharmony_ci if (!self->readline || !self->read) { 16567db96d56Sopenharmony_ci if (!PyErr_Occurred()) { 16577db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 16587db96d56Sopenharmony_ci "file must have 'read' and 'readline' attributes"); 16597db96d56Sopenharmony_ci } 16607db96d56Sopenharmony_ci Py_CLEAR(self->read); 16617db96d56Sopenharmony_ci Py_CLEAR(self->readinto); 16627db96d56Sopenharmony_ci Py_CLEAR(self->readline); 16637db96d56Sopenharmony_ci Py_CLEAR(self->peek); 16647db96d56Sopenharmony_ci return -1; 16657db96d56Sopenharmony_ci } 16667db96d56Sopenharmony_ci return 0; 16677db96d56Sopenharmony_ci} 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may 16707db96d56Sopenharmony_ci be called once on a freshly created Unpickler. */ 16717db96d56Sopenharmony_cistatic int 16727db96d56Sopenharmony_ci_Unpickler_SetInputEncoding(UnpicklerObject *self, 16737db96d56Sopenharmony_ci const char *encoding, 16747db96d56Sopenharmony_ci const char *errors) 16757db96d56Sopenharmony_ci{ 16767db96d56Sopenharmony_ci if (encoding == NULL) 16777db96d56Sopenharmony_ci encoding = "ASCII"; 16787db96d56Sopenharmony_ci if (errors == NULL) 16797db96d56Sopenharmony_ci errors = "strict"; 16807db96d56Sopenharmony_ci 16817db96d56Sopenharmony_ci self->encoding = _PyMem_Strdup(encoding); 16827db96d56Sopenharmony_ci self->errors = _PyMem_Strdup(errors); 16837db96d56Sopenharmony_ci if (self->encoding == NULL || self->errors == NULL) { 16847db96d56Sopenharmony_ci PyErr_NoMemory(); 16857db96d56Sopenharmony_ci return -1; 16867db96d56Sopenharmony_ci } 16877db96d56Sopenharmony_ci return 0; 16887db96d56Sopenharmony_ci} 16897db96d56Sopenharmony_ci 16907db96d56Sopenharmony_ci/* Returns -1 (with an exception set) on failure, 0 on success. This may 16917db96d56Sopenharmony_ci be called once on a freshly created Unpickler. */ 16927db96d56Sopenharmony_cistatic int 16937db96d56Sopenharmony_ci_Unpickler_SetBuffers(UnpicklerObject *self, PyObject *buffers) 16947db96d56Sopenharmony_ci{ 16957db96d56Sopenharmony_ci if (buffers == NULL || buffers == Py_None) { 16967db96d56Sopenharmony_ci self->buffers = NULL; 16977db96d56Sopenharmony_ci } 16987db96d56Sopenharmony_ci else { 16997db96d56Sopenharmony_ci self->buffers = PyObject_GetIter(buffers); 17007db96d56Sopenharmony_ci if (self->buffers == NULL) { 17017db96d56Sopenharmony_ci return -1; 17027db96d56Sopenharmony_ci } 17037db96d56Sopenharmony_ci } 17047db96d56Sopenharmony_ci return 0; 17057db96d56Sopenharmony_ci} 17067db96d56Sopenharmony_ci 17077db96d56Sopenharmony_ci/* Generate a GET opcode for an object stored in the memo. */ 17087db96d56Sopenharmony_cistatic int 17097db96d56Sopenharmony_cimemo_get(PicklerObject *self, PyObject *key) 17107db96d56Sopenharmony_ci{ 17117db96d56Sopenharmony_ci Py_ssize_t *value; 17127db96d56Sopenharmony_ci char pdata[30]; 17137db96d56Sopenharmony_ci Py_ssize_t len; 17147db96d56Sopenharmony_ci 17157db96d56Sopenharmony_ci value = PyMemoTable_Get(self->memo, key); 17167db96d56Sopenharmony_ci if (value == NULL) { 17177db96d56Sopenharmony_ci PyErr_SetObject(PyExc_KeyError, key); 17187db96d56Sopenharmony_ci return -1; 17197db96d56Sopenharmony_ci } 17207db96d56Sopenharmony_ci 17217db96d56Sopenharmony_ci if (!self->bin) { 17227db96d56Sopenharmony_ci pdata[0] = GET; 17237db96d56Sopenharmony_ci PyOS_snprintf(pdata + 1, sizeof(pdata) - 1, 17247db96d56Sopenharmony_ci "%zd\n", *value); 17257db96d56Sopenharmony_ci len = strlen(pdata); 17267db96d56Sopenharmony_ci } 17277db96d56Sopenharmony_ci else { 17287db96d56Sopenharmony_ci if (*value < 256) { 17297db96d56Sopenharmony_ci pdata[0] = BINGET; 17307db96d56Sopenharmony_ci pdata[1] = (unsigned char)(*value & 0xff); 17317db96d56Sopenharmony_ci len = 2; 17327db96d56Sopenharmony_ci } 17337db96d56Sopenharmony_ci else if ((size_t)*value <= 0xffffffffUL) { 17347db96d56Sopenharmony_ci pdata[0] = LONG_BINGET; 17357db96d56Sopenharmony_ci pdata[1] = (unsigned char)(*value & 0xff); 17367db96d56Sopenharmony_ci pdata[2] = (unsigned char)((*value >> 8) & 0xff); 17377db96d56Sopenharmony_ci pdata[3] = (unsigned char)((*value >> 16) & 0xff); 17387db96d56Sopenharmony_ci pdata[4] = (unsigned char)((*value >> 24) & 0xff); 17397db96d56Sopenharmony_ci len = 5; 17407db96d56Sopenharmony_ci } 17417db96d56Sopenharmony_ci else { /* unlikely */ 17427db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 17437db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, 17447db96d56Sopenharmony_ci "memo id too large for LONG_BINGET"); 17457db96d56Sopenharmony_ci return -1; 17467db96d56Sopenharmony_ci } 17477db96d56Sopenharmony_ci } 17487db96d56Sopenharmony_ci 17497db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, len) < 0) 17507db96d56Sopenharmony_ci return -1; 17517db96d56Sopenharmony_ci 17527db96d56Sopenharmony_ci return 0; 17537db96d56Sopenharmony_ci} 17547db96d56Sopenharmony_ci 17557db96d56Sopenharmony_ci/* Store an object in the memo, assign it a new unique ID based on the number 17567db96d56Sopenharmony_ci of objects currently stored in the memo and generate a PUT opcode. */ 17577db96d56Sopenharmony_cistatic int 17587db96d56Sopenharmony_cimemo_put(PicklerObject *self, PyObject *obj) 17597db96d56Sopenharmony_ci{ 17607db96d56Sopenharmony_ci char pdata[30]; 17617db96d56Sopenharmony_ci Py_ssize_t len; 17627db96d56Sopenharmony_ci Py_ssize_t idx; 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ci const char memoize_op = MEMOIZE; 17657db96d56Sopenharmony_ci 17667db96d56Sopenharmony_ci if (self->fast) 17677db96d56Sopenharmony_ci return 0; 17687db96d56Sopenharmony_ci 17697db96d56Sopenharmony_ci idx = PyMemoTable_Size(self->memo); 17707db96d56Sopenharmony_ci if (PyMemoTable_Set(self->memo, obj, idx) < 0) 17717db96d56Sopenharmony_ci return -1; 17727db96d56Sopenharmony_ci 17737db96d56Sopenharmony_ci if (self->proto >= 4) { 17747db96d56Sopenharmony_ci if (_Pickler_Write(self, &memoize_op, 1) < 0) 17757db96d56Sopenharmony_ci return -1; 17767db96d56Sopenharmony_ci return 0; 17777db96d56Sopenharmony_ci } 17787db96d56Sopenharmony_ci else if (!self->bin) { 17797db96d56Sopenharmony_ci pdata[0] = PUT; 17807db96d56Sopenharmony_ci PyOS_snprintf(pdata + 1, sizeof(pdata) - 1, 17817db96d56Sopenharmony_ci "%zd\n", idx); 17827db96d56Sopenharmony_ci len = strlen(pdata); 17837db96d56Sopenharmony_ci } 17847db96d56Sopenharmony_ci else { 17857db96d56Sopenharmony_ci if (idx < 256) { 17867db96d56Sopenharmony_ci pdata[0] = BINPUT; 17877db96d56Sopenharmony_ci pdata[1] = (unsigned char)idx; 17887db96d56Sopenharmony_ci len = 2; 17897db96d56Sopenharmony_ci } 17907db96d56Sopenharmony_ci else if ((size_t)idx <= 0xffffffffUL) { 17917db96d56Sopenharmony_ci pdata[0] = LONG_BINPUT; 17927db96d56Sopenharmony_ci pdata[1] = (unsigned char)(idx & 0xff); 17937db96d56Sopenharmony_ci pdata[2] = (unsigned char)((idx >> 8) & 0xff); 17947db96d56Sopenharmony_ci pdata[3] = (unsigned char)((idx >> 16) & 0xff); 17957db96d56Sopenharmony_ci pdata[4] = (unsigned char)((idx >> 24) & 0xff); 17967db96d56Sopenharmony_ci len = 5; 17977db96d56Sopenharmony_ci } 17987db96d56Sopenharmony_ci else { /* unlikely */ 17997db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 18007db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, 18017db96d56Sopenharmony_ci "memo id too large for LONG_BINPUT"); 18027db96d56Sopenharmony_ci return -1; 18037db96d56Sopenharmony_ci } 18047db96d56Sopenharmony_ci } 18057db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, len) < 0) 18067db96d56Sopenharmony_ci return -1; 18077db96d56Sopenharmony_ci 18087db96d56Sopenharmony_ci return 0; 18097db96d56Sopenharmony_ci} 18107db96d56Sopenharmony_ci 18117db96d56Sopenharmony_cistatic PyObject * 18127db96d56Sopenharmony_ciget_dotted_path(PyObject *obj, PyObject *name) 18137db96d56Sopenharmony_ci{ 18147db96d56Sopenharmony_ci PyObject *dotted_path; 18157db96d56Sopenharmony_ci Py_ssize_t i, n; 18167db96d56Sopenharmony_ci _Py_DECLARE_STR(dot, "."); 18177db96d56Sopenharmony_ci dotted_path = PyUnicode_Split(name, &_Py_STR(dot), -1); 18187db96d56Sopenharmony_ci if (dotted_path == NULL) 18197db96d56Sopenharmony_ci return NULL; 18207db96d56Sopenharmony_ci n = PyList_GET_SIZE(dotted_path); 18217db96d56Sopenharmony_ci assert(n >= 1); 18227db96d56Sopenharmony_ci for (i = 0; i < n; i++) { 18237db96d56Sopenharmony_ci PyObject *subpath = PyList_GET_ITEM(dotted_path, i); 18247db96d56Sopenharmony_ci if (_PyUnicode_EqualToASCIIString(subpath, "<locals>")) { 18257db96d56Sopenharmony_ci if (obj == NULL) 18267db96d56Sopenharmony_ci PyErr_Format(PyExc_AttributeError, 18277db96d56Sopenharmony_ci "Can't pickle local object %R", name); 18287db96d56Sopenharmony_ci else 18297db96d56Sopenharmony_ci PyErr_Format(PyExc_AttributeError, 18307db96d56Sopenharmony_ci "Can't pickle local attribute %R on %R", name, obj); 18317db96d56Sopenharmony_ci Py_DECREF(dotted_path); 18327db96d56Sopenharmony_ci return NULL; 18337db96d56Sopenharmony_ci } 18347db96d56Sopenharmony_ci } 18357db96d56Sopenharmony_ci return dotted_path; 18367db96d56Sopenharmony_ci} 18377db96d56Sopenharmony_ci 18387db96d56Sopenharmony_cistatic PyObject * 18397db96d56Sopenharmony_ciget_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent) 18407db96d56Sopenharmony_ci{ 18417db96d56Sopenharmony_ci Py_ssize_t i, n; 18427db96d56Sopenharmony_ci PyObject *parent = NULL; 18437db96d56Sopenharmony_ci 18447db96d56Sopenharmony_ci assert(PyList_CheckExact(names)); 18457db96d56Sopenharmony_ci Py_INCREF(obj); 18467db96d56Sopenharmony_ci n = PyList_GET_SIZE(names); 18477db96d56Sopenharmony_ci for (i = 0; i < n; i++) { 18487db96d56Sopenharmony_ci PyObject *name = PyList_GET_ITEM(names, i); 18497db96d56Sopenharmony_ci Py_XDECREF(parent); 18507db96d56Sopenharmony_ci parent = obj; 18517db96d56Sopenharmony_ci (void)_PyObject_LookupAttr(parent, name, &obj); 18527db96d56Sopenharmony_ci if (obj == NULL) { 18537db96d56Sopenharmony_ci Py_DECREF(parent); 18547db96d56Sopenharmony_ci return NULL; 18557db96d56Sopenharmony_ci } 18567db96d56Sopenharmony_ci } 18577db96d56Sopenharmony_ci if (pparent != NULL) 18587db96d56Sopenharmony_ci *pparent = parent; 18597db96d56Sopenharmony_ci else 18607db96d56Sopenharmony_ci Py_XDECREF(parent); 18617db96d56Sopenharmony_ci return obj; 18627db96d56Sopenharmony_ci} 18637db96d56Sopenharmony_ci 18647db96d56Sopenharmony_ci 18657db96d56Sopenharmony_cistatic PyObject * 18667db96d56Sopenharmony_cigetattribute(PyObject *obj, PyObject *name, int allow_qualname) 18677db96d56Sopenharmony_ci{ 18687db96d56Sopenharmony_ci PyObject *dotted_path, *attr; 18697db96d56Sopenharmony_ci 18707db96d56Sopenharmony_ci if (allow_qualname) { 18717db96d56Sopenharmony_ci dotted_path = get_dotted_path(obj, name); 18727db96d56Sopenharmony_ci if (dotted_path == NULL) 18737db96d56Sopenharmony_ci return NULL; 18747db96d56Sopenharmony_ci attr = get_deep_attribute(obj, dotted_path, NULL); 18757db96d56Sopenharmony_ci Py_DECREF(dotted_path); 18767db96d56Sopenharmony_ci } 18777db96d56Sopenharmony_ci else { 18787db96d56Sopenharmony_ci (void)_PyObject_LookupAttr(obj, name, &attr); 18797db96d56Sopenharmony_ci } 18807db96d56Sopenharmony_ci if (attr == NULL && !PyErr_Occurred()) { 18817db96d56Sopenharmony_ci PyErr_Format(PyExc_AttributeError, 18827db96d56Sopenharmony_ci "Can't get attribute %R on %R", name, obj); 18837db96d56Sopenharmony_ci } 18847db96d56Sopenharmony_ci return attr; 18857db96d56Sopenharmony_ci} 18867db96d56Sopenharmony_ci 18877db96d56Sopenharmony_cistatic int 18887db96d56Sopenharmony_ci_checkmodule(PyObject *module_name, PyObject *module, 18897db96d56Sopenharmony_ci PyObject *global, PyObject *dotted_path) 18907db96d56Sopenharmony_ci{ 18917db96d56Sopenharmony_ci if (module == Py_None) { 18927db96d56Sopenharmony_ci return -1; 18937db96d56Sopenharmony_ci } 18947db96d56Sopenharmony_ci if (PyUnicode_Check(module_name) && 18957db96d56Sopenharmony_ci _PyUnicode_EqualToASCIIString(module_name, "__main__")) { 18967db96d56Sopenharmony_ci return -1; 18977db96d56Sopenharmony_ci } 18987db96d56Sopenharmony_ci 18997db96d56Sopenharmony_ci PyObject *candidate = get_deep_attribute(module, dotted_path, NULL); 19007db96d56Sopenharmony_ci if (candidate == NULL) { 19017db96d56Sopenharmony_ci return -1; 19027db96d56Sopenharmony_ci } 19037db96d56Sopenharmony_ci if (candidate != global) { 19047db96d56Sopenharmony_ci Py_DECREF(candidate); 19057db96d56Sopenharmony_ci return -1; 19067db96d56Sopenharmony_ci } 19077db96d56Sopenharmony_ci Py_DECREF(candidate); 19087db96d56Sopenharmony_ci return 0; 19097db96d56Sopenharmony_ci} 19107db96d56Sopenharmony_ci 19117db96d56Sopenharmony_cistatic PyObject * 19127db96d56Sopenharmony_ciwhichmodule(PyObject *global, PyObject *dotted_path) 19137db96d56Sopenharmony_ci{ 19147db96d56Sopenharmony_ci PyObject *module_name; 19157db96d56Sopenharmony_ci PyObject *module = NULL; 19167db96d56Sopenharmony_ci Py_ssize_t i; 19177db96d56Sopenharmony_ci PyObject *modules; 19187db96d56Sopenharmony_ci 19197db96d56Sopenharmony_ci if (_PyObject_LookupAttr(global, &_Py_ID(__module__), &module_name) < 0) { 19207db96d56Sopenharmony_ci return NULL; 19217db96d56Sopenharmony_ci } 19227db96d56Sopenharmony_ci if (module_name) { 19237db96d56Sopenharmony_ci /* In some rare cases (e.g., bound methods of extension types), 19247db96d56Sopenharmony_ci __module__ can be None. If it is so, then search sys.modules for 19257db96d56Sopenharmony_ci the module of global. */ 19267db96d56Sopenharmony_ci if (module_name != Py_None) 19277db96d56Sopenharmony_ci return module_name; 19287db96d56Sopenharmony_ci Py_CLEAR(module_name); 19297db96d56Sopenharmony_ci } 19307db96d56Sopenharmony_ci assert(module_name == NULL); 19317db96d56Sopenharmony_ci 19327db96d56Sopenharmony_ci /* Fallback on walking sys.modules */ 19337db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 19347db96d56Sopenharmony_ci modules = _PySys_GetAttr(tstate, &_Py_ID(modules)); 19357db96d56Sopenharmony_ci if (modules == NULL) { 19367db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); 19377db96d56Sopenharmony_ci return NULL; 19387db96d56Sopenharmony_ci } 19397db96d56Sopenharmony_ci if (PyDict_CheckExact(modules)) { 19407db96d56Sopenharmony_ci i = 0; 19417db96d56Sopenharmony_ci while (PyDict_Next(modules, &i, &module_name, &module)) { 19427db96d56Sopenharmony_ci if (_checkmodule(module_name, module, global, dotted_path) == 0) { 19437db96d56Sopenharmony_ci Py_INCREF(module_name); 19447db96d56Sopenharmony_ci return module_name; 19457db96d56Sopenharmony_ci } 19467db96d56Sopenharmony_ci if (PyErr_Occurred()) { 19477db96d56Sopenharmony_ci return NULL; 19487db96d56Sopenharmony_ci } 19497db96d56Sopenharmony_ci } 19507db96d56Sopenharmony_ci } 19517db96d56Sopenharmony_ci else { 19527db96d56Sopenharmony_ci PyObject *iterator = PyObject_GetIter(modules); 19537db96d56Sopenharmony_ci if (iterator == NULL) { 19547db96d56Sopenharmony_ci return NULL; 19557db96d56Sopenharmony_ci } 19567db96d56Sopenharmony_ci while ((module_name = PyIter_Next(iterator))) { 19577db96d56Sopenharmony_ci module = PyObject_GetItem(modules, module_name); 19587db96d56Sopenharmony_ci if (module == NULL) { 19597db96d56Sopenharmony_ci Py_DECREF(module_name); 19607db96d56Sopenharmony_ci Py_DECREF(iterator); 19617db96d56Sopenharmony_ci return NULL; 19627db96d56Sopenharmony_ci } 19637db96d56Sopenharmony_ci if (_checkmodule(module_name, module, global, dotted_path) == 0) { 19647db96d56Sopenharmony_ci Py_DECREF(module); 19657db96d56Sopenharmony_ci Py_DECREF(iterator); 19667db96d56Sopenharmony_ci return module_name; 19677db96d56Sopenharmony_ci } 19687db96d56Sopenharmony_ci Py_DECREF(module); 19697db96d56Sopenharmony_ci Py_DECREF(module_name); 19707db96d56Sopenharmony_ci if (PyErr_Occurred()) { 19717db96d56Sopenharmony_ci Py_DECREF(iterator); 19727db96d56Sopenharmony_ci return NULL; 19737db96d56Sopenharmony_ci } 19747db96d56Sopenharmony_ci } 19757db96d56Sopenharmony_ci Py_DECREF(iterator); 19767db96d56Sopenharmony_ci } 19777db96d56Sopenharmony_ci 19787db96d56Sopenharmony_ci /* If no module is found, use __main__. */ 19797db96d56Sopenharmony_ci module_name = &_Py_ID(__main__); 19807db96d56Sopenharmony_ci Py_INCREF(module_name); 19817db96d56Sopenharmony_ci return module_name; 19827db96d56Sopenharmony_ci} 19837db96d56Sopenharmony_ci 19847db96d56Sopenharmony_ci/* fast_save_enter() and fast_save_leave() are guards against recursive 19857db96d56Sopenharmony_ci objects when Pickler is used with the "fast mode" (i.e., with object 19867db96d56Sopenharmony_ci memoization disabled). If the nesting of a list or dict object exceed 19877db96d56Sopenharmony_ci FAST_NESTING_LIMIT, these guards will start keeping an internal 19887db96d56Sopenharmony_ci reference to the seen list or dict objects and check whether these objects 19897db96d56Sopenharmony_ci are recursive. These are not strictly necessary, since save() has a 19907db96d56Sopenharmony_ci hard-coded recursion limit, but they give a nicer error message than the 19917db96d56Sopenharmony_ci typical RuntimeError. */ 19927db96d56Sopenharmony_cistatic int 19937db96d56Sopenharmony_cifast_save_enter(PicklerObject *self, PyObject *obj) 19947db96d56Sopenharmony_ci{ 19957db96d56Sopenharmony_ci /* if fast_nesting < 0, we're doing an error exit. */ 19967db96d56Sopenharmony_ci if (++self->fast_nesting >= FAST_NESTING_LIMIT) { 19977db96d56Sopenharmony_ci PyObject *key = NULL; 19987db96d56Sopenharmony_ci if (self->fast_memo == NULL) { 19997db96d56Sopenharmony_ci self->fast_memo = PyDict_New(); 20007db96d56Sopenharmony_ci if (self->fast_memo == NULL) { 20017db96d56Sopenharmony_ci self->fast_nesting = -1; 20027db96d56Sopenharmony_ci return 0; 20037db96d56Sopenharmony_ci } 20047db96d56Sopenharmony_ci } 20057db96d56Sopenharmony_ci key = PyLong_FromVoidPtr(obj); 20067db96d56Sopenharmony_ci if (key == NULL) { 20077db96d56Sopenharmony_ci self->fast_nesting = -1; 20087db96d56Sopenharmony_ci return 0; 20097db96d56Sopenharmony_ci } 20107db96d56Sopenharmony_ci int r = PyDict_Contains(self->fast_memo, key); 20117db96d56Sopenharmony_ci if (r > 0) { 20127db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 20137db96d56Sopenharmony_ci "fast mode: can't pickle cyclic objects " 20147db96d56Sopenharmony_ci "including object type %.200s at %p", 20157db96d56Sopenharmony_ci Py_TYPE(obj)->tp_name, obj); 20167db96d56Sopenharmony_ci } 20177db96d56Sopenharmony_ci else if (r == 0) { 20187db96d56Sopenharmony_ci r = PyDict_SetItem(self->fast_memo, key, Py_None); 20197db96d56Sopenharmony_ci } 20207db96d56Sopenharmony_ci Py_DECREF(key); 20217db96d56Sopenharmony_ci if (r != 0) { 20227db96d56Sopenharmony_ci self->fast_nesting = -1; 20237db96d56Sopenharmony_ci return 0; 20247db96d56Sopenharmony_ci } 20257db96d56Sopenharmony_ci } 20267db96d56Sopenharmony_ci return 1; 20277db96d56Sopenharmony_ci} 20287db96d56Sopenharmony_ci 20297db96d56Sopenharmony_cistatic int 20307db96d56Sopenharmony_cifast_save_leave(PicklerObject *self, PyObject *obj) 20317db96d56Sopenharmony_ci{ 20327db96d56Sopenharmony_ci if (self->fast_nesting-- >= FAST_NESTING_LIMIT) { 20337db96d56Sopenharmony_ci PyObject *key = PyLong_FromVoidPtr(obj); 20347db96d56Sopenharmony_ci if (key == NULL) 20357db96d56Sopenharmony_ci return 0; 20367db96d56Sopenharmony_ci if (PyDict_DelItem(self->fast_memo, key) < 0) { 20377db96d56Sopenharmony_ci Py_DECREF(key); 20387db96d56Sopenharmony_ci return 0; 20397db96d56Sopenharmony_ci } 20407db96d56Sopenharmony_ci Py_DECREF(key); 20417db96d56Sopenharmony_ci } 20427db96d56Sopenharmony_ci return 1; 20437db96d56Sopenharmony_ci} 20447db96d56Sopenharmony_ci 20457db96d56Sopenharmony_cistatic int 20467db96d56Sopenharmony_cisave_none(PicklerObject *self, PyObject *obj) 20477db96d56Sopenharmony_ci{ 20487db96d56Sopenharmony_ci const char none_op = NONE; 20497db96d56Sopenharmony_ci if (_Pickler_Write(self, &none_op, 1) < 0) 20507db96d56Sopenharmony_ci return -1; 20517db96d56Sopenharmony_ci 20527db96d56Sopenharmony_ci return 0; 20537db96d56Sopenharmony_ci} 20547db96d56Sopenharmony_ci 20557db96d56Sopenharmony_cistatic int 20567db96d56Sopenharmony_cisave_bool(PicklerObject *self, PyObject *obj) 20577db96d56Sopenharmony_ci{ 20587db96d56Sopenharmony_ci if (self->proto >= 2) { 20597db96d56Sopenharmony_ci const char bool_op = (obj == Py_True) ? NEWTRUE : NEWFALSE; 20607db96d56Sopenharmony_ci if (_Pickler_Write(self, &bool_op, 1) < 0) 20617db96d56Sopenharmony_ci return -1; 20627db96d56Sopenharmony_ci } 20637db96d56Sopenharmony_ci else { 20647db96d56Sopenharmony_ci /* These aren't opcodes -- they're ways to pickle bools before protocol 2 20657db96d56Sopenharmony_ci * so that unpicklers written before bools were introduced unpickle them 20667db96d56Sopenharmony_ci * as ints, but unpicklers after can recognize that bools were intended. 20677db96d56Sopenharmony_ci * Note that protocol 2 added direct ways to pickle bools. 20687db96d56Sopenharmony_ci */ 20697db96d56Sopenharmony_ci const char *bool_str = (obj == Py_True) ? "I01\n" : "I00\n"; 20707db96d56Sopenharmony_ci if (_Pickler_Write(self, bool_str, strlen(bool_str)) < 0) 20717db96d56Sopenharmony_ci return -1; 20727db96d56Sopenharmony_ci } 20737db96d56Sopenharmony_ci return 0; 20747db96d56Sopenharmony_ci} 20757db96d56Sopenharmony_ci 20767db96d56Sopenharmony_cistatic int 20777db96d56Sopenharmony_cisave_long(PicklerObject *self, PyObject *obj) 20787db96d56Sopenharmony_ci{ 20797db96d56Sopenharmony_ci PyObject *repr = NULL; 20807db96d56Sopenharmony_ci Py_ssize_t size; 20817db96d56Sopenharmony_ci long val; 20827db96d56Sopenharmony_ci int overflow; 20837db96d56Sopenharmony_ci int status = 0; 20847db96d56Sopenharmony_ci 20857db96d56Sopenharmony_ci val= PyLong_AsLongAndOverflow(obj, &overflow); 20867db96d56Sopenharmony_ci if (!overflow && (sizeof(long) <= 4 || 20877db96d56Sopenharmony_ci (val <= 0x7fffffffL && val >= (-0x7fffffffL - 1)))) 20887db96d56Sopenharmony_ci { 20897db96d56Sopenharmony_ci /* result fits in a signed 4-byte integer. 20907db96d56Sopenharmony_ci 20917db96d56Sopenharmony_ci Note: we can't use -0x80000000L in the above condition because some 20927db96d56Sopenharmony_ci compilers (e.g., MSVC) will promote 0x80000000L to an unsigned type 20937db96d56Sopenharmony_ci before applying the unary minus when sizeof(long) <= 4. The 20947db96d56Sopenharmony_ci resulting value stays unsigned which is commonly not what we want, 20957db96d56Sopenharmony_ci so MSVC happily warns us about it. However, that result would have 20967db96d56Sopenharmony_ci been fine because we guard for sizeof(long) <= 4 which turns the 20977db96d56Sopenharmony_ci condition true in that particular case. */ 20987db96d56Sopenharmony_ci char pdata[32]; 20997db96d56Sopenharmony_ci Py_ssize_t len = 0; 21007db96d56Sopenharmony_ci 21017db96d56Sopenharmony_ci if (self->bin) { 21027db96d56Sopenharmony_ci pdata[1] = (unsigned char)(val & 0xff); 21037db96d56Sopenharmony_ci pdata[2] = (unsigned char)((val >> 8) & 0xff); 21047db96d56Sopenharmony_ci pdata[3] = (unsigned char)((val >> 16) & 0xff); 21057db96d56Sopenharmony_ci pdata[4] = (unsigned char)((val >> 24) & 0xff); 21067db96d56Sopenharmony_ci 21077db96d56Sopenharmony_ci if ((pdata[4] != 0) || (pdata[3] != 0)) { 21087db96d56Sopenharmony_ci pdata[0] = BININT; 21097db96d56Sopenharmony_ci len = 5; 21107db96d56Sopenharmony_ci } 21117db96d56Sopenharmony_ci else if (pdata[2] != 0) { 21127db96d56Sopenharmony_ci pdata[0] = BININT2; 21137db96d56Sopenharmony_ci len = 3; 21147db96d56Sopenharmony_ci } 21157db96d56Sopenharmony_ci else { 21167db96d56Sopenharmony_ci pdata[0] = BININT1; 21177db96d56Sopenharmony_ci len = 2; 21187db96d56Sopenharmony_ci } 21197db96d56Sopenharmony_ci } 21207db96d56Sopenharmony_ci else { 21217db96d56Sopenharmony_ci sprintf(pdata, "%c%ld\n", INT, val); 21227db96d56Sopenharmony_ci len = strlen(pdata); 21237db96d56Sopenharmony_ci } 21247db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, len) < 0) 21257db96d56Sopenharmony_ci return -1; 21267db96d56Sopenharmony_ci 21277db96d56Sopenharmony_ci return 0; 21287db96d56Sopenharmony_ci } 21297db96d56Sopenharmony_ci assert(!PyErr_Occurred()); 21307db96d56Sopenharmony_ci 21317db96d56Sopenharmony_ci if (self->proto >= 2) { 21327db96d56Sopenharmony_ci /* Linear-time pickling. */ 21337db96d56Sopenharmony_ci size_t nbits; 21347db96d56Sopenharmony_ci size_t nbytes; 21357db96d56Sopenharmony_ci unsigned char *pdata; 21367db96d56Sopenharmony_ci char header[5]; 21377db96d56Sopenharmony_ci int i; 21387db96d56Sopenharmony_ci int sign = _PyLong_Sign(obj); 21397db96d56Sopenharmony_ci 21407db96d56Sopenharmony_ci if (sign == 0) { 21417db96d56Sopenharmony_ci header[0] = LONG1; 21427db96d56Sopenharmony_ci header[1] = 0; /* It's 0 -- an empty bytestring. */ 21437db96d56Sopenharmony_ci if (_Pickler_Write(self, header, 2) < 0) 21447db96d56Sopenharmony_ci goto error; 21457db96d56Sopenharmony_ci return 0; 21467db96d56Sopenharmony_ci } 21477db96d56Sopenharmony_ci nbits = _PyLong_NumBits(obj); 21487db96d56Sopenharmony_ci if (nbits == (size_t)-1 && PyErr_Occurred()) 21497db96d56Sopenharmony_ci goto error; 21507db96d56Sopenharmony_ci /* How many bytes do we need? There are nbits >> 3 full 21517db96d56Sopenharmony_ci * bytes of data, and nbits & 7 leftover bits. If there 21527db96d56Sopenharmony_ci * are any leftover bits, then we clearly need another 21537db96d56Sopenharmony_ci * byte. What's not so obvious is that we *probably* 21547db96d56Sopenharmony_ci * need another byte even if there aren't any leftovers: 21557db96d56Sopenharmony_ci * the most-significant bit of the most-significant byte 21567db96d56Sopenharmony_ci * acts like a sign bit, and it's usually got a sense 21577db96d56Sopenharmony_ci * opposite of the one we need. The exception is ints 21587db96d56Sopenharmony_ci * of the form -(2**(8*j-1)) for j > 0. Such an int is 21597db96d56Sopenharmony_ci * its own 256's-complement, so has the right sign bit 21607db96d56Sopenharmony_ci * even without the extra byte. That's a pain to check 21617db96d56Sopenharmony_ci * for in advance, though, so we always grab an extra 21627db96d56Sopenharmony_ci * byte at the start, and cut it back later if possible. 21637db96d56Sopenharmony_ci */ 21647db96d56Sopenharmony_ci nbytes = (nbits >> 3) + 1; 21657db96d56Sopenharmony_ci if (nbytes > 0x7fffffffL) { 21667db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 21677db96d56Sopenharmony_ci "int too large to pickle"); 21687db96d56Sopenharmony_ci goto error; 21697db96d56Sopenharmony_ci } 21707db96d56Sopenharmony_ci repr = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)nbytes); 21717db96d56Sopenharmony_ci if (repr == NULL) 21727db96d56Sopenharmony_ci goto error; 21737db96d56Sopenharmony_ci pdata = (unsigned char *)PyBytes_AS_STRING(repr); 21747db96d56Sopenharmony_ci i = _PyLong_AsByteArray((PyLongObject *)obj, 21757db96d56Sopenharmony_ci pdata, nbytes, 21767db96d56Sopenharmony_ci 1 /* little endian */ , 1 /* signed */ ); 21777db96d56Sopenharmony_ci if (i < 0) 21787db96d56Sopenharmony_ci goto error; 21797db96d56Sopenharmony_ci /* If the int is negative, this may be a byte more than 21807db96d56Sopenharmony_ci * needed. This is so iff the MSB is all redundant sign 21817db96d56Sopenharmony_ci * bits. 21827db96d56Sopenharmony_ci */ 21837db96d56Sopenharmony_ci if (sign < 0 && 21847db96d56Sopenharmony_ci nbytes > 1 && 21857db96d56Sopenharmony_ci pdata[nbytes - 1] == 0xff && 21867db96d56Sopenharmony_ci (pdata[nbytes - 2] & 0x80) != 0) { 21877db96d56Sopenharmony_ci nbytes--; 21887db96d56Sopenharmony_ci } 21897db96d56Sopenharmony_ci 21907db96d56Sopenharmony_ci if (nbytes < 256) { 21917db96d56Sopenharmony_ci header[0] = LONG1; 21927db96d56Sopenharmony_ci header[1] = (unsigned char)nbytes; 21937db96d56Sopenharmony_ci size = 2; 21947db96d56Sopenharmony_ci } 21957db96d56Sopenharmony_ci else { 21967db96d56Sopenharmony_ci header[0] = LONG4; 21977db96d56Sopenharmony_ci size = (Py_ssize_t) nbytes; 21987db96d56Sopenharmony_ci for (i = 1; i < 5; i++) { 21997db96d56Sopenharmony_ci header[i] = (unsigned char)(size & 0xff); 22007db96d56Sopenharmony_ci size >>= 8; 22017db96d56Sopenharmony_ci } 22027db96d56Sopenharmony_ci size = 5; 22037db96d56Sopenharmony_ci } 22047db96d56Sopenharmony_ci if (_Pickler_Write(self, header, size) < 0 || 22057db96d56Sopenharmony_ci _Pickler_Write(self, (char *)pdata, (int)nbytes) < 0) 22067db96d56Sopenharmony_ci goto error; 22077db96d56Sopenharmony_ci } 22087db96d56Sopenharmony_ci else { 22097db96d56Sopenharmony_ci const char long_op = LONG; 22107db96d56Sopenharmony_ci const char *string; 22117db96d56Sopenharmony_ci 22127db96d56Sopenharmony_ci /* proto < 2: write the repr and newline. This is quadratic-time (in 22137db96d56Sopenharmony_ci the number of digits), in both directions. We add a trailing 'L' 22147db96d56Sopenharmony_ci to the repr, for compatibility with Python 2.x. */ 22157db96d56Sopenharmony_ci 22167db96d56Sopenharmony_ci repr = PyObject_Repr(obj); 22177db96d56Sopenharmony_ci if (repr == NULL) 22187db96d56Sopenharmony_ci goto error; 22197db96d56Sopenharmony_ci 22207db96d56Sopenharmony_ci string = PyUnicode_AsUTF8AndSize(repr, &size); 22217db96d56Sopenharmony_ci if (string == NULL) 22227db96d56Sopenharmony_ci goto error; 22237db96d56Sopenharmony_ci 22247db96d56Sopenharmony_ci if (_Pickler_Write(self, &long_op, 1) < 0 || 22257db96d56Sopenharmony_ci _Pickler_Write(self, string, size) < 0 || 22267db96d56Sopenharmony_ci _Pickler_Write(self, "L\n", 2) < 0) 22277db96d56Sopenharmony_ci goto error; 22287db96d56Sopenharmony_ci } 22297db96d56Sopenharmony_ci 22307db96d56Sopenharmony_ci if (0) { 22317db96d56Sopenharmony_ci error: 22327db96d56Sopenharmony_ci status = -1; 22337db96d56Sopenharmony_ci } 22347db96d56Sopenharmony_ci Py_XDECREF(repr); 22357db96d56Sopenharmony_ci 22367db96d56Sopenharmony_ci return status; 22377db96d56Sopenharmony_ci} 22387db96d56Sopenharmony_ci 22397db96d56Sopenharmony_cistatic int 22407db96d56Sopenharmony_cisave_float(PicklerObject *self, PyObject *obj) 22417db96d56Sopenharmony_ci{ 22427db96d56Sopenharmony_ci double x = PyFloat_AS_DOUBLE((PyFloatObject *)obj); 22437db96d56Sopenharmony_ci 22447db96d56Sopenharmony_ci if (self->bin) { 22457db96d56Sopenharmony_ci char pdata[9]; 22467db96d56Sopenharmony_ci pdata[0] = BINFLOAT; 22477db96d56Sopenharmony_ci if (PyFloat_Pack8(x, &pdata[1], 0) < 0) 22487db96d56Sopenharmony_ci return -1; 22497db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, 9) < 0) 22507db96d56Sopenharmony_ci return -1; 22517db96d56Sopenharmony_ci } 22527db96d56Sopenharmony_ci else { 22537db96d56Sopenharmony_ci int result = -1; 22547db96d56Sopenharmony_ci char *buf = NULL; 22557db96d56Sopenharmony_ci char op = FLOAT; 22567db96d56Sopenharmony_ci 22577db96d56Sopenharmony_ci if (_Pickler_Write(self, &op, 1) < 0) 22587db96d56Sopenharmony_ci goto done; 22597db96d56Sopenharmony_ci 22607db96d56Sopenharmony_ci buf = PyOS_double_to_string(x, 'r', 0, Py_DTSF_ADD_DOT_0, NULL); 22617db96d56Sopenharmony_ci if (!buf) { 22627db96d56Sopenharmony_ci PyErr_NoMemory(); 22637db96d56Sopenharmony_ci goto done; 22647db96d56Sopenharmony_ci } 22657db96d56Sopenharmony_ci 22667db96d56Sopenharmony_ci if (_Pickler_Write(self, buf, strlen(buf)) < 0) 22677db96d56Sopenharmony_ci goto done; 22687db96d56Sopenharmony_ci 22697db96d56Sopenharmony_ci if (_Pickler_Write(self, "\n", 1) < 0) 22707db96d56Sopenharmony_ci goto done; 22717db96d56Sopenharmony_ci 22727db96d56Sopenharmony_ci result = 0; 22737db96d56Sopenharmony_cidone: 22747db96d56Sopenharmony_ci PyMem_Free(buf); 22757db96d56Sopenharmony_ci return result; 22767db96d56Sopenharmony_ci } 22777db96d56Sopenharmony_ci 22787db96d56Sopenharmony_ci return 0; 22797db96d56Sopenharmony_ci} 22807db96d56Sopenharmony_ci 22817db96d56Sopenharmony_ci/* Perform direct write of the header and payload of the binary object. 22827db96d56Sopenharmony_ci 22837db96d56Sopenharmony_ci The large contiguous data is written directly into the underlying file 22847db96d56Sopenharmony_ci object, bypassing the output_buffer of the Pickler. We intentionally 22857db96d56Sopenharmony_ci do not insert a protocol 4 frame opcode to make it possible to optimize 22867db96d56Sopenharmony_ci file.read calls in the loader. 22877db96d56Sopenharmony_ci */ 22887db96d56Sopenharmony_cistatic int 22897db96d56Sopenharmony_ci_Pickler_write_bytes(PicklerObject *self, 22907db96d56Sopenharmony_ci const char *header, Py_ssize_t header_size, 22917db96d56Sopenharmony_ci const char *data, Py_ssize_t data_size, 22927db96d56Sopenharmony_ci PyObject *payload) 22937db96d56Sopenharmony_ci{ 22947db96d56Sopenharmony_ci int bypass_buffer = (data_size >= FRAME_SIZE_TARGET); 22957db96d56Sopenharmony_ci int framing = self->framing; 22967db96d56Sopenharmony_ci 22977db96d56Sopenharmony_ci if (bypass_buffer) { 22987db96d56Sopenharmony_ci assert(self->output_buffer != NULL); 22997db96d56Sopenharmony_ci /* Commit the previous frame. */ 23007db96d56Sopenharmony_ci if (_Pickler_CommitFrame(self)) { 23017db96d56Sopenharmony_ci return -1; 23027db96d56Sopenharmony_ci } 23037db96d56Sopenharmony_ci /* Disable framing temporarily */ 23047db96d56Sopenharmony_ci self->framing = 0; 23057db96d56Sopenharmony_ci } 23067db96d56Sopenharmony_ci 23077db96d56Sopenharmony_ci if (_Pickler_Write(self, header, header_size) < 0) { 23087db96d56Sopenharmony_ci return -1; 23097db96d56Sopenharmony_ci } 23107db96d56Sopenharmony_ci 23117db96d56Sopenharmony_ci if (bypass_buffer && self->write != NULL) { 23127db96d56Sopenharmony_ci /* Bypass the in-memory buffer to directly stream large data 23137db96d56Sopenharmony_ci into the underlying file object. */ 23147db96d56Sopenharmony_ci PyObject *result, *mem = NULL; 23157db96d56Sopenharmony_ci /* Dump the output buffer to the file. */ 23167db96d56Sopenharmony_ci if (_Pickler_FlushToFile(self) < 0) { 23177db96d56Sopenharmony_ci return -1; 23187db96d56Sopenharmony_ci } 23197db96d56Sopenharmony_ci 23207db96d56Sopenharmony_ci /* Stream write the payload into the file without going through the 23217db96d56Sopenharmony_ci output buffer. */ 23227db96d56Sopenharmony_ci if (payload == NULL) { 23237db96d56Sopenharmony_ci /* TODO: It would be better to use a memoryview with a linked 23247db96d56Sopenharmony_ci original string if this is possible. */ 23257db96d56Sopenharmony_ci payload = mem = PyBytes_FromStringAndSize(data, data_size); 23267db96d56Sopenharmony_ci if (payload == NULL) { 23277db96d56Sopenharmony_ci return -1; 23287db96d56Sopenharmony_ci } 23297db96d56Sopenharmony_ci } 23307db96d56Sopenharmony_ci result = PyObject_CallOneArg(self->write, payload); 23317db96d56Sopenharmony_ci Py_XDECREF(mem); 23327db96d56Sopenharmony_ci if (result == NULL) { 23337db96d56Sopenharmony_ci return -1; 23347db96d56Sopenharmony_ci } 23357db96d56Sopenharmony_ci Py_DECREF(result); 23367db96d56Sopenharmony_ci 23377db96d56Sopenharmony_ci /* Reinitialize the buffer for subsequent calls to _Pickler_Write. */ 23387db96d56Sopenharmony_ci if (_Pickler_ClearBuffer(self) < 0) { 23397db96d56Sopenharmony_ci return -1; 23407db96d56Sopenharmony_ci } 23417db96d56Sopenharmony_ci } 23427db96d56Sopenharmony_ci else { 23437db96d56Sopenharmony_ci if (_Pickler_Write(self, data, data_size) < 0) { 23447db96d56Sopenharmony_ci return -1; 23457db96d56Sopenharmony_ci } 23467db96d56Sopenharmony_ci } 23477db96d56Sopenharmony_ci 23487db96d56Sopenharmony_ci /* Re-enable framing for subsequent calls to _Pickler_Write. */ 23497db96d56Sopenharmony_ci self->framing = framing; 23507db96d56Sopenharmony_ci 23517db96d56Sopenharmony_ci return 0; 23527db96d56Sopenharmony_ci} 23537db96d56Sopenharmony_ci 23547db96d56Sopenharmony_cistatic int 23557db96d56Sopenharmony_ci_save_bytes_data(PicklerObject *self, PyObject *obj, const char *data, 23567db96d56Sopenharmony_ci Py_ssize_t size) 23577db96d56Sopenharmony_ci{ 23587db96d56Sopenharmony_ci assert(self->proto >= 3); 23597db96d56Sopenharmony_ci 23607db96d56Sopenharmony_ci char header[9]; 23617db96d56Sopenharmony_ci Py_ssize_t len; 23627db96d56Sopenharmony_ci 23637db96d56Sopenharmony_ci if (size < 0) 23647db96d56Sopenharmony_ci return -1; 23657db96d56Sopenharmony_ci 23667db96d56Sopenharmony_ci if (size <= 0xff) { 23677db96d56Sopenharmony_ci header[0] = SHORT_BINBYTES; 23687db96d56Sopenharmony_ci header[1] = (unsigned char)size; 23697db96d56Sopenharmony_ci len = 2; 23707db96d56Sopenharmony_ci } 23717db96d56Sopenharmony_ci else if ((size_t)size <= 0xffffffffUL) { 23727db96d56Sopenharmony_ci header[0] = BINBYTES; 23737db96d56Sopenharmony_ci header[1] = (unsigned char)(size & 0xff); 23747db96d56Sopenharmony_ci header[2] = (unsigned char)((size >> 8) & 0xff); 23757db96d56Sopenharmony_ci header[3] = (unsigned char)((size >> 16) & 0xff); 23767db96d56Sopenharmony_ci header[4] = (unsigned char)((size >> 24) & 0xff); 23777db96d56Sopenharmony_ci len = 5; 23787db96d56Sopenharmony_ci } 23797db96d56Sopenharmony_ci else if (self->proto >= 4) { 23807db96d56Sopenharmony_ci header[0] = BINBYTES8; 23817db96d56Sopenharmony_ci _write_size64(header + 1, size); 23827db96d56Sopenharmony_ci len = 9; 23837db96d56Sopenharmony_ci } 23847db96d56Sopenharmony_ci else { 23857db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 23867db96d56Sopenharmony_ci "serializing a bytes object larger than 4 GiB " 23877db96d56Sopenharmony_ci "requires pickle protocol 4 or higher"); 23887db96d56Sopenharmony_ci return -1; 23897db96d56Sopenharmony_ci } 23907db96d56Sopenharmony_ci 23917db96d56Sopenharmony_ci if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) { 23927db96d56Sopenharmony_ci return -1; 23937db96d56Sopenharmony_ci } 23947db96d56Sopenharmony_ci 23957db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) { 23967db96d56Sopenharmony_ci return -1; 23977db96d56Sopenharmony_ci } 23987db96d56Sopenharmony_ci 23997db96d56Sopenharmony_ci return 0; 24007db96d56Sopenharmony_ci} 24017db96d56Sopenharmony_ci 24027db96d56Sopenharmony_cistatic int 24037db96d56Sopenharmony_cisave_bytes(PicklerObject *self, PyObject *obj) 24047db96d56Sopenharmony_ci{ 24057db96d56Sopenharmony_ci if (self->proto < 3) { 24067db96d56Sopenharmony_ci /* Older pickle protocols do not have an opcode for pickling bytes 24077db96d56Sopenharmony_ci objects. Therefore, we need to fake the copy protocol (i.e., 24087db96d56Sopenharmony_ci the __reduce__ method) to permit bytes object unpickling. 24097db96d56Sopenharmony_ci 24107db96d56Sopenharmony_ci Here we use a hack to be compatible with Python 2. Since in Python 24117db96d56Sopenharmony_ci 2 'bytes' is just an alias for 'str' (which has different 24127db96d56Sopenharmony_ci parameters than the actual bytes object), we use codecs.encode 24137db96d56Sopenharmony_ci to create the appropriate 'str' object when unpickled using 24147db96d56Sopenharmony_ci Python 2 *and* the appropriate 'bytes' object when unpickled 24157db96d56Sopenharmony_ci using Python 3. Again this is a hack and we don't need to do this 24167db96d56Sopenharmony_ci with newer protocols. */ 24177db96d56Sopenharmony_ci PyObject *reduce_value; 24187db96d56Sopenharmony_ci int status; 24197db96d56Sopenharmony_ci 24207db96d56Sopenharmony_ci if (PyBytes_GET_SIZE(obj) == 0) { 24217db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O())", (PyObject*)&PyBytes_Type); 24227db96d56Sopenharmony_ci } 24237db96d56Sopenharmony_ci else { 24247db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 24257db96d56Sopenharmony_ci PyObject *unicode_str = 24267db96d56Sopenharmony_ci PyUnicode_DecodeLatin1(PyBytes_AS_STRING(obj), 24277db96d56Sopenharmony_ci PyBytes_GET_SIZE(obj), 24287db96d56Sopenharmony_ci "strict"); 24297db96d56Sopenharmony_ci 24307db96d56Sopenharmony_ci if (unicode_str == NULL) 24317db96d56Sopenharmony_ci return -1; 24327db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O(OO))", 24337db96d56Sopenharmony_ci st->codecs_encode, unicode_str, 24347db96d56Sopenharmony_ci &_Py_ID(latin1)); 24357db96d56Sopenharmony_ci Py_DECREF(unicode_str); 24367db96d56Sopenharmony_ci } 24377db96d56Sopenharmony_ci 24387db96d56Sopenharmony_ci if (reduce_value == NULL) 24397db96d56Sopenharmony_ci return -1; 24407db96d56Sopenharmony_ci 24417db96d56Sopenharmony_ci /* save_reduce() will memoize the object automatically. */ 24427db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 24437db96d56Sopenharmony_ci Py_DECREF(reduce_value); 24447db96d56Sopenharmony_ci return status; 24457db96d56Sopenharmony_ci } 24467db96d56Sopenharmony_ci else { 24477db96d56Sopenharmony_ci return _save_bytes_data(self, obj, PyBytes_AS_STRING(obj), 24487db96d56Sopenharmony_ci PyBytes_GET_SIZE(obj)); 24497db96d56Sopenharmony_ci } 24507db96d56Sopenharmony_ci} 24517db96d56Sopenharmony_ci 24527db96d56Sopenharmony_cistatic int 24537db96d56Sopenharmony_ci_save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data, 24547db96d56Sopenharmony_ci Py_ssize_t size) 24557db96d56Sopenharmony_ci{ 24567db96d56Sopenharmony_ci assert(self->proto >= 5); 24577db96d56Sopenharmony_ci 24587db96d56Sopenharmony_ci char header[9]; 24597db96d56Sopenharmony_ci Py_ssize_t len; 24607db96d56Sopenharmony_ci 24617db96d56Sopenharmony_ci if (size < 0) 24627db96d56Sopenharmony_ci return -1; 24637db96d56Sopenharmony_ci 24647db96d56Sopenharmony_ci header[0] = BYTEARRAY8; 24657db96d56Sopenharmony_ci _write_size64(header + 1, size); 24667db96d56Sopenharmony_ci len = 9; 24677db96d56Sopenharmony_ci 24687db96d56Sopenharmony_ci if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) { 24697db96d56Sopenharmony_ci return -1; 24707db96d56Sopenharmony_ci } 24717db96d56Sopenharmony_ci 24727db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) { 24737db96d56Sopenharmony_ci return -1; 24747db96d56Sopenharmony_ci } 24757db96d56Sopenharmony_ci 24767db96d56Sopenharmony_ci return 0; 24777db96d56Sopenharmony_ci} 24787db96d56Sopenharmony_ci 24797db96d56Sopenharmony_cistatic int 24807db96d56Sopenharmony_cisave_bytearray(PicklerObject *self, PyObject *obj) 24817db96d56Sopenharmony_ci{ 24827db96d56Sopenharmony_ci if (self->proto < 5) { 24837db96d56Sopenharmony_ci /* Older pickle protocols do not have an opcode for pickling 24847db96d56Sopenharmony_ci * bytearrays. */ 24857db96d56Sopenharmony_ci PyObject *reduce_value = NULL; 24867db96d56Sopenharmony_ci int status; 24877db96d56Sopenharmony_ci 24887db96d56Sopenharmony_ci if (PyByteArray_GET_SIZE(obj) == 0) { 24897db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O())", 24907db96d56Sopenharmony_ci (PyObject *) &PyByteArray_Type); 24917db96d56Sopenharmony_ci } 24927db96d56Sopenharmony_ci else { 24937db96d56Sopenharmony_ci PyObject *bytes_obj = PyBytes_FromObject(obj); 24947db96d56Sopenharmony_ci if (bytes_obj != NULL) { 24957db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O(O))", 24967db96d56Sopenharmony_ci (PyObject *) &PyByteArray_Type, 24977db96d56Sopenharmony_ci bytes_obj); 24987db96d56Sopenharmony_ci Py_DECREF(bytes_obj); 24997db96d56Sopenharmony_ci } 25007db96d56Sopenharmony_ci } 25017db96d56Sopenharmony_ci if (reduce_value == NULL) 25027db96d56Sopenharmony_ci return -1; 25037db96d56Sopenharmony_ci 25047db96d56Sopenharmony_ci /* save_reduce() will memoize the object automatically. */ 25057db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 25067db96d56Sopenharmony_ci Py_DECREF(reduce_value); 25077db96d56Sopenharmony_ci return status; 25087db96d56Sopenharmony_ci } 25097db96d56Sopenharmony_ci else { 25107db96d56Sopenharmony_ci return _save_bytearray_data(self, obj, PyByteArray_AS_STRING(obj), 25117db96d56Sopenharmony_ci PyByteArray_GET_SIZE(obj)); 25127db96d56Sopenharmony_ci } 25137db96d56Sopenharmony_ci} 25147db96d56Sopenharmony_ci 25157db96d56Sopenharmony_cistatic int 25167db96d56Sopenharmony_cisave_picklebuffer(PicklerObject *self, PyObject *obj) 25177db96d56Sopenharmony_ci{ 25187db96d56Sopenharmony_ci if (self->proto < 5) { 25197db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 25207db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, 25217db96d56Sopenharmony_ci "PickleBuffer can only pickled with protocol >= 5"); 25227db96d56Sopenharmony_ci return -1; 25237db96d56Sopenharmony_ci } 25247db96d56Sopenharmony_ci const Py_buffer* view = PyPickleBuffer_GetBuffer(obj); 25257db96d56Sopenharmony_ci if (view == NULL) { 25267db96d56Sopenharmony_ci return -1; 25277db96d56Sopenharmony_ci } 25287db96d56Sopenharmony_ci if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) { 25297db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 25307db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, 25317db96d56Sopenharmony_ci "PickleBuffer can not be pickled when " 25327db96d56Sopenharmony_ci "pointing to a non-contiguous buffer"); 25337db96d56Sopenharmony_ci return -1; 25347db96d56Sopenharmony_ci } 25357db96d56Sopenharmony_ci int in_band = 1; 25367db96d56Sopenharmony_ci if (self->buffer_callback != NULL) { 25377db96d56Sopenharmony_ci PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj); 25387db96d56Sopenharmony_ci if (ret == NULL) { 25397db96d56Sopenharmony_ci return -1; 25407db96d56Sopenharmony_ci } 25417db96d56Sopenharmony_ci in_band = PyObject_IsTrue(ret); 25427db96d56Sopenharmony_ci Py_DECREF(ret); 25437db96d56Sopenharmony_ci if (in_band == -1) { 25447db96d56Sopenharmony_ci return -1; 25457db96d56Sopenharmony_ci } 25467db96d56Sopenharmony_ci } 25477db96d56Sopenharmony_ci if (in_band) { 25487db96d56Sopenharmony_ci /* Write data in-band */ 25497db96d56Sopenharmony_ci if (view->readonly) { 25507db96d56Sopenharmony_ci return _save_bytes_data(self, obj, (const char*) view->buf, 25517db96d56Sopenharmony_ci view->len); 25527db96d56Sopenharmony_ci } 25537db96d56Sopenharmony_ci else { 25547db96d56Sopenharmony_ci return _save_bytearray_data(self, obj, (const char*) view->buf, 25557db96d56Sopenharmony_ci view->len); 25567db96d56Sopenharmony_ci } 25577db96d56Sopenharmony_ci } 25587db96d56Sopenharmony_ci else { 25597db96d56Sopenharmony_ci /* Write data out-of-band */ 25607db96d56Sopenharmony_ci const char next_buffer_op = NEXT_BUFFER; 25617db96d56Sopenharmony_ci if (_Pickler_Write(self, &next_buffer_op, 1) < 0) { 25627db96d56Sopenharmony_ci return -1; 25637db96d56Sopenharmony_ci } 25647db96d56Sopenharmony_ci if (view->readonly) { 25657db96d56Sopenharmony_ci const char readonly_buffer_op = READONLY_BUFFER; 25667db96d56Sopenharmony_ci if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) { 25677db96d56Sopenharmony_ci return -1; 25687db96d56Sopenharmony_ci } 25697db96d56Sopenharmony_ci } 25707db96d56Sopenharmony_ci } 25717db96d56Sopenharmony_ci return 0; 25727db96d56Sopenharmony_ci} 25737db96d56Sopenharmony_ci 25747db96d56Sopenharmony_ci/* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates 25757db96d56Sopenharmony_ci backslash and newline characters to \uXXXX escapes. */ 25767db96d56Sopenharmony_cistatic PyObject * 25777db96d56Sopenharmony_ciraw_unicode_escape(PyObject *obj) 25787db96d56Sopenharmony_ci{ 25797db96d56Sopenharmony_ci char *p; 25807db96d56Sopenharmony_ci Py_ssize_t i, size; 25817db96d56Sopenharmony_ci const void *data; 25827db96d56Sopenharmony_ci unsigned int kind; 25837db96d56Sopenharmony_ci _PyBytesWriter writer; 25847db96d56Sopenharmony_ci 25857db96d56Sopenharmony_ci if (PyUnicode_READY(obj)) 25867db96d56Sopenharmony_ci return NULL; 25877db96d56Sopenharmony_ci 25887db96d56Sopenharmony_ci _PyBytesWriter_Init(&writer); 25897db96d56Sopenharmony_ci 25907db96d56Sopenharmony_ci size = PyUnicode_GET_LENGTH(obj); 25917db96d56Sopenharmony_ci data = PyUnicode_DATA(obj); 25927db96d56Sopenharmony_ci kind = PyUnicode_KIND(obj); 25937db96d56Sopenharmony_ci 25947db96d56Sopenharmony_ci p = _PyBytesWriter_Alloc(&writer, size); 25957db96d56Sopenharmony_ci if (p == NULL) 25967db96d56Sopenharmony_ci goto error; 25977db96d56Sopenharmony_ci writer.overallocate = 1; 25987db96d56Sopenharmony_ci 25997db96d56Sopenharmony_ci for (i=0; i < size; i++) { 26007db96d56Sopenharmony_ci Py_UCS4 ch = PyUnicode_READ(kind, data, i); 26017db96d56Sopenharmony_ci /* Map 32-bit characters to '\Uxxxxxxxx' */ 26027db96d56Sopenharmony_ci if (ch >= 0x10000) { 26037db96d56Sopenharmony_ci /* -1: subtract 1 preallocated byte */ 26047db96d56Sopenharmony_ci p = _PyBytesWriter_Prepare(&writer, p, 10-1); 26057db96d56Sopenharmony_ci if (p == NULL) 26067db96d56Sopenharmony_ci goto error; 26077db96d56Sopenharmony_ci 26087db96d56Sopenharmony_ci *p++ = '\\'; 26097db96d56Sopenharmony_ci *p++ = 'U'; 26107db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 28) & 0xf]; 26117db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 24) & 0xf]; 26127db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 20) & 0xf]; 26137db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 16) & 0xf]; 26147db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 12) & 0xf]; 26157db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 8) & 0xf]; 26167db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 4) & 0xf]; 26177db96d56Sopenharmony_ci *p++ = Py_hexdigits[ch & 15]; 26187db96d56Sopenharmony_ci } 26197db96d56Sopenharmony_ci /* Map 16-bit characters, '\\' and '\n' to '\uxxxx' */ 26207db96d56Sopenharmony_ci else if (ch >= 256 || 26217db96d56Sopenharmony_ci ch == '\\' || ch == 0 || ch == '\n' || ch == '\r' || 26227db96d56Sopenharmony_ci ch == 0x1a) 26237db96d56Sopenharmony_ci { 26247db96d56Sopenharmony_ci /* -1: subtract 1 preallocated byte */ 26257db96d56Sopenharmony_ci p = _PyBytesWriter_Prepare(&writer, p, 6-1); 26267db96d56Sopenharmony_ci if (p == NULL) 26277db96d56Sopenharmony_ci goto error; 26287db96d56Sopenharmony_ci 26297db96d56Sopenharmony_ci *p++ = '\\'; 26307db96d56Sopenharmony_ci *p++ = 'u'; 26317db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 12) & 0xf]; 26327db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 8) & 0xf]; 26337db96d56Sopenharmony_ci *p++ = Py_hexdigits[(ch >> 4) & 0xf]; 26347db96d56Sopenharmony_ci *p++ = Py_hexdigits[ch & 15]; 26357db96d56Sopenharmony_ci } 26367db96d56Sopenharmony_ci /* Copy everything else as-is */ 26377db96d56Sopenharmony_ci else 26387db96d56Sopenharmony_ci *p++ = (char) ch; 26397db96d56Sopenharmony_ci } 26407db96d56Sopenharmony_ci 26417db96d56Sopenharmony_ci return _PyBytesWriter_Finish(&writer, p); 26427db96d56Sopenharmony_ci 26437db96d56Sopenharmony_cierror: 26447db96d56Sopenharmony_ci _PyBytesWriter_Dealloc(&writer); 26457db96d56Sopenharmony_ci return NULL; 26467db96d56Sopenharmony_ci} 26477db96d56Sopenharmony_ci 26487db96d56Sopenharmony_cistatic int 26497db96d56Sopenharmony_ciwrite_unicode_binary(PicklerObject *self, PyObject *obj) 26507db96d56Sopenharmony_ci{ 26517db96d56Sopenharmony_ci char header[9]; 26527db96d56Sopenharmony_ci Py_ssize_t len; 26537db96d56Sopenharmony_ci PyObject *encoded = NULL; 26547db96d56Sopenharmony_ci Py_ssize_t size; 26557db96d56Sopenharmony_ci const char *data; 26567db96d56Sopenharmony_ci 26577db96d56Sopenharmony_ci if (PyUnicode_READY(obj)) 26587db96d56Sopenharmony_ci return -1; 26597db96d56Sopenharmony_ci 26607db96d56Sopenharmony_ci data = PyUnicode_AsUTF8AndSize(obj, &size); 26617db96d56Sopenharmony_ci if (data == NULL) { 26627db96d56Sopenharmony_ci /* Issue #8383: for strings with lone surrogates, fallback on the 26637db96d56Sopenharmony_ci "surrogatepass" error handler. */ 26647db96d56Sopenharmony_ci PyErr_Clear(); 26657db96d56Sopenharmony_ci encoded = PyUnicode_AsEncodedString(obj, "utf-8", "surrogatepass"); 26667db96d56Sopenharmony_ci if (encoded == NULL) 26677db96d56Sopenharmony_ci return -1; 26687db96d56Sopenharmony_ci 26697db96d56Sopenharmony_ci data = PyBytes_AS_STRING(encoded); 26707db96d56Sopenharmony_ci size = PyBytes_GET_SIZE(encoded); 26717db96d56Sopenharmony_ci } 26727db96d56Sopenharmony_ci 26737db96d56Sopenharmony_ci assert(size >= 0); 26747db96d56Sopenharmony_ci if (size <= 0xff && self->proto >= 4) { 26757db96d56Sopenharmony_ci header[0] = SHORT_BINUNICODE; 26767db96d56Sopenharmony_ci header[1] = (unsigned char)(size & 0xff); 26777db96d56Sopenharmony_ci len = 2; 26787db96d56Sopenharmony_ci } 26797db96d56Sopenharmony_ci else if ((size_t)size <= 0xffffffffUL) { 26807db96d56Sopenharmony_ci header[0] = BINUNICODE; 26817db96d56Sopenharmony_ci header[1] = (unsigned char)(size & 0xff); 26827db96d56Sopenharmony_ci header[2] = (unsigned char)((size >> 8) & 0xff); 26837db96d56Sopenharmony_ci header[3] = (unsigned char)((size >> 16) & 0xff); 26847db96d56Sopenharmony_ci header[4] = (unsigned char)((size >> 24) & 0xff); 26857db96d56Sopenharmony_ci len = 5; 26867db96d56Sopenharmony_ci } 26877db96d56Sopenharmony_ci else if (self->proto >= 4) { 26887db96d56Sopenharmony_ci header[0] = BINUNICODE8; 26897db96d56Sopenharmony_ci _write_size64(header + 1, size); 26907db96d56Sopenharmony_ci len = 9; 26917db96d56Sopenharmony_ci } 26927db96d56Sopenharmony_ci else { 26937db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 26947db96d56Sopenharmony_ci "serializing a string larger than 4 GiB " 26957db96d56Sopenharmony_ci "requires pickle protocol 4 or higher"); 26967db96d56Sopenharmony_ci Py_XDECREF(encoded); 26977db96d56Sopenharmony_ci return -1; 26987db96d56Sopenharmony_ci } 26997db96d56Sopenharmony_ci 27007db96d56Sopenharmony_ci if (_Pickler_write_bytes(self, header, len, data, size, encoded) < 0) { 27017db96d56Sopenharmony_ci Py_XDECREF(encoded); 27027db96d56Sopenharmony_ci return -1; 27037db96d56Sopenharmony_ci } 27047db96d56Sopenharmony_ci Py_XDECREF(encoded); 27057db96d56Sopenharmony_ci return 0; 27067db96d56Sopenharmony_ci} 27077db96d56Sopenharmony_ci 27087db96d56Sopenharmony_cistatic int 27097db96d56Sopenharmony_cisave_unicode(PicklerObject *self, PyObject *obj) 27107db96d56Sopenharmony_ci{ 27117db96d56Sopenharmony_ci if (self->bin) { 27127db96d56Sopenharmony_ci if (write_unicode_binary(self, obj) < 0) 27137db96d56Sopenharmony_ci return -1; 27147db96d56Sopenharmony_ci } 27157db96d56Sopenharmony_ci else { 27167db96d56Sopenharmony_ci PyObject *encoded; 27177db96d56Sopenharmony_ci Py_ssize_t size; 27187db96d56Sopenharmony_ci const char unicode_op = UNICODE; 27197db96d56Sopenharmony_ci 27207db96d56Sopenharmony_ci encoded = raw_unicode_escape(obj); 27217db96d56Sopenharmony_ci if (encoded == NULL) 27227db96d56Sopenharmony_ci return -1; 27237db96d56Sopenharmony_ci 27247db96d56Sopenharmony_ci if (_Pickler_Write(self, &unicode_op, 1) < 0) { 27257db96d56Sopenharmony_ci Py_DECREF(encoded); 27267db96d56Sopenharmony_ci return -1; 27277db96d56Sopenharmony_ci } 27287db96d56Sopenharmony_ci 27297db96d56Sopenharmony_ci size = PyBytes_GET_SIZE(encoded); 27307db96d56Sopenharmony_ci if (_Pickler_Write(self, PyBytes_AS_STRING(encoded), size) < 0) { 27317db96d56Sopenharmony_ci Py_DECREF(encoded); 27327db96d56Sopenharmony_ci return -1; 27337db96d56Sopenharmony_ci } 27347db96d56Sopenharmony_ci Py_DECREF(encoded); 27357db96d56Sopenharmony_ci 27367db96d56Sopenharmony_ci if (_Pickler_Write(self, "\n", 1) < 0) 27377db96d56Sopenharmony_ci return -1; 27387db96d56Sopenharmony_ci } 27397db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 27407db96d56Sopenharmony_ci return -1; 27417db96d56Sopenharmony_ci 27427db96d56Sopenharmony_ci return 0; 27437db96d56Sopenharmony_ci} 27447db96d56Sopenharmony_ci 27457db96d56Sopenharmony_ci/* A helper for save_tuple. Push the len elements in tuple t on the stack. */ 27467db96d56Sopenharmony_cistatic int 27477db96d56Sopenharmony_cistore_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len) 27487db96d56Sopenharmony_ci{ 27497db96d56Sopenharmony_ci Py_ssize_t i; 27507db96d56Sopenharmony_ci 27517db96d56Sopenharmony_ci assert(PyTuple_Size(t) == len); 27527db96d56Sopenharmony_ci 27537db96d56Sopenharmony_ci for (i = 0; i < len; i++) { 27547db96d56Sopenharmony_ci PyObject *element = PyTuple_GET_ITEM(t, i); 27557db96d56Sopenharmony_ci 27567db96d56Sopenharmony_ci if (element == NULL) 27577db96d56Sopenharmony_ci return -1; 27587db96d56Sopenharmony_ci if (save(self, element, 0) < 0) 27597db96d56Sopenharmony_ci return -1; 27607db96d56Sopenharmony_ci } 27617db96d56Sopenharmony_ci 27627db96d56Sopenharmony_ci return 0; 27637db96d56Sopenharmony_ci} 27647db96d56Sopenharmony_ci 27657db96d56Sopenharmony_ci/* Tuples are ubiquitous in the pickle protocols, so many techniques are 27667db96d56Sopenharmony_ci * used across protocols to minimize the space needed to pickle them. 27677db96d56Sopenharmony_ci * Tuples are also the only builtin immutable type that can be recursive 27687db96d56Sopenharmony_ci * (a tuple can be reached from itself), and that requires some subtle 27697db96d56Sopenharmony_ci * magic so that it works in all cases. IOW, this is a long routine. 27707db96d56Sopenharmony_ci */ 27717db96d56Sopenharmony_cistatic int 27727db96d56Sopenharmony_cisave_tuple(PicklerObject *self, PyObject *obj) 27737db96d56Sopenharmony_ci{ 27747db96d56Sopenharmony_ci Py_ssize_t len, i; 27757db96d56Sopenharmony_ci 27767db96d56Sopenharmony_ci const char mark_op = MARK; 27777db96d56Sopenharmony_ci const char tuple_op = TUPLE; 27787db96d56Sopenharmony_ci const char pop_op = POP; 27797db96d56Sopenharmony_ci const char pop_mark_op = POP_MARK; 27807db96d56Sopenharmony_ci const char len2opcode[] = {EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3}; 27817db96d56Sopenharmony_ci 27827db96d56Sopenharmony_ci if ((len = PyTuple_Size(obj)) < 0) 27837db96d56Sopenharmony_ci return -1; 27847db96d56Sopenharmony_ci 27857db96d56Sopenharmony_ci if (len == 0) { 27867db96d56Sopenharmony_ci char pdata[2]; 27877db96d56Sopenharmony_ci 27887db96d56Sopenharmony_ci if (self->proto) { 27897db96d56Sopenharmony_ci pdata[0] = EMPTY_TUPLE; 27907db96d56Sopenharmony_ci len = 1; 27917db96d56Sopenharmony_ci } 27927db96d56Sopenharmony_ci else { 27937db96d56Sopenharmony_ci pdata[0] = MARK; 27947db96d56Sopenharmony_ci pdata[1] = TUPLE; 27957db96d56Sopenharmony_ci len = 2; 27967db96d56Sopenharmony_ci } 27977db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, len) < 0) 27987db96d56Sopenharmony_ci return -1; 27997db96d56Sopenharmony_ci return 0; 28007db96d56Sopenharmony_ci } 28017db96d56Sopenharmony_ci 28027db96d56Sopenharmony_ci /* The tuple isn't in the memo now. If it shows up there after 28037db96d56Sopenharmony_ci * saving the tuple elements, the tuple must be recursive, in 28047db96d56Sopenharmony_ci * which case we'll pop everything we put on the stack, and fetch 28057db96d56Sopenharmony_ci * its value from the memo. 28067db96d56Sopenharmony_ci */ 28077db96d56Sopenharmony_ci if (len <= 3 && self->proto >= 2) { 28087db96d56Sopenharmony_ci /* Use TUPLE{1,2,3} opcodes. */ 28097db96d56Sopenharmony_ci if (store_tuple_elements(self, obj, len) < 0) 28107db96d56Sopenharmony_ci return -1; 28117db96d56Sopenharmony_ci 28127db96d56Sopenharmony_ci if (PyMemoTable_Get(self->memo, obj)) { 28137db96d56Sopenharmony_ci /* pop the len elements */ 28147db96d56Sopenharmony_ci for (i = 0; i < len; i++) 28157db96d56Sopenharmony_ci if (_Pickler_Write(self, &pop_op, 1) < 0) 28167db96d56Sopenharmony_ci return -1; 28177db96d56Sopenharmony_ci /* fetch from memo */ 28187db96d56Sopenharmony_ci if (memo_get(self, obj) < 0) 28197db96d56Sopenharmony_ci return -1; 28207db96d56Sopenharmony_ci 28217db96d56Sopenharmony_ci return 0; 28227db96d56Sopenharmony_ci } 28237db96d56Sopenharmony_ci else { /* Not recursive. */ 28247db96d56Sopenharmony_ci if (_Pickler_Write(self, len2opcode + len, 1) < 0) 28257db96d56Sopenharmony_ci return -1; 28267db96d56Sopenharmony_ci } 28277db96d56Sopenharmony_ci goto memoize; 28287db96d56Sopenharmony_ci } 28297db96d56Sopenharmony_ci 28307db96d56Sopenharmony_ci /* proto < 2 and len > 0, or proto >= 2 and len > 3. 28317db96d56Sopenharmony_ci * Generate MARK e1 e2 ... TUPLE 28327db96d56Sopenharmony_ci */ 28337db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 28347db96d56Sopenharmony_ci return -1; 28357db96d56Sopenharmony_ci 28367db96d56Sopenharmony_ci if (store_tuple_elements(self, obj, len) < 0) 28377db96d56Sopenharmony_ci return -1; 28387db96d56Sopenharmony_ci 28397db96d56Sopenharmony_ci if (PyMemoTable_Get(self->memo, obj)) { 28407db96d56Sopenharmony_ci /* pop the stack stuff we pushed */ 28417db96d56Sopenharmony_ci if (self->bin) { 28427db96d56Sopenharmony_ci if (_Pickler_Write(self, &pop_mark_op, 1) < 0) 28437db96d56Sopenharmony_ci return -1; 28447db96d56Sopenharmony_ci } 28457db96d56Sopenharmony_ci else { 28467db96d56Sopenharmony_ci /* Note that we pop one more than len, to remove 28477db96d56Sopenharmony_ci * the MARK too. 28487db96d56Sopenharmony_ci */ 28497db96d56Sopenharmony_ci for (i = 0; i <= len; i++) 28507db96d56Sopenharmony_ci if (_Pickler_Write(self, &pop_op, 1) < 0) 28517db96d56Sopenharmony_ci return -1; 28527db96d56Sopenharmony_ci } 28537db96d56Sopenharmony_ci /* fetch from memo */ 28547db96d56Sopenharmony_ci if (memo_get(self, obj) < 0) 28557db96d56Sopenharmony_ci return -1; 28567db96d56Sopenharmony_ci 28577db96d56Sopenharmony_ci return 0; 28587db96d56Sopenharmony_ci } 28597db96d56Sopenharmony_ci else { /* Not recursive. */ 28607db96d56Sopenharmony_ci if (_Pickler_Write(self, &tuple_op, 1) < 0) 28617db96d56Sopenharmony_ci return -1; 28627db96d56Sopenharmony_ci } 28637db96d56Sopenharmony_ci 28647db96d56Sopenharmony_ci memoize: 28657db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 28667db96d56Sopenharmony_ci return -1; 28677db96d56Sopenharmony_ci 28687db96d56Sopenharmony_ci return 0; 28697db96d56Sopenharmony_ci} 28707db96d56Sopenharmony_ci 28717db96d56Sopenharmony_ci/* iter is an iterator giving items, and we batch up chunks of 28727db96d56Sopenharmony_ci * MARK item item ... item APPENDS 28737db96d56Sopenharmony_ci * opcode sequences. Calling code should have arranged to first create an 28747db96d56Sopenharmony_ci * empty list, or list-like object, for the APPENDS to operate on. 28757db96d56Sopenharmony_ci * Returns 0 on success, <0 on error. 28767db96d56Sopenharmony_ci */ 28777db96d56Sopenharmony_cistatic int 28787db96d56Sopenharmony_cibatch_list(PicklerObject *self, PyObject *iter) 28797db96d56Sopenharmony_ci{ 28807db96d56Sopenharmony_ci PyObject *obj = NULL; 28817db96d56Sopenharmony_ci PyObject *firstitem = NULL; 28827db96d56Sopenharmony_ci int i, n; 28837db96d56Sopenharmony_ci 28847db96d56Sopenharmony_ci const char mark_op = MARK; 28857db96d56Sopenharmony_ci const char append_op = APPEND; 28867db96d56Sopenharmony_ci const char appends_op = APPENDS; 28877db96d56Sopenharmony_ci 28887db96d56Sopenharmony_ci assert(iter != NULL); 28897db96d56Sopenharmony_ci 28907db96d56Sopenharmony_ci /* XXX: I think this function could be made faster by avoiding the 28917db96d56Sopenharmony_ci iterator interface and fetching objects directly from list using 28927db96d56Sopenharmony_ci PyList_GET_ITEM. 28937db96d56Sopenharmony_ci */ 28947db96d56Sopenharmony_ci 28957db96d56Sopenharmony_ci if (self->proto == 0) { 28967db96d56Sopenharmony_ci /* APPENDS isn't available; do one at a time. */ 28977db96d56Sopenharmony_ci for (;;) { 28987db96d56Sopenharmony_ci obj = PyIter_Next(iter); 28997db96d56Sopenharmony_ci if (obj == NULL) { 29007db96d56Sopenharmony_ci if (PyErr_Occurred()) 29017db96d56Sopenharmony_ci return -1; 29027db96d56Sopenharmony_ci break; 29037db96d56Sopenharmony_ci } 29047db96d56Sopenharmony_ci i = save(self, obj, 0); 29057db96d56Sopenharmony_ci Py_DECREF(obj); 29067db96d56Sopenharmony_ci if (i < 0) 29077db96d56Sopenharmony_ci return -1; 29087db96d56Sopenharmony_ci if (_Pickler_Write(self, &append_op, 1) < 0) 29097db96d56Sopenharmony_ci return -1; 29107db96d56Sopenharmony_ci } 29117db96d56Sopenharmony_ci return 0; 29127db96d56Sopenharmony_ci } 29137db96d56Sopenharmony_ci 29147db96d56Sopenharmony_ci /* proto > 0: write in batches of BATCHSIZE. */ 29157db96d56Sopenharmony_ci do { 29167db96d56Sopenharmony_ci /* Get first item */ 29177db96d56Sopenharmony_ci firstitem = PyIter_Next(iter); 29187db96d56Sopenharmony_ci if (firstitem == NULL) { 29197db96d56Sopenharmony_ci if (PyErr_Occurred()) 29207db96d56Sopenharmony_ci goto error; 29217db96d56Sopenharmony_ci 29227db96d56Sopenharmony_ci /* nothing more to add */ 29237db96d56Sopenharmony_ci break; 29247db96d56Sopenharmony_ci } 29257db96d56Sopenharmony_ci 29267db96d56Sopenharmony_ci /* Try to get a second item */ 29277db96d56Sopenharmony_ci obj = PyIter_Next(iter); 29287db96d56Sopenharmony_ci if (obj == NULL) { 29297db96d56Sopenharmony_ci if (PyErr_Occurred()) 29307db96d56Sopenharmony_ci goto error; 29317db96d56Sopenharmony_ci 29327db96d56Sopenharmony_ci /* Only one item to write */ 29337db96d56Sopenharmony_ci if (save(self, firstitem, 0) < 0) 29347db96d56Sopenharmony_ci goto error; 29357db96d56Sopenharmony_ci if (_Pickler_Write(self, &append_op, 1) < 0) 29367db96d56Sopenharmony_ci goto error; 29377db96d56Sopenharmony_ci Py_CLEAR(firstitem); 29387db96d56Sopenharmony_ci break; 29397db96d56Sopenharmony_ci } 29407db96d56Sopenharmony_ci 29417db96d56Sopenharmony_ci /* More than one item to write */ 29427db96d56Sopenharmony_ci 29437db96d56Sopenharmony_ci /* Pump out MARK, items, APPENDS. */ 29447db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 29457db96d56Sopenharmony_ci goto error; 29467db96d56Sopenharmony_ci 29477db96d56Sopenharmony_ci if (save(self, firstitem, 0) < 0) 29487db96d56Sopenharmony_ci goto error; 29497db96d56Sopenharmony_ci Py_CLEAR(firstitem); 29507db96d56Sopenharmony_ci n = 1; 29517db96d56Sopenharmony_ci 29527db96d56Sopenharmony_ci /* Fetch and save up to BATCHSIZE items */ 29537db96d56Sopenharmony_ci while (obj) { 29547db96d56Sopenharmony_ci if (save(self, obj, 0) < 0) 29557db96d56Sopenharmony_ci goto error; 29567db96d56Sopenharmony_ci Py_CLEAR(obj); 29577db96d56Sopenharmony_ci n += 1; 29587db96d56Sopenharmony_ci 29597db96d56Sopenharmony_ci if (n == BATCHSIZE) 29607db96d56Sopenharmony_ci break; 29617db96d56Sopenharmony_ci 29627db96d56Sopenharmony_ci obj = PyIter_Next(iter); 29637db96d56Sopenharmony_ci if (obj == NULL) { 29647db96d56Sopenharmony_ci if (PyErr_Occurred()) 29657db96d56Sopenharmony_ci goto error; 29667db96d56Sopenharmony_ci break; 29677db96d56Sopenharmony_ci } 29687db96d56Sopenharmony_ci } 29697db96d56Sopenharmony_ci 29707db96d56Sopenharmony_ci if (_Pickler_Write(self, &appends_op, 1) < 0) 29717db96d56Sopenharmony_ci goto error; 29727db96d56Sopenharmony_ci 29737db96d56Sopenharmony_ci } while (n == BATCHSIZE); 29747db96d56Sopenharmony_ci return 0; 29757db96d56Sopenharmony_ci 29767db96d56Sopenharmony_ci error: 29777db96d56Sopenharmony_ci Py_XDECREF(firstitem); 29787db96d56Sopenharmony_ci Py_XDECREF(obj); 29797db96d56Sopenharmony_ci return -1; 29807db96d56Sopenharmony_ci} 29817db96d56Sopenharmony_ci 29827db96d56Sopenharmony_ci/* This is a variant of batch_list() above, specialized for lists (with no 29837db96d56Sopenharmony_ci * support for list subclasses). Like batch_list(), we batch up chunks of 29847db96d56Sopenharmony_ci * MARK item item ... item APPENDS 29857db96d56Sopenharmony_ci * opcode sequences. Calling code should have arranged to first create an 29867db96d56Sopenharmony_ci * empty list, or list-like object, for the APPENDS to operate on. 29877db96d56Sopenharmony_ci * Returns 0 on success, -1 on error. 29887db96d56Sopenharmony_ci * 29897db96d56Sopenharmony_ci * This version is considerably faster than batch_list(), if less general. 29907db96d56Sopenharmony_ci * 29917db96d56Sopenharmony_ci * Note that this only works for protocols > 0. 29927db96d56Sopenharmony_ci */ 29937db96d56Sopenharmony_cistatic int 29947db96d56Sopenharmony_cibatch_list_exact(PicklerObject *self, PyObject *obj) 29957db96d56Sopenharmony_ci{ 29967db96d56Sopenharmony_ci PyObject *item = NULL; 29977db96d56Sopenharmony_ci Py_ssize_t this_batch, total; 29987db96d56Sopenharmony_ci 29997db96d56Sopenharmony_ci const char append_op = APPEND; 30007db96d56Sopenharmony_ci const char appends_op = APPENDS; 30017db96d56Sopenharmony_ci const char mark_op = MARK; 30027db96d56Sopenharmony_ci 30037db96d56Sopenharmony_ci assert(obj != NULL); 30047db96d56Sopenharmony_ci assert(self->proto > 0); 30057db96d56Sopenharmony_ci assert(PyList_CheckExact(obj)); 30067db96d56Sopenharmony_ci 30077db96d56Sopenharmony_ci if (PyList_GET_SIZE(obj) == 1) { 30087db96d56Sopenharmony_ci item = PyList_GET_ITEM(obj, 0); 30097db96d56Sopenharmony_ci Py_INCREF(item); 30107db96d56Sopenharmony_ci int err = save(self, item, 0); 30117db96d56Sopenharmony_ci Py_DECREF(item); 30127db96d56Sopenharmony_ci if (err < 0) 30137db96d56Sopenharmony_ci return -1; 30147db96d56Sopenharmony_ci if (_Pickler_Write(self, &append_op, 1) < 0) 30157db96d56Sopenharmony_ci return -1; 30167db96d56Sopenharmony_ci return 0; 30177db96d56Sopenharmony_ci } 30187db96d56Sopenharmony_ci 30197db96d56Sopenharmony_ci /* Write in batches of BATCHSIZE. */ 30207db96d56Sopenharmony_ci total = 0; 30217db96d56Sopenharmony_ci do { 30227db96d56Sopenharmony_ci this_batch = 0; 30237db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 30247db96d56Sopenharmony_ci return -1; 30257db96d56Sopenharmony_ci while (total < PyList_GET_SIZE(obj)) { 30267db96d56Sopenharmony_ci item = PyList_GET_ITEM(obj, total); 30277db96d56Sopenharmony_ci Py_INCREF(item); 30287db96d56Sopenharmony_ci int err = save(self, item, 0); 30297db96d56Sopenharmony_ci Py_DECREF(item); 30307db96d56Sopenharmony_ci if (err < 0) 30317db96d56Sopenharmony_ci return -1; 30327db96d56Sopenharmony_ci total++; 30337db96d56Sopenharmony_ci if (++this_batch == BATCHSIZE) 30347db96d56Sopenharmony_ci break; 30357db96d56Sopenharmony_ci } 30367db96d56Sopenharmony_ci if (_Pickler_Write(self, &appends_op, 1) < 0) 30377db96d56Sopenharmony_ci return -1; 30387db96d56Sopenharmony_ci 30397db96d56Sopenharmony_ci } while (total < PyList_GET_SIZE(obj)); 30407db96d56Sopenharmony_ci 30417db96d56Sopenharmony_ci return 0; 30427db96d56Sopenharmony_ci} 30437db96d56Sopenharmony_ci 30447db96d56Sopenharmony_cistatic int 30457db96d56Sopenharmony_cisave_list(PicklerObject *self, PyObject *obj) 30467db96d56Sopenharmony_ci{ 30477db96d56Sopenharmony_ci char header[3]; 30487db96d56Sopenharmony_ci Py_ssize_t len; 30497db96d56Sopenharmony_ci int status = 0; 30507db96d56Sopenharmony_ci 30517db96d56Sopenharmony_ci if (self->fast && !fast_save_enter(self, obj)) 30527db96d56Sopenharmony_ci goto error; 30537db96d56Sopenharmony_ci 30547db96d56Sopenharmony_ci /* Create an empty list. */ 30557db96d56Sopenharmony_ci if (self->bin) { 30567db96d56Sopenharmony_ci header[0] = EMPTY_LIST; 30577db96d56Sopenharmony_ci len = 1; 30587db96d56Sopenharmony_ci } 30597db96d56Sopenharmony_ci else { 30607db96d56Sopenharmony_ci header[0] = MARK; 30617db96d56Sopenharmony_ci header[1] = LIST; 30627db96d56Sopenharmony_ci len = 2; 30637db96d56Sopenharmony_ci } 30647db96d56Sopenharmony_ci 30657db96d56Sopenharmony_ci if (_Pickler_Write(self, header, len) < 0) 30667db96d56Sopenharmony_ci goto error; 30677db96d56Sopenharmony_ci 30687db96d56Sopenharmony_ci /* Get list length, and bow out early if empty. */ 30697db96d56Sopenharmony_ci if ((len = PyList_Size(obj)) < 0) 30707db96d56Sopenharmony_ci goto error; 30717db96d56Sopenharmony_ci 30727db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 30737db96d56Sopenharmony_ci goto error; 30747db96d56Sopenharmony_ci 30757db96d56Sopenharmony_ci if (len != 0) { 30767db96d56Sopenharmony_ci /* Materialize the list elements. */ 30777db96d56Sopenharmony_ci if (PyList_CheckExact(obj) && self->proto > 0) { 30787db96d56Sopenharmony_ci if (_Py_EnterRecursiveCall(" while pickling an object")) 30797db96d56Sopenharmony_ci goto error; 30807db96d56Sopenharmony_ci status = batch_list_exact(self, obj); 30817db96d56Sopenharmony_ci _Py_LeaveRecursiveCall(); 30827db96d56Sopenharmony_ci } else { 30837db96d56Sopenharmony_ci PyObject *iter = PyObject_GetIter(obj); 30847db96d56Sopenharmony_ci if (iter == NULL) 30857db96d56Sopenharmony_ci goto error; 30867db96d56Sopenharmony_ci 30877db96d56Sopenharmony_ci if (_Py_EnterRecursiveCall(" while pickling an object")) { 30887db96d56Sopenharmony_ci Py_DECREF(iter); 30897db96d56Sopenharmony_ci goto error; 30907db96d56Sopenharmony_ci } 30917db96d56Sopenharmony_ci status = batch_list(self, iter); 30927db96d56Sopenharmony_ci _Py_LeaveRecursiveCall(); 30937db96d56Sopenharmony_ci Py_DECREF(iter); 30947db96d56Sopenharmony_ci } 30957db96d56Sopenharmony_ci } 30967db96d56Sopenharmony_ci if (0) { 30977db96d56Sopenharmony_ci error: 30987db96d56Sopenharmony_ci status = -1; 30997db96d56Sopenharmony_ci } 31007db96d56Sopenharmony_ci 31017db96d56Sopenharmony_ci if (self->fast && !fast_save_leave(self, obj)) 31027db96d56Sopenharmony_ci status = -1; 31037db96d56Sopenharmony_ci 31047db96d56Sopenharmony_ci return status; 31057db96d56Sopenharmony_ci} 31067db96d56Sopenharmony_ci 31077db96d56Sopenharmony_ci/* iter is an iterator giving (key, value) pairs, and we batch up chunks of 31087db96d56Sopenharmony_ci * MARK key value ... key value SETITEMS 31097db96d56Sopenharmony_ci * opcode sequences. Calling code should have arranged to first create an 31107db96d56Sopenharmony_ci * empty dict, or dict-like object, for the SETITEMS to operate on. 31117db96d56Sopenharmony_ci * Returns 0 on success, <0 on error. 31127db96d56Sopenharmony_ci * 31137db96d56Sopenharmony_ci * This is very much like batch_list(). The difference between saving 31147db96d56Sopenharmony_ci * elements directly, and picking apart two-tuples, is so long-winded at 31157db96d56Sopenharmony_ci * the C level, though, that attempts to combine these routines were too 31167db96d56Sopenharmony_ci * ugly to bear. 31177db96d56Sopenharmony_ci */ 31187db96d56Sopenharmony_cistatic int 31197db96d56Sopenharmony_cibatch_dict(PicklerObject *self, PyObject *iter) 31207db96d56Sopenharmony_ci{ 31217db96d56Sopenharmony_ci PyObject *obj = NULL; 31227db96d56Sopenharmony_ci PyObject *firstitem = NULL; 31237db96d56Sopenharmony_ci int i, n; 31247db96d56Sopenharmony_ci 31257db96d56Sopenharmony_ci const char mark_op = MARK; 31267db96d56Sopenharmony_ci const char setitem_op = SETITEM; 31277db96d56Sopenharmony_ci const char setitems_op = SETITEMS; 31287db96d56Sopenharmony_ci 31297db96d56Sopenharmony_ci assert(iter != NULL); 31307db96d56Sopenharmony_ci 31317db96d56Sopenharmony_ci if (self->proto == 0) { 31327db96d56Sopenharmony_ci /* SETITEMS isn't available; do one at a time. */ 31337db96d56Sopenharmony_ci for (;;) { 31347db96d56Sopenharmony_ci obj = PyIter_Next(iter); 31357db96d56Sopenharmony_ci if (obj == NULL) { 31367db96d56Sopenharmony_ci if (PyErr_Occurred()) 31377db96d56Sopenharmony_ci return -1; 31387db96d56Sopenharmony_ci break; 31397db96d56Sopenharmony_ci } 31407db96d56Sopenharmony_ci if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) { 31417db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "dict items " 31427db96d56Sopenharmony_ci "iterator must return 2-tuples"); 31437db96d56Sopenharmony_ci return -1; 31447db96d56Sopenharmony_ci } 31457db96d56Sopenharmony_ci i = save(self, PyTuple_GET_ITEM(obj, 0), 0); 31467db96d56Sopenharmony_ci if (i >= 0) 31477db96d56Sopenharmony_ci i = save(self, PyTuple_GET_ITEM(obj, 1), 0); 31487db96d56Sopenharmony_ci Py_DECREF(obj); 31497db96d56Sopenharmony_ci if (i < 0) 31507db96d56Sopenharmony_ci return -1; 31517db96d56Sopenharmony_ci if (_Pickler_Write(self, &setitem_op, 1) < 0) 31527db96d56Sopenharmony_ci return -1; 31537db96d56Sopenharmony_ci } 31547db96d56Sopenharmony_ci return 0; 31557db96d56Sopenharmony_ci } 31567db96d56Sopenharmony_ci 31577db96d56Sopenharmony_ci /* proto > 0: write in batches of BATCHSIZE. */ 31587db96d56Sopenharmony_ci do { 31597db96d56Sopenharmony_ci /* Get first item */ 31607db96d56Sopenharmony_ci firstitem = PyIter_Next(iter); 31617db96d56Sopenharmony_ci if (firstitem == NULL) { 31627db96d56Sopenharmony_ci if (PyErr_Occurred()) 31637db96d56Sopenharmony_ci goto error; 31647db96d56Sopenharmony_ci 31657db96d56Sopenharmony_ci /* nothing more to add */ 31667db96d56Sopenharmony_ci break; 31677db96d56Sopenharmony_ci } 31687db96d56Sopenharmony_ci if (!PyTuple_Check(firstitem) || PyTuple_Size(firstitem) != 2) { 31697db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "dict items " 31707db96d56Sopenharmony_ci "iterator must return 2-tuples"); 31717db96d56Sopenharmony_ci goto error; 31727db96d56Sopenharmony_ci } 31737db96d56Sopenharmony_ci 31747db96d56Sopenharmony_ci /* Try to get a second item */ 31757db96d56Sopenharmony_ci obj = PyIter_Next(iter); 31767db96d56Sopenharmony_ci if (obj == NULL) { 31777db96d56Sopenharmony_ci if (PyErr_Occurred()) 31787db96d56Sopenharmony_ci goto error; 31797db96d56Sopenharmony_ci 31807db96d56Sopenharmony_ci /* Only one item to write */ 31817db96d56Sopenharmony_ci if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0) 31827db96d56Sopenharmony_ci goto error; 31837db96d56Sopenharmony_ci if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0) 31847db96d56Sopenharmony_ci goto error; 31857db96d56Sopenharmony_ci if (_Pickler_Write(self, &setitem_op, 1) < 0) 31867db96d56Sopenharmony_ci goto error; 31877db96d56Sopenharmony_ci Py_CLEAR(firstitem); 31887db96d56Sopenharmony_ci break; 31897db96d56Sopenharmony_ci } 31907db96d56Sopenharmony_ci 31917db96d56Sopenharmony_ci /* More than one item to write */ 31927db96d56Sopenharmony_ci 31937db96d56Sopenharmony_ci /* Pump out MARK, items, SETITEMS. */ 31947db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 31957db96d56Sopenharmony_ci goto error; 31967db96d56Sopenharmony_ci 31977db96d56Sopenharmony_ci if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0) 31987db96d56Sopenharmony_ci goto error; 31997db96d56Sopenharmony_ci if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0) 32007db96d56Sopenharmony_ci goto error; 32017db96d56Sopenharmony_ci Py_CLEAR(firstitem); 32027db96d56Sopenharmony_ci n = 1; 32037db96d56Sopenharmony_ci 32047db96d56Sopenharmony_ci /* Fetch and save up to BATCHSIZE items */ 32057db96d56Sopenharmony_ci while (obj) { 32067db96d56Sopenharmony_ci if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) { 32077db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "dict items " 32087db96d56Sopenharmony_ci "iterator must return 2-tuples"); 32097db96d56Sopenharmony_ci goto error; 32107db96d56Sopenharmony_ci } 32117db96d56Sopenharmony_ci if (save(self, PyTuple_GET_ITEM(obj, 0), 0) < 0 || 32127db96d56Sopenharmony_ci save(self, PyTuple_GET_ITEM(obj, 1), 0) < 0) 32137db96d56Sopenharmony_ci goto error; 32147db96d56Sopenharmony_ci Py_CLEAR(obj); 32157db96d56Sopenharmony_ci n += 1; 32167db96d56Sopenharmony_ci 32177db96d56Sopenharmony_ci if (n == BATCHSIZE) 32187db96d56Sopenharmony_ci break; 32197db96d56Sopenharmony_ci 32207db96d56Sopenharmony_ci obj = PyIter_Next(iter); 32217db96d56Sopenharmony_ci if (obj == NULL) { 32227db96d56Sopenharmony_ci if (PyErr_Occurred()) 32237db96d56Sopenharmony_ci goto error; 32247db96d56Sopenharmony_ci break; 32257db96d56Sopenharmony_ci } 32267db96d56Sopenharmony_ci } 32277db96d56Sopenharmony_ci 32287db96d56Sopenharmony_ci if (_Pickler_Write(self, &setitems_op, 1) < 0) 32297db96d56Sopenharmony_ci goto error; 32307db96d56Sopenharmony_ci 32317db96d56Sopenharmony_ci } while (n == BATCHSIZE); 32327db96d56Sopenharmony_ci return 0; 32337db96d56Sopenharmony_ci 32347db96d56Sopenharmony_ci error: 32357db96d56Sopenharmony_ci Py_XDECREF(firstitem); 32367db96d56Sopenharmony_ci Py_XDECREF(obj); 32377db96d56Sopenharmony_ci return -1; 32387db96d56Sopenharmony_ci} 32397db96d56Sopenharmony_ci 32407db96d56Sopenharmony_ci/* This is a variant of batch_dict() above that specializes for dicts, with no 32417db96d56Sopenharmony_ci * support for dict subclasses. Like batch_dict(), we batch up chunks of 32427db96d56Sopenharmony_ci * MARK key value ... key value SETITEMS 32437db96d56Sopenharmony_ci * opcode sequences. Calling code should have arranged to first create an 32447db96d56Sopenharmony_ci * empty dict, or dict-like object, for the SETITEMS to operate on. 32457db96d56Sopenharmony_ci * Returns 0 on success, -1 on error. 32467db96d56Sopenharmony_ci * 32477db96d56Sopenharmony_ci * Note that this currently doesn't work for protocol 0. 32487db96d56Sopenharmony_ci */ 32497db96d56Sopenharmony_cistatic int 32507db96d56Sopenharmony_cibatch_dict_exact(PicklerObject *self, PyObject *obj) 32517db96d56Sopenharmony_ci{ 32527db96d56Sopenharmony_ci PyObject *key = NULL, *value = NULL; 32537db96d56Sopenharmony_ci int i; 32547db96d56Sopenharmony_ci Py_ssize_t dict_size, ppos = 0; 32557db96d56Sopenharmony_ci 32567db96d56Sopenharmony_ci const char mark_op = MARK; 32577db96d56Sopenharmony_ci const char setitem_op = SETITEM; 32587db96d56Sopenharmony_ci const char setitems_op = SETITEMS; 32597db96d56Sopenharmony_ci 32607db96d56Sopenharmony_ci assert(obj != NULL && PyDict_CheckExact(obj)); 32617db96d56Sopenharmony_ci assert(self->proto > 0); 32627db96d56Sopenharmony_ci 32637db96d56Sopenharmony_ci dict_size = PyDict_GET_SIZE(obj); 32647db96d56Sopenharmony_ci 32657db96d56Sopenharmony_ci /* Special-case len(d) == 1 to save space. */ 32667db96d56Sopenharmony_ci if (dict_size == 1) { 32677db96d56Sopenharmony_ci PyDict_Next(obj, &ppos, &key, &value); 32687db96d56Sopenharmony_ci Py_INCREF(key); 32697db96d56Sopenharmony_ci Py_INCREF(value); 32707db96d56Sopenharmony_ci if (save(self, key, 0) < 0) { 32717db96d56Sopenharmony_ci goto error; 32727db96d56Sopenharmony_ci } 32737db96d56Sopenharmony_ci if (save(self, value, 0) < 0) { 32747db96d56Sopenharmony_ci goto error; 32757db96d56Sopenharmony_ci } 32767db96d56Sopenharmony_ci Py_CLEAR(key); 32777db96d56Sopenharmony_ci Py_CLEAR(value); 32787db96d56Sopenharmony_ci if (_Pickler_Write(self, &setitem_op, 1) < 0) 32797db96d56Sopenharmony_ci return -1; 32807db96d56Sopenharmony_ci return 0; 32817db96d56Sopenharmony_ci } 32827db96d56Sopenharmony_ci 32837db96d56Sopenharmony_ci /* Write in batches of BATCHSIZE. */ 32847db96d56Sopenharmony_ci do { 32857db96d56Sopenharmony_ci i = 0; 32867db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 32877db96d56Sopenharmony_ci return -1; 32887db96d56Sopenharmony_ci while (PyDict_Next(obj, &ppos, &key, &value)) { 32897db96d56Sopenharmony_ci Py_INCREF(key); 32907db96d56Sopenharmony_ci Py_INCREF(value); 32917db96d56Sopenharmony_ci if (save(self, key, 0) < 0) { 32927db96d56Sopenharmony_ci goto error; 32937db96d56Sopenharmony_ci } 32947db96d56Sopenharmony_ci if (save(self, value, 0) < 0) { 32957db96d56Sopenharmony_ci goto error; 32967db96d56Sopenharmony_ci } 32977db96d56Sopenharmony_ci Py_CLEAR(key); 32987db96d56Sopenharmony_ci Py_CLEAR(value); 32997db96d56Sopenharmony_ci if (++i == BATCHSIZE) 33007db96d56Sopenharmony_ci break; 33017db96d56Sopenharmony_ci } 33027db96d56Sopenharmony_ci if (_Pickler_Write(self, &setitems_op, 1) < 0) 33037db96d56Sopenharmony_ci return -1; 33047db96d56Sopenharmony_ci if (PyDict_GET_SIZE(obj) != dict_size) { 33057db96d56Sopenharmony_ci PyErr_Format( 33067db96d56Sopenharmony_ci PyExc_RuntimeError, 33077db96d56Sopenharmony_ci "dictionary changed size during iteration"); 33087db96d56Sopenharmony_ci return -1; 33097db96d56Sopenharmony_ci } 33107db96d56Sopenharmony_ci 33117db96d56Sopenharmony_ci } while (i == BATCHSIZE); 33127db96d56Sopenharmony_ci return 0; 33137db96d56Sopenharmony_cierror: 33147db96d56Sopenharmony_ci Py_XDECREF(key); 33157db96d56Sopenharmony_ci Py_XDECREF(value); 33167db96d56Sopenharmony_ci return -1; 33177db96d56Sopenharmony_ci} 33187db96d56Sopenharmony_ci 33197db96d56Sopenharmony_cistatic int 33207db96d56Sopenharmony_cisave_dict(PicklerObject *self, PyObject *obj) 33217db96d56Sopenharmony_ci{ 33227db96d56Sopenharmony_ci PyObject *items, *iter; 33237db96d56Sopenharmony_ci char header[3]; 33247db96d56Sopenharmony_ci Py_ssize_t len; 33257db96d56Sopenharmony_ci int status = 0; 33267db96d56Sopenharmony_ci assert(PyDict_Check(obj)); 33277db96d56Sopenharmony_ci 33287db96d56Sopenharmony_ci if (self->fast && !fast_save_enter(self, obj)) 33297db96d56Sopenharmony_ci goto error; 33307db96d56Sopenharmony_ci 33317db96d56Sopenharmony_ci /* Create an empty dict. */ 33327db96d56Sopenharmony_ci if (self->bin) { 33337db96d56Sopenharmony_ci header[0] = EMPTY_DICT; 33347db96d56Sopenharmony_ci len = 1; 33357db96d56Sopenharmony_ci } 33367db96d56Sopenharmony_ci else { 33377db96d56Sopenharmony_ci header[0] = MARK; 33387db96d56Sopenharmony_ci header[1] = DICT; 33397db96d56Sopenharmony_ci len = 2; 33407db96d56Sopenharmony_ci } 33417db96d56Sopenharmony_ci 33427db96d56Sopenharmony_ci if (_Pickler_Write(self, header, len) < 0) 33437db96d56Sopenharmony_ci goto error; 33447db96d56Sopenharmony_ci 33457db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 33467db96d56Sopenharmony_ci goto error; 33477db96d56Sopenharmony_ci 33487db96d56Sopenharmony_ci if (PyDict_GET_SIZE(obj)) { 33497db96d56Sopenharmony_ci /* Save the dict items. */ 33507db96d56Sopenharmony_ci if (PyDict_CheckExact(obj) && self->proto > 0) { 33517db96d56Sopenharmony_ci /* We can take certain shortcuts if we know this is a dict and 33527db96d56Sopenharmony_ci not a dict subclass. */ 33537db96d56Sopenharmony_ci if (_Py_EnterRecursiveCall(" while pickling an object")) 33547db96d56Sopenharmony_ci goto error; 33557db96d56Sopenharmony_ci status = batch_dict_exact(self, obj); 33567db96d56Sopenharmony_ci _Py_LeaveRecursiveCall(); 33577db96d56Sopenharmony_ci } else { 33587db96d56Sopenharmony_ci items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items)); 33597db96d56Sopenharmony_ci if (items == NULL) 33607db96d56Sopenharmony_ci goto error; 33617db96d56Sopenharmony_ci iter = PyObject_GetIter(items); 33627db96d56Sopenharmony_ci Py_DECREF(items); 33637db96d56Sopenharmony_ci if (iter == NULL) 33647db96d56Sopenharmony_ci goto error; 33657db96d56Sopenharmony_ci if (_Py_EnterRecursiveCall(" while pickling an object")) { 33667db96d56Sopenharmony_ci Py_DECREF(iter); 33677db96d56Sopenharmony_ci goto error; 33687db96d56Sopenharmony_ci } 33697db96d56Sopenharmony_ci status = batch_dict(self, iter); 33707db96d56Sopenharmony_ci _Py_LeaveRecursiveCall(); 33717db96d56Sopenharmony_ci Py_DECREF(iter); 33727db96d56Sopenharmony_ci } 33737db96d56Sopenharmony_ci } 33747db96d56Sopenharmony_ci 33757db96d56Sopenharmony_ci if (0) { 33767db96d56Sopenharmony_ci error: 33777db96d56Sopenharmony_ci status = -1; 33787db96d56Sopenharmony_ci } 33797db96d56Sopenharmony_ci 33807db96d56Sopenharmony_ci if (self->fast && !fast_save_leave(self, obj)) 33817db96d56Sopenharmony_ci status = -1; 33827db96d56Sopenharmony_ci 33837db96d56Sopenharmony_ci return status; 33847db96d56Sopenharmony_ci} 33857db96d56Sopenharmony_ci 33867db96d56Sopenharmony_cistatic int 33877db96d56Sopenharmony_cisave_set(PicklerObject *self, PyObject *obj) 33887db96d56Sopenharmony_ci{ 33897db96d56Sopenharmony_ci PyObject *item; 33907db96d56Sopenharmony_ci int i; 33917db96d56Sopenharmony_ci Py_ssize_t set_size, ppos = 0; 33927db96d56Sopenharmony_ci Py_hash_t hash; 33937db96d56Sopenharmony_ci 33947db96d56Sopenharmony_ci const char empty_set_op = EMPTY_SET; 33957db96d56Sopenharmony_ci const char mark_op = MARK; 33967db96d56Sopenharmony_ci const char additems_op = ADDITEMS; 33977db96d56Sopenharmony_ci 33987db96d56Sopenharmony_ci if (self->proto < 4) { 33997db96d56Sopenharmony_ci PyObject *items; 34007db96d56Sopenharmony_ci PyObject *reduce_value; 34017db96d56Sopenharmony_ci int status; 34027db96d56Sopenharmony_ci 34037db96d56Sopenharmony_ci items = PySequence_List(obj); 34047db96d56Sopenharmony_ci if (items == NULL) { 34057db96d56Sopenharmony_ci return -1; 34067db96d56Sopenharmony_ci } 34077db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PySet_Type, items); 34087db96d56Sopenharmony_ci Py_DECREF(items); 34097db96d56Sopenharmony_ci if (reduce_value == NULL) { 34107db96d56Sopenharmony_ci return -1; 34117db96d56Sopenharmony_ci } 34127db96d56Sopenharmony_ci /* save_reduce() will memoize the object automatically. */ 34137db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 34147db96d56Sopenharmony_ci Py_DECREF(reduce_value); 34157db96d56Sopenharmony_ci return status; 34167db96d56Sopenharmony_ci } 34177db96d56Sopenharmony_ci 34187db96d56Sopenharmony_ci if (_Pickler_Write(self, &empty_set_op, 1) < 0) 34197db96d56Sopenharmony_ci return -1; 34207db96d56Sopenharmony_ci 34217db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 34227db96d56Sopenharmony_ci return -1; 34237db96d56Sopenharmony_ci 34247db96d56Sopenharmony_ci set_size = PySet_GET_SIZE(obj); 34257db96d56Sopenharmony_ci if (set_size == 0) 34267db96d56Sopenharmony_ci return 0; /* nothing to do */ 34277db96d56Sopenharmony_ci 34287db96d56Sopenharmony_ci /* Write in batches of BATCHSIZE. */ 34297db96d56Sopenharmony_ci do { 34307db96d56Sopenharmony_ci i = 0; 34317db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 34327db96d56Sopenharmony_ci return -1; 34337db96d56Sopenharmony_ci while (_PySet_NextEntry(obj, &ppos, &item, &hash)) { 34347db96d56Sopenharmony_ci Py_INCREF(item); 34357db96d56Sopenharmony_ci int err = save(self, item, 0); 34367db96d56Sopenharmony_ci Py_CLEAR(item); 34377db96d56Sopenharmony_ci if (err < 0) 34387db96d56Sopenharmony_ci return -1; 34397db96d56Sopenharmony_ci if (++i == BATCHSIZE) 34407db96d56Sopenharmony_ci break; 34417db96d56Sopenharmony_ci } 34427db96d56Sopenharmony_ci if (_Pickler_Write(self, &additems_op, 1) < 0) 34437db96d56Sopenharmony_ci return -1; 34447db96d56Sopenharmony_ci if (PySet_GET_SIZE(obj) != set_size) { 34457db96d56Sopenharmony_ci PyErr_Format( 34467db96d56Sopenharmony_ci PyExc_RuntimeError, 34477db96d56Sopenharmony_ci "set changed size during iteration"); 34487db96d56Sopenharmony_ci return -1; 34497db96d56Sopenharmony_ci } 34507db96d56Sopenharmony_ci } while (i == BATCHSIZE); 34517db96d56Sopenharmony_ci 34527db96d56Sopenharmony_ci return 0; 34537db96d56Sopenharmony_ci} 34547db96d56Sopenharmony_ci 34557db96d56Sopenharmony_cistatic int 34567db96d56Sopenharmony_cisave_frozenset(PicklerObject *self, PyObject *obj) 34577db96d56Sopenharmony_ci{ 34587db96d56Sopenharmony_ci PyObject *iter; 34597db96d56Sopenharmony_ci 34607db96d56Sopenharmony_ci const char mark_op = MARK; 34617db96d56Sopenharmony_ci const char frozenset_op = FROZENSET; 34627db96d56Sopenharmony_ci 34637db96d56Sopenharmony_ci if (self->fast && !fast_save_enter(self, obj)) 34647db96d56Sopenharmony_ci return -1; 34657db96d56Sopenharmony_ci 34667db96d56Sopenharmony_ci if (self->proto < 4) { 34677db96d56Sopenharmony_ci PyObject *items; 34687db96d56Sopenharmony_ci PyObject *reduce_value; 34697db96d56Sopenharmony_ci int status; 34707db96d56Sopenharmony_ci 34717db96d56Sopenharmony_ci items = PySequence_List(obj); 34727db96d56Sopenharmony_ci if (items == NULL) { 34737db96d56Sopenharmony_ci return -1; 34747db96d56Sopenharmony_ci } 34757db96d56Sopenharmony_ci reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PyFrozenSet_Type, 34767db96d56Sopenharmony_ci items); 34777db96d56Sopenharmony_ci Py_DECREF(items); 34787db96d56Sopenharmony_ci if (reduce_value == NULL) { 34797db96d56Sopenharmony_ci return -1; 34807db96d56Sopenharmony_ci } 34817db96d56Sopenharmony_ci /* save_reduce() will memoize the object automatically. */ 34827db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 34837db96d56Sopenharmony_ci Py_DECREF(reduce_value); 34847db96d56Sopenharmony_ci return status; 34857db96d56Sopenharmony_ci } 34867db96d56Sopenharmony_ci 34877db96d56Sopenharmony_ci if (_Pickler_Write(self, &mark_op, 1) < 0) 34887db96d56Sopenharmony_ci return -1; 34897db96d56Sopenharmony_ci 34907db96d56Sopenharmony_ci iter = PyObject_GetIter(obj); 34917db96d56Sopenharmony_ci if (iter == NULL) { 34927db96d56Sopenharmony_ci return -1; 34937db96d56Sopenharmony_ci } 34947db96d56Sopenharmony_ci for (;;) { 34957db96d56Sopenharmony_ci PyObject *item; 34967db96d56Sopenharmony_ci 34977db96d56Sopenharmony_ci item = PyIter_Next(iter); 34987db96d56Sopenharmony_ci if (item == NULL) { 34997db96d56Sopenharmony_ci if (PyErr_Occurred()) { 35007db96d56Sopenharmony_ci Py_DECREF(iter); 35017db96d56Sopenharmony_ci return -1; 35027db96d56Sopenharmony_ci } 35037db96d56Sopenharmony_ci break; 35047db96d56Sopenharmony_ci } 35057db96d56Sopenharmony_ci if (save(self, item, 0) < 0) { 35067db96d56Sopenharmony_ci Py_DECREF(item); 35077db96d56Sopenharmony_ci Py_DECREF(iter); 35087db96d56Sopenharmony_ci return -1; 35097db96d56Sopenharmony_ci } 35107db96d56Sopenharmony_ci Py_DECREF(item); 35117db96d56Sopenharmony_ci } 35127db96d56Sopenharmony_ci Py_DECREF(iter); 35137db96d56Sopenharmony_ci 35147db96d56Sopenharmony_ci /* If the object is already in the memo, this means it is 35157db96d56Sopenharmony_ci recursive. In this case, throw away everything we put on the 35167db96d56Sopenharmony_ci stack, and fetch the object back from the memo. */ 35177db96d56Sopenharmony_ci if (PyMemoTable_Get(self->memo, obj)) { 35187db96d56Sopenharmony_ci const char pop_mark_op = POP_MARK; 35197db96d56Sopenharmony_ci 35207db96d56Sopenharmony_ci if (_Pickler_Write(self, &pop_mark_op, 1) < 0) 35217db96d56Sopenharmony_ci return -1; 35227db96d56Sopenharmony_ci if (memo_get(self, obj) < 0) 35237db96d56Sopenharmony_ci return -1; 35247db96d56Sopenharmony_ci return 0; 35257db96d56Sopenharmony_ci } 35267db96d56Sopenharmony_ci 35277db96d56Sopenharmony_ci if (_Pickler_Write(self, &frozenset_op, 1) < 0) 35287db96d56Sopenharmony_ci return -1; 35297db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 35307db96d56Sopenharmony_ci return -1; 35317db96d56Sopenharmony_ci 35327db96d56Sopenharmony_ci return 0; 35337db96d56Sopenharmony_ci} 35347db96d56Sopenharmony_ci 35357db96d56Sopenharmony_cistatic int 35367db96d56Sopenharmony_cifix_imports(PyObject **module_name, PyObject **global_name) 35377db96d56Sopenharmony_ci{ 35387db96d56Sopenharmony_ci PyObject *key; 35397db96d56Sopenharmony_ci PyObject *item; 35407db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 35417db96d56Sopenharmony_ci 35427db96d56Sopenharmony_ci key = PyTuple_Pack(2, *module_name, *global_name); 35437db96d56Sopenharmony_ci if (key == NULL) 35447db96d56Sopenharmony_ci return -1; 35457db96d56Sopenharmony_ci item = PyDict_GetItemWithError(st->name_mapping_3to2, key); 35467db96d56Sopenharmony_ci Py_DECREF(key); 35477db96d56Sopenharmony_ci if (item) { 35487db96d56Sopenharmony_ci PyObject *fixed_module_name; 35497db96d56Sopenharmony_ci PyObject *fixed_global_name; 35507db96d56Sopenharmony_ci 35517db96d56Sopenharmony_ci if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) { 35527db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 35537db96d56Sopenharmony_ci "_compat_pickle.REVERSE_NAME_MAPPING values " 35547db96d56Sopenharmony_ci "should be 2-tuples, not %.200s", 35557db96d56Sopenharmony_ci Py_TYPE(item)->tp_name); 35567db96d56Sopenharmony_ci return -1; 35577db96d56Sopenharmony_ci } 35587db96d56Sopenharmony_ci fixed_module_name = PyTuple_GET_ITEM(item, 0); 35597db96d56Sopenharmony_ci fixed_global_name = PyTuple_GET_ITEM(item, 1); 35607db96d56Sopenharmony_ci if (!PyUnicode_Check(fixed_module_name) || 35617db96d56Sopenharmony_ci !PyUnicode_Check(fixed_global_name)) { 35627db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 35637db96d56Sopenharmony_ci "_compat_pickle.REVERSE_NAME_MAPPING values " 35647db96d56Sopenharmony_ci "should be pairs of str, not (%.200s, %.200s)", 35657db96d56Sopenharmony_ci Py_TYPE(fixed_module_name)->tp_name, 35667db96d56Sopenharmony_ci Py_TYPE(fixed_global_name)->tp_name); 35677db96d56Sopenharmony_ci return -1; 35687db96d56Sopenharmony_ci } 35697db96d56Sopenharmony_ci 35707db96d56Sopenharmony_ci Py_CLEAR(*module_name); 35717db96d56Sopenharmony_ci Py_CLEAR(*global_name); 35727db96d56Sopenharmony_ci Py_INCREF(fixed_module_name); 35737db96d56Sopenharmony_ci Py_INCREF(fixed_global_name); 35747db96d56Sopenharmony_ci *module_name = fixed_module_name; 35757db96d56Sopenharmony_ci *global_name = fixed_global_name; 35767db96d56Sopenharmony_ci return 0; 35777db96d56Sopenharmony_ci } 35787db96d56Sopenharmony_ci else if (PyErr_Occurred()) { 35797db96d56Sopenharmony_ci return -1; 35807db96d56Sopenharmony_ci } 35817db96d56Sopenharmony_ci 35827db96d56Sopenharmony_ci item = PyDict_GetItemWithError(st->import_mapping_3to2, *module_name); 35837db96d56Sopenharmony_ci if (item) { 35847db96d56Sopenharmony_ci if (!PyUnicode_Check(item)) { 35857db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 35867db96d56Sopenharmony_ci "_compat_pickle.REVERSE_IMPORT_MAPPING values " 35877db96d56Sopenharmony_ci "should be strings, not %.200s", 35887db96d56Sopenharmony_ci Py_TYPE(item)->tp_name); 35897db96d56Sopenharmony_ci return -1; 35907db96d56Sopenharmony_ci } 35917db96d56Sopenharmony_ci Py_INCREF(item); 35927db96d56Sopenharmony_ci Py_XSETREF(*module_name, item); 35937db96d56Sopenharmony_ci } 35947db96d56Sopenharmony_ci else if (PyErr_Occurred()) { 35957db96d56Sopenharmony_ci return -1; 35967db96d56Sopenharmony_ci } 35977db96d56Sopenharmony_ci 35987db96d56Sopenharmony_ci return 0; 35997db96d56Sopenharmony_ci} 36007db96d56Sopenharmony_ci 36017db96d56Sopenharmony_cistatic int 36027db96d56Sopenharmony_cisave_global(PicklerObject *self, PyObject *obj, PyObject *name) 36037db96d56Sopenharmony_ci{ 36047db96d56Sopenharmony_ci PyObject *global_name = NULL; 36057db96d56Sopenharmony_ci PyObject *module_name = NULL; 36067db96d56Sopenharmony_ci PyObject *module = NULL; 36077db96d56Sopenharmony_ci PyObject *parent = NULL; 36087db96d56Sopenharmony_ci PyObject *dotted_path = NULL; 36097db96d56Sopenharmony_ci PyObject *lastname = NULL; 36107db96d56Sopenharmony_ci PyObject *cls; 36117db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 36127db96d56Sopenharmony_ci int status = 0; 36137db96d56Sopenharmony_ci 36147db96d56Sopenharmony_ci const char global_op = GLOBAL; 36157db96d56Sopenharmony_ci 36167db96d56Sopenharmony_ci if (name) { 36177db96d56Sopenharmony_ci Py_INCREF(name); 36187db96d56Sopenharmony_ci global_name = name; 36197db96d56Sopenharmony_ci } 36207db96d56Sopenharmony_ci else { 36217db96d56Sopenharmony_ci if (_PyObject_LookupAttr(obj, &_Py_ID(__qualname__), &global_name) < 0) 36227db96d56Sopenharmony_ci goto error; 36237db96d56Sopenharmony_ci if (global_name == NULL) { 36247db96d56Sopenharmony_ci global_name = PyObject_GetAttr(obj, &_Py_ID(__name__)); 36257db96d56Sopenharmony_ci if (global_name == NULL) 36267db96d56Sopenharmony_ci goto error; 36277db96d56Sopenharmony_ci } 36287db96d56Sopenharmony_ci } 36297db96d56Sopenharmony_ci 36307db96d56Sopenharmony_ci dotted_path = get_dotted_path(module, global_name); 36317db96d56Sopenharmony_ci if (dotted_path == NULL) 36327db96d56Sopenharmony_ci goto error; 36337db96d56Sopenharmony_ci module_name = whichmodule(obj, dotted_path); 36347db96d56Sopenharmony_ci if (module_name == NULL) 36357db96d56Sopenharmony_ci goto error; 36367db96d56Sopenharmony_ci 36377db96d56Sopenharmony_ci /* XXX: Change to use the import C API directly with level=0 to disallow 36387db96d56Sopenharmony_ci relative imports. 36397db96d56Sopenharmony_ci 36407db96d56Sopenharmony_ci XXX: PyImport_ImportModuleLevel could be used. However, this bypasses 36417db96d56Sopenharmony_ci builtins.__import__. Therefore, _pickle, unlike pickle.py, will ignore 36427db96d56Sopenharmony_ci custom import functions (IMHO, this would be a nice security 36437db96d56Sopenharmony_ci feature). The import C API would need to be extended to support the 36447db96d56Sopenharmony_ci extra parameters of __import__ to fix that. */ 36457db96d56Sopenharmony_ci module = PyImport_Import(module_name); 36467db96d56Sopenharmony_ci if (module == NULL) { 36477db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 36487db96d56Sopenharmony_ci "Can't pickle %R: import of module %R failed", 36497db96d56Sopenharmony_ci obj, module_name); 36507db96d56Sopenharmony_ci goto error; 36517db96d56Sopenharmony_ci } 36527db96d56Sopenharmony_ci lastname = PyList_GET_ITEM(dotted_path, PyList_GET_SIZE(dotted_path)-1); 36537db96d56Sopenharmony_ci Py_INCREF(lastname); 36547db96d56Sopenharmony_ci cls = get_deep_attribute(module, dotted_path, &parent); 36557db96d56Sopenharmony_ci Py_CLEAR(dotted_path); 36567db96d56Sopenharmony_ci if (cls == NULL) { 36577db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 36587db96d56Sopenharmony_ci "Can't pickle %R: attribute lookup %S on %S failed", 36597db96d56Sopenharmony_ci obj, global_name, module_name); 36607db96d56Sopenharmony_ci goto error; 36617db96d56Sopenharmony_ci } 36627db96d56Sopenharmony_ci if (cls != obj) { 36637db96d56Sopenharmony_ci Py_DECREF(cls); 36647db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 36657db96d56Sopenharmony_ci "Can't pickle %R: it's not the same object as %S.%S", 36667db96d56Sopenharmony_ci obj, module_name, global_name); 36677db96d56Sopenharmony_ci goto error; 36687db96d56Sopenharmony_ci } 36697db96d56Sopenharmony_ci Py_DECREF(cls); 36707db96d56Sopenharmony_ci 36717db96d56Sopenharmony_ci if (self->proto >= 2) { 36727db96d56Sopenharmony_ci /* See whether this is in the extension registry, and if 36737db96d56Sopenharmony_ci * so generate an EXT opcode. 36747db96d56Sopenharmony_ci */ 36757db96d56Sopenharmony_ci PyObject *extension_key; 36767db96d56Sopenharmony_ci PyObject *code_obj; /* extension code as Python object */ 36777db96d56Sopenharmony_ci long code; /* extension code as C value */ 36787db96d56Sopenharmony_ci char pdata[5]; 36797db96d56Sopenharmony_ci Py_ssize_t n; 36807db96d56Sopenharmony_ci 36817db96d56Sopenharmony_ci extension_key = PyTuple_Pack(2, module_name, global_name); 36827db96d56Sopenharmony_ci if (extension_key == NULL) { 36837db96d56Sopenharmony_ci goto error; 36847db96d56Sopenharmony_ci } 36857db96d56Sopenharmony_ci code_obj = PyDict_GetItemWithError(st->extension_registry, 36867db96d56Sopenharmony_ci extension_key); 36877db96d56Sopenharmony_ci Py_DECREF(extension_key); 36887db96d56Sopenharmony_ci /* The object is not registered in the extension registry. 36897db96d56Sopenharmony_ci This is the most likely code path. */ 36907db96d56Sopenharmony_ci if (code_obj == NULL) { 36917db96d56Sopenharmony_ci if (PyErr_Occurred()) { 36927db96d56Sopenharmony_ci goto error; 36937db96d56Sopenharmony_ci } 36947db96d56Sopenharmony_ci goto gen_global; 36957db96d56Sopenharmony_ci } 36967db96d56Sopenharmony_ci 36977db96d56Sopenharmony_ci /* XXX: pickle.py doesn't check neither the type, nor the range 36987db96d56Sopenharmony_ci of the value returned by the extension_registry. It should for 36997db96d56Sopenharmony_ci consistency. */ 37007db96d56Sopenharmony_ci 37017db96d56Sopenharmony_ci /* Verify code_obj has the right type and value. */ 37027db96d56Sopenharmony_ci if (!PyLong_Check(code_obj)) { 37037db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 37047db96d56Sopenharmony_ci "Can't pickle %R: extension code %R isn't an integer", 37057db96d56Sopenharmony_ci obj, code_obj); 37067db96d56Sopenharmony_ci goto error; 37077db96d56Sopenharmony_ci } 37087db96d56Sopenharmony_ci code = PyLong_AS_LONG(code_obj); 37097db96d56Sopenharmony_ci if (code <= 0 || code > 0x7fffffffL) { 37107db96d56Sopenharmony_ci if (!PyErr_Occurred()) 37117db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, "Can't pickle %R: extension " 37127db96d56Sopenharmony_ci "code %ld is out of range", obj, code); 37137db96d56Sopenharmony_ci goto error; 37147db96d56Sopenharmony_ci } 37157db96d56Sopenharmony_ci 37167db96d56Sopenharmony_ci /* Generate an EXT opcode. */ 37177db96d56Sopenharmony_ci if (code <= 0xff) { 37187db96d56Sopenharmony_ci pdata[0] = EXT1; 37197db96d56Sopenharmony_ci pdata[1] = (unsigned char)code; 37207db96d56Sopenharmony_ci n = 2; 37217db96d56Sopenharmony_ci } 37227db96d56Sopenharmony_ci else if (code <= 0xffff) { 37237db96d56Sopenharmony_ci pdata[0] = EXT2; 37247db96d56Sopenharmony_ci pdata[1] = (unsigned char)(code & 0xff); 37257db96d56Sopenharmony_ci pdata[2] = (unsigned char)((code >> 8) & 0xff); 37267db96d56Sopenharmony_ci n = 3; 37277db96d56Sopenharmony_ci } 37287db96d56Sopenharmony_ci else { 37297db96d56Sopenharmony_ci pdata[0] = EXT4; 37307db96d56Sopenharmony_ci pdata[1] = (unsigned char)(code & 0xff); 37317db96d56Sopenharmony_ci pdata[2] = (unsigned char)((code >> 8) & 0xff); 37327db96d56Sopenharmony_ci pdata[3] = (unsigned char)((code >> 16) & 0xff); 37337db96d56Sopenharmony_ci pdata[4] = (unsigned char)((code >> 24) & 0xff); 37347db96d56Sopenharmony_ci n = 5; 37357db96d56Sopenharmony_ci } 37367db96d56Sopenharmony_ci 37377db96d56Sopenharmony_ci if (_Pickler_Write(self, pdata, n) < 0) 37387db96d56Sopenharmony_ci goto error; 37397db96d56Sopenharmony_ci } 37407db96d56Sopenharmony_ci else { 37417db96d56Sopenharmony_ci gen_global: 37427db96d56Sopenharmony_ci if (parent == module) { 37437db96d56Sopenharmony_ci Py_INCREF(lastname); 37447db96d56Sopenharmony_ci Py_DECREF(global_name); 37457db96d56Sopenharmony_ci global_name = lastname; 37467db96d56Sopenharmony_ci } 37477db96d56Sopenharmony_ci if (self->proto >= 4) { 37487db96d56Sopenharmony_ci const char stack_global_op = STACK_GLOBAL; 37497db96d56Sopenharmony_ci 37507db96d56Sopenharmony_ci if (save(self, module_name, 0) < 0) 37517db96d56Sopenharmony_ci goto error; 37527db96d56Sopenharmony_ci if (save(self, global_name, 0) < 0) 37537db96d56Sopenharmony_ci goto error; 37547db96d56Sopenharmony_ci 37557db96d56Sopenharmony_ci if (_Pickler_Write(self, &stack_global_op, 1) < 0) 37567db96d56Sopenharmony_ci goto error; 37577db96d56Sopenharmony_ci } 37587db96d56Sopenharmony_ci else if (parent != module) { 37597db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 37607db96d56Sopenharmony_ci PyObject *reduce_value = Py_BuildValue("(O(OO))", 37617db96d56Sopenharmony_ci st->getattr, parent, lastname); 37627db96d56Sopenharmony_ci if (reduce_value == NULL) 37637db96d56Sopenharmony_ci goto error; 37647db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, NULL); 37657db96d56Sopenharmony_ci Py_DECREF(reduce_value); 37667db96d56Sopenharmony_ci if (status < 0) 37677db96d56Sopenharmony_ci goto error; 37687db96d56Sopenharmony_ci } 37697db96d56Sopenharmony_ci else { 37707db96d56Sopenharmony_ci /* Generate a normal global opcode if we are using a pickle 37717db96d56Sopenharmony_ci protocol < 4, or if the object is not registered in the 37727db96d56Sopenharmony_ci extension registry. */ 37737db96d56Sopenharmony_ci PyObject *encoded; 37747db96d56Sopenharmony_ci PyObject *(*unicode_encoder)(PyObject *); 37757db96d56Sopenharmony_ci 37767db96d56Sopenharmony_ci if (_Pickler_Write(self, &global_op, 1) < 0) 37777db96d56Sopenharmony_ci goto error; 37787db96d56Sopenharmony_ci 37797db96d56Sopenharmony_ci /* For protocol < 3 and if the user didn't request against doing 37807db96d56Sopenharmony_ci so, we convert module names to the old 2.x module names. */ 37817db96d56Sopenharmony_ci if (self->proto < 3 && self->fix_imports) { 37827db96d56Sopenharmony_ci if (fix_imports(&module_name, &global_name) < 0) { 37837db96d56Sopenharmony_ci goto error; 37847db96d56Sopenharmony_ci } 37857db96d56Sopenharmony_ci } 37867db96d56Sopenharmony_ci 37877db96d56Sopenharmony_ci /* Since Python 3.0 now supports non-ASCII identifiers, we encode 37887db96d56Sopenharmony_ci both the module name and the global name using UTF-8. We do so 37897db96d56Sopenharmony_ci only when we are using the pickle protocol newer than version 37907db96d56Sopenharmony_ci 3. This is to ensure compatibility with older Unpickler running 37917db96d56Sopenharmony_ci on Python 2.x. */ 37927db96d56Sopenharmony_ci if (self->proto == 3) { 37937db96d56Sopenharmony_ci unicode_encoder = PyUnicode_AsUTF8String; 37947db96d56Sopenharmony_ci } 37957db96d56Sopenharmony_ci else { 37967db96d56Sopenharmony_ci unicode_encoder = PyUnicode_AsASCIIString; 37977db96d56Sopenharmony_ci } 37987db96d56Sopenharmony_ci encoded = unicode_encoder(module_name); 37997db96d56Sopenharmony_ci if (encoded == NULL) { 38007db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) 38017db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 38027db96d56Sopenharmony_ci "can't pickle module identifier '%S' using " 38037db96d56Sopenharmony_ci "pickle protocol %i", 38047db96d56Sopenharmony_ci module_name, self->proto); 38057db96d56Sopenharmony_ci goto error; 38067db96d56Sopenharmony_ci } 38077db96d56Sopenharmony_ci if (_Pickler_Write(self, PyBytes_AS_STRING(encoded), 38087db96d56Sopenharmony_ci PyBytes_GET_SIZE(encoded)) < 0) { 38097db96d56Sopenharmony_ci Py_DECREF(encoded); 38107db96d56Sopenharmony_ci goto error; 38117db96d56Sopenharmony_ci } 38127db96d56Sopenharmony_ci Py_DECREF(encoded); 38137db96d56Sopenharmony_ci if(_Pickler_Write(self, "\n", 1) < 0) 38147db96d56Sopenharmony_ci goto error; 38157db96d56Sopenharmony_ci 38167db96d56Sopenharmony_ci /* Save the name of the module. */ 38177db96d56Sopenharmony_ci encoded = unicode_encoder(global_name); 38187db96d56Sopenharmony_ci if (encoded == NULL) { 38197db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) 38207db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 38217db96d56Sopenharmony_ci "can't pickle global identifier '%S' using " 38227db96d56Sopenharmony_ci "pickle protocol %i", 38237db96d56Sopenharmony_ci global_name, self->proto); 38247db96d56Sopenharmony_ci goto error; 38257db96d56Sopenharmony_ci } 38267db96d56Sopenharmony_ci if (_Pickler_Write(self, PyBytes_AS_STRING(encoded), 38277db96d56Sopenharmony_ci PyBytes_GET_SIZE(encoded)) < 0) { 38287db96d56Sopenharmony_ci Py_DECREF(encoded); 38297db96d56Sopenharmony_ci goto error; 38307db96d56Sopenharmony_ci } 38317db96d56Sopenharmony_ci Py_DECREF(encoded); 38327db96d56Sopenharmony_ci if (_Pickler_Write(self, "\n", 1) < 0) 38337db96d56Sopenharmony_ci goto error; 38347db96d56Sopenharmony_ci } 38357db96d56Sopenharmony_ci /* Memoize the object. */ 38367db96d56Sopenharmony_ci if (memo_put(self, obj) < 0) 38377db96d56Sopenharmony_ci goto error; 38387db96d56Sopenharmony_ci } 38397db96d56Sopenharmony_ci 38407db96d56Sopenharmony_ci if (0) { 38417db96d56Sopenharmony_ci error: 38427db96d56Sopenharmony_ci status = -1; 38437db96d56Sopenharmony_ci } 38447db96d56Sopenharmony_ci Py_XDECREF(module_name); 38457db96d56Sopenharmony_ci Py_XDECREF(global_name); 38467db96d56Sopenharmony_ci Py_XDECREF(module); 38477db96d56Sopenharmony_ci Py_XDECREF(parent); 38487db96d56Sopenharmony_ci Py_XDECREF(dotted_path); 38497db96d56Sopenharmony_ci Py_XDECREF(lastname); 38507db96d56Sopenharmony_ci 38517db96d56Sopenharmony_ci return status; 38527db96d56Sopenharmony_ci} 38537db96d56Sopenharmony_ci 38547db96d56Sopenharmony_cistatic int 38557db96d56Sopenharmony_cisave_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton) 38567db96d56Sopenharmony_ci{ 38577db96d56Sopenharmony_ci PyObject *reduce_value; 38587db96d56Sopenharmony_ci int status; 38597db96d56Sopenharmony_ci 38607db96d56Sopenharmony_ci reduce_value = Py_BuildValue("O(O)", &PyType_Type, singleton); 38617db96d56Sopenharmony_ci if (reduce_value == NULL) { 38627db96d56Sopenharmony_ci return -1; 38637db96d56Sopenharmony_ci } 38647db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 38657db96d56Sopenharmony_ci Py_DECREF(reduce_value); 38667db96d56Sopenharmony_ci return status; 38677db96d56Sopenharmony_ci} 38687db96d56Sopenharmony_ci 38697db96d56Sopenharmony_cistatic int 38707db96d56Sopenharmony_cisave_type(PicklerObject *self, PyObject *obj) 38717db96d56Sopenharmony_ci{ 38727db96d56Sopenharmony_ci if (obj == (PyObject *)&_PyNone_Type) { 38737db96d56Sopenharmony_ci return save_singleton_type(self, obj, Py_None); 38747db96d56Sopenharmony_ci } 38757db96d56Sopenharmony_ci else if (obj == (PyObject *)&PyEllipsis_Type) { 38767db96d56Sopenharmony_ci return save_singleton_type(self, obj, Py_Ellipsis); 38777db96d56Sopenharmony_ci } 38787db96d56Sopenharmony_ci else if (obj == (PyObject *)&_PyNotImplemented_Type) { 38797db96d56Sopenharmony_ci return save_singleton_type(self, obj, Py_NotImplemented); 38807db96d56Sopenharmony_ci } 38817db96d56Sopenharmony_ci return save_global(self, obj, NULL); 38827db96d56Sopenharmony_ci} 38837db96d56Sopenharmony_ci 38847db96d56Sopenharmony_cistatic int 38857db96d56Sopenharmony_cisave_pers(PicklerObject *self, PyObject *obj) 38867db96d56Sopenharmony_ci{ 38877db96d56Sopenharmony_ci PyObject *pid = NULL; 38887db96d56Sopenharmony_ci int status = 0; 38897db96d56Sopenharmony_ci 38907db96d56Sopenharmony_ci const char persid_op = PERSID; 38917db96d56Sopenharmony_ci const char binpersid_op = BINPERSID; 38927db96d56Sopenharmony_ci 38937db96d56Sopenharmony_ci pid = call_method(self->pers_func, self->pers_func_self, obj); 38947db96d56Sopenharmony_ci if (pid == NULL) 38957db96d56Sopenharmony_ci return -1; 38967db96d56Sopenharmony_ci 38977db96d56Sopenharmony_ci if (pid != Py_None) { 38987db96d56Sopenharmony_ci if (self->bin) { 38997db96d56Sopenharmony_ci if (save(self, pid, 1) < 0 || 39007db96d56Sopenharmony_ci _Pickler_Write(self, &binpersid_op, 1) < 0) 39017db96d56Sopenharmony_ci goto error; 39027db96d56Sopenharmony_ci } 39037db96d56Sopenharmony_ci else { 39047db96d56Sopenharmony_ci PyObject *pid_str; 39057db96d56Sopenharmony_ci 39067db96d56Sopenharmony_ci pid_str = PyObject_Str(pid); 39077db96d56Sopenharmony_ci if (pid_str == NULL) 39087db96d56Sopenharmony_ci goto error; 39097db96d56Sopenharmony_ci 39107db96d56Sopenharmony_ci /* XXX: Should it check whether the pid contains embedded 39117db96d56Sopenharmony_ci newlines? */ 39127db96d56Sopenharmony_ci if (!PyUnicode_IS_ASCII(pid_str)) { 39137db96d56Sopenharmony_ci PyErr_SetString(_Pickle_GetGlobalState()->PicklingError, 39147db96d56Sopenharmony_ci "persistent IDs in protocol 0 must be " 39157db96d56Sopenharmony_ci "ASCII strings"); 39167db96d56Sopenharmony_ci Py_DECREF(pid_str); 39177db96d56Sopenharmony_ci goto error; 39187db96d56Sopenharmony_ci } 39197db96d56Sopenharmony_ci 39207db96d56Sopenharmony_ci if (_Pickler_Write(self, &persid_op, 1) < 0 || 39217db96d56Sopenharmony_ci _Pickler_Write(self, PyUnicode_DATA(pid_str), 39227db96d56Sopenharmony_ci PyUnicode_GET_LENGTH(pid_str)) < 0 || 39237db96d56Sopenharmony_ci _Pickler_Write(self, "\n", 1) < 0) { 39247db96d56Sopenharmony_ci Py_DECREF(pid_str); 39257db96d56Sopenharmony_ci goto error; 39267db96d56Sopenharmony_ci } 39277db96d56Sopenharmony_ci Py_DECREF(pid_str); 39287db96d56Sopenharmony_ci } 39297db96d56Sopenharmony_ci status = 1; 39307db96d56Sopenharmony_ci } 39317db96d56Sopenharmony_ci 39327db96d56Sopenharmony_ci if (0) { 39337db96d56Sopenharmony_ci error: 39347db96d56Sopenharmony_ci status = -1; 39357db96d56Sopenharmony_ci } 39367db96d56Sopenharmony_ci Py_XDECREF(pid); 39377db96d56Sopenharmony_ci 39387db96d56Sopenharmony_ci return status; 39397db96d56Sopenharmony_ci} 39407db96d56Sopenharmony_ci 39417db96d56Sopenharmony_cistatic PyObject * 39427db96d56Sopenharmony_ciget_class(PyObject *obj) 39437db96d56Sopenharmony_ci{ 39447db96d56Sopenharmony_ci PyObject *cls; 39457db96d56Sopenharmony_ci 39467db96d56Sopenharmony_ci if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &cls) == 0) { 39477db96d56Sopenharmony_ci cls = (PyObject *) Py_TYPE(obj); 39487db96d56Sopenharmony_ci Py_INCREF(cls); 39497db96d56Sopenharmony_ci } 39507db96d56Sopenharmony_ci return cls; 39517db96d56Sopenharmony_ci} 39527db96d56Sopenharmony_ci 39537db96d56Sopenharmony_ci/* We're saving obj, and args is the 2-thru-5 tuple returned by the 39547db96d56Sopenharmony_ci * appropriate __reduce__ method for obj. 39557db96d56Sopenharmony_ci */ 39567db96d56Sopenharmony_cistatic int 39577db96d56Sopenharmony_cisave_reduce(PicklerObject *self, PyObject *args, PyObject *obj) 39587db96d56Sopenharmony_ci{ 39597db96d56Sopenharmony_ci PyObject *callable; 39607db96d56Sopenharmony_ci PyObject *argtup; 39617db96d56Sopenharmony_ci PyObject *state = NULL; 39627db96d56Sopenharmony_ci PyObject *listitems = Py_None; 39637db96d56Sopenharmony_ci PyObject *dictitems = Py_None; 39647db96d56Sopenharmony_ci PyObject *state_setter = Py_None; 39657db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 39667db96d56Sopenharmony_ci Py_ssize_t size; 39677db96d56Sopenharmony_ci int use_newobj = 0, use_newobj_ex = 0; 39687db96d56Sopenharmony_ci 39697db96d56Sopenharmony_ci const char reduce_op = REDUCE; 39707db96d56Sopenharmony_ci const char build_op = BUILD; 39717db96d56Sopenharmony_ci const char newobj_op = NEWOBJ; 39727db96d56Sopenharmony_ci const char newobj_ex_op = NEWOBJ_EX; 39737db96d56Sopenharmony_ci 39747db96d56Sopenharmony_ci size = PyTuple_Size(args); 39757db96d56Sopenharmony_ci if (size < 2 || size > 6) { 39767db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "tuple returned by " 39777db96d56Sopenharmony_ci "__reduce__ must contain 2 through 6 elements"); 39787db96d56Sopenharmony_ci return -1; 39797db96d56Sopenharmony_ci } 39807db96d56Sopenharmony_ci 39817db96d56Sopenharmony_ci if (!PyArg_UnpackTuple(args, "save_reduce", 2, 6, 39827db96d56Sopenharmony_ci &callable, &argtup, &state, &listitems, &dictitems, 39837db96d56Sopenharmony_ci &state_setter)) 39847db96d56Sopenharmony_ci return -1; 39857db96d56Sopenharmony_ci 39867db96d56Sopenharmony_ci if (!PyCallable_Check(callable)) { 39877db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "first item of the tuple " 39887db96d56Sopenharmony_ci "returned by __reduce__ must be callable"); 39897db96d56Sopenharmony_ci return -1; 39907db96d56Sopenharmony_ci } 39917db96d56Sopenharmony_ci if (!PyTuple_Check(argtup)) { 39927db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "second item of the tuple " 39937db96d56Sopenharmony_ci "returned by __reduce__ must be a tuple"); 39947db96d56Sopenharmony_ci return -1; 39957db96d56Sopenharmony_ci } 39967db96d56Sopenharmony_ci 39977db96d56Sopenharmony_ci if (state == Py_None) 39987db96d56Sopenharmony_ci state = NULL; 39997db96d56Sopenharmony_ci 40007db96d56Sopenharmony_ci if (listitems == Py_None) 40017db96d56Sopenharmony_ci listitems = NULL; 40027db96d56Sopenharmony_ci else if (!PyIter_Check(listitems)) { 40037db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, "fourth element of the tuple " 40047db96d56Sopenharmony_ci "returned by __reduce__ must be an iterator, not %s", 40057db96d56Sopenharmony_ci Py_TYPE(listitems)->tp_name); 40067db96d56Sopenharmony_ci return -1; 40077db96d56Sopenharmony_ci } 40087db96d56Sopenharmony_ci 40097db96d56Sopenharmony_ci if (dictitems == Py_None) 40107db96d56Sopenharmony_ci dictitems = NULL; 40117db96d56Sopenharmony_ci else if (!PyIter_Check(dictitems)) { 40127db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, "fifth element of the tuple " 40137db96d56Sopenharmony_ci "returned by __reduce__ must be an iterator, not %s", 40147db96d56Sopenharmony_ci Py_TYPE(dictitems)->tp_name); 40157db96d56Sopenharmony_ci return -1; 40167db96d56Sopenharmony_ci } 40177db96d56Sopenharmony_ci 40187db96d56Sopenharmony_ci if (state_setter == Py_None) 40197db96d56Sopenharmony_ci state_setter = NULL; 40207db96d56Sopenharmony_ci else if (!PyCallable_Check(state_setter)) { 40217db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, "sixth element of the tuple " 40227db96d56Sopenharmony_ci "returned by __reduce__ must be a function, not %s", 40237db96d56Sopenharmony_ci Py_TYPE(state_setter)->tp_name); 40247db96d56Sopenharmony_ci return -1; 40257db96d56Sopenharmony_ci } 40267db96d56Sopenharmony_ci 40277db96d56Sopenharmony_ci if (self->proto >= 2) { 40287db96d56Sopenharmony_ci PyObject *name; 40297db96d56Sopenharmony_ci 40307db96d56Sopenharmony_ci if (_PyObject_LookupAttr(callable, &_Py_ID(__name__), &name) < 0) { 40317db96d56Sopenharmony_ci return -1; 40327db96d56Sopenharmony_ci } 40337db96d56Sopenharmony_ci if (name != NULL && PyUnicode_Check(name)) { 40347db96d56Sopenharmony_ci use_newobj_ex = _PyUnicode_Equal(name, &_Py_ID(__newobj_ex__)); 40357db96d56Sopenharmony_ci if (!use_newobj_ex) { 40367db96d56Sopenharmony_ci use_newobj = _PyUnicode_Equal(name, &_Py_ID(__newobj__)); 40377db96d56Sopenharmony_ci } 40387db96d56Sopenharmony_ci } 40397db96d56Sopenharmony_ci Py_XDECREF(name); 40407db96d56Sopenharmony_ci } 40417db96d56Sopenharmony_ci 40427db96d56Sopenharmony_ci if (use_newobj_ex) { 40437db96d56Sopenharmony_ci PyObject *cls; 40447db96d56Sopenharmony_ci PyObject *args; 40457db96d56Sopenharmony_ci PyObject *kwargs; 40467db96d56Sopenharmony_ci 40477db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(argtup) != 3) { 40487db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 40497db96d56Sopenharmony_ci "length of the NEWOBJ_EX argument tuple must be " 40507db96d56Sopenharmony_ci "exactly 3, not %zd", PyTuple_GET_SIZE(argtup)); 40517db96d56Sopenharmony_ci return -1; 40527db96d56Sopenharmony_ci } 40537db96d56Sopenharmony_ci 40547db96d56Sopenharmony_ci cls = PyTuple_GET_ITEM(argtup, 0); 40557db96d56Sopenharmony_ci if (!PyType_Check(cls)) { 40567db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 40577db96d56Sopenharmony_ci "first item from NEWOBJ_EX argument tuple must " 40587db96d56Sopenharmony_ci "be a class, not %.200s", Py_TYPE(cls)->tp_name); 40597db96d56Sopenharmony_ci return -1; 40607db96d56Sopenharmony_ci } 40617db96d56Sopenharmony_ci args = PyTuple_GET_ITEM(argtup, 1); 40627db96d56Sopenharmony_ci if (!PyTuple_Check(args)) { 40637db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 40647db96d56Sopenharmony_ci "second item from NEWOBJ_EX argument tuple must " 40657db96d56Sopenharmony_ci "be a tuple, not %.200s", Py_TYPE(args)->tp_name); 40667db96d56Sopenharmony_ci return -1; 40677db96d56Sopenharmony_ci } 40687db96d56Sopenharmony_ci kwargs = PyTuple_GET_ITEM(argtup, 2); 40697db96d56Sopenharmony_ci if (!PyDict_Check(kwargs)) { 40707db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 40717db96d56Sopenharmony_ci "third item from NEWOBJ_EX argument tuple must " 40727db96d56Sopenharmony_ci "be a dict, not %.200s", Py_TYPE(kwargs)->tp_name); 40737db96d56Sopenharmony_ci return -1; 40747db96d56Sopenharmony_ci } 40757db96d56Sopenharmony_ci 40767db96d56Sopenharmony_ci if (self->proto >= 4) { 40777db96d56Sopenharmony_ci if (save(self, cls, 0) < 0 || 40787db96d56Sopenharmony_ci save(self, args, 0) < 0 || 40797db96d56Sopenharmony_ci save(self, kwargs, 0) < 0 || 40807db96d56Sopenharmony_ci _Pickler_Write(self, &newobj_ex_op, 1) < 0) { 40817db96d56Sopenharmony_ci return -1; 40827db96d56Sopenharmony_ci } 40837db96d56Sopenharmony_ci } 40847db96d56Sopenharmony_ci else { 40857db96d56Sopenharmony_ci PyObject *newargs; 40867db96d56Sopenharmony_ci PyObject *cls_new; 40877db96d56Sopenharmony_ci Py_ssize_t i; 40887db96d56Sopenharmony_ci 40897db96d56Sopenharmony_ci newargs = PyTuple_New(PyTuple_GET_SIZE(args) + 2); 40907db96d56Sopenharmony_ci if (newargs == NULL) 40917db96d56Sopenharmony_ci return -1; 40927db96d56Sopenharmony_ci 40937db96d56Sopenharmony_ci cls_new = PyObject_GetAttr(cls, &_Py_ID(__new__)); 40947db96d56Sopenharmony_ci if (cls_new == NULL) { 40957db96d56Sopenharmony_ci Py_DECREF(newargs); 40967db96d56Sopenharmony_ci return -1; 40977db96d56Sopenharmony_ci } 40987db96d56Sopenharmony_ci PyTuple_SET_ITEM(newargs, 0, cls_new); 40997db96d56Sopenharmony_ci Py_INCREF(cls); 41007db96d56Sopenharmony_ci PyTuple_SET_ITEM(newargs, 1, cls); 41017db96d56Sopenharmony_ci for (i = 0; i < PyTuple_GET_SIZE(args); i++) { 41027db96d56Sopenharmony_ci PyObject *item = PyTuple_GET_ITEM(args, i); 41037db96d56Sopenharmony_ci Py_INCREF(item); 41047db96d56Sopenharmony_ci PyTuple_SET_ITEM(newargs, i + 2, item); 41057db96d56Sopenharmony_ci } 41067db96d56Sopenharmony_ci 41077db96d56Sopenharmony_ci callable = PyObject_Call(st->partial, newargs, kwargs); 41087db96d56Sopenharmony_ci Py_DECREF(newargs); 41097db96d56Sopenharmony_ci if (callable == NULL) 41107db96d56Sopenharmony_ci return -1; 41117db96d56Sopenharmony_ci 41127db96d56Sopenharmony_ci newargs = PyTuple_New(0); 41137db96d56Sopenharmony_ci if (newargs == NULL) { 41147db96d56Sopenharmony_ci Py_DECREF(callable); 41157db96d56Sopenharmony_ci return -1; 41167db96d56Sopenharmony_ci } 41177db96d56Sopenharmony_ci 41187db96d56Sopenharmony_ci if (save(self, callable, 0) < 0 || 41197db96d56Sopenharmony_ci save(self, newargs, 0) < 0 || 41207db96d56Sopenharmony_ci _Pickler_Write(self, &reduce_op, 1) < 0) { 41217db96d56Sopenharmony_ci Py_DECREF(newargs); 41227db96d56Sopenharmony_ci Py_DECREF(callable); 41237db96d56Sopenharmony_ci return -1; 41247db96d56Sopenharmony_ci } 41257db96d56Sopenharmony_ci Py_DECREF(newargs); 41267db96d56Sopenharmony_ci Py_DECREF(callable); 41277db96d56Sopenharmony_ci } 41287db96d56Sopenharmony_ci } 41297db96d56Sopenharmony_ci else if (use_newobj) { 41307db96d56Sopenharmony_ci PyObject *cls; 41317db96d56Sopenharmony_ci PyObject *newargtup; 41327db96d56Sopenharmony_ci PyObject *obj_class; 41337db96d56Sopenharmony_ci int p; 41347db96d56Sopenharmony_ci 41357db96d56Sopenharmony_ci /* Sanity checks. */ 41367db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(argtup) < 1) { 41377db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "__newobj__ arglist is empty"); 41387db96d56Sopenharmony_ci return -1; 41397db96d56Sopenharmony_ci } 41407db96d56Sopenharmony_ci 41417db96d56Sopenharmony_ci cls = PyTuple_GET_ITEM(argtup, 0); 41427db96d56Sopenharmony_ci if (!PyType_Check(cls)) { 41437db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "args[0] from " 41447db96d56Sopenharmony_ci "__newobj__ args is not a type"); 41457db96d56Sopenharmony_ci return -1; 41467db96d56Sopenharmony_ci } 41477db96d56Sopenharmony_ci 41487db96d56Sopenharmony_ci if (obj != NULL) { 41497db96d56Sopenharmony_ci obj_class = get_class(obj); 41507db96d56Sopenharmony_ci if (obj_class == NULL) { 41517db96d56Sopenharmony_ci return -1; 41527db96d56Sopenharmony_ci } 41537db96d56Sopenharmony_ci p = obj_class != cls; 41547db96d56Sopenharmony_ci Py_DECREF(obj_class); 41557db96d56Sopenharmony_ci if (p) { 41567db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, "args[0] from " 41577db96d56Sopenharmony_ci "__newobj__ args has the wrong class"); 41587db96d56Sopenharmony_ci return -1; 41597db96d56Sopenharmony_ci } 41607db96d56Sopenharmony_ci } 41617db96d56Sopenharmony_ci /* XXX: These calls save() are prone to infinite recursion. Imagine 41627db96d56Sopenharmony_ci what happen if the value returned by the __reduce__() method of 41637db96d56Sopenharmony_ci some extension type contains another object of the same type. Ouch! 41647db96d56Sopenharmony_ci 41657db96d56Sopenharmony_ci Here is a quick example, that I ran into, to illustrate what I 41667db96d56Sopenharmony_ci mean: 41677db96d56Sopenharmony_ci 41687db96d56Sopenharmony_ci >>> import pickle, copyreg 41697db96d56Sopenharmony_ci >>> copyreg.dispatch_table.pop(complex) 41707db96d56Sopenharmony_ci >>> pickle.dumps(1+2j) 41717db96d56Sopenharmony_ci Traceback (most recent call last): 41727db96d56Sopenharmony_ci ... 41737db96d56Sopenharmony_ci RecursionError: maximum recursion depth exceeded 41747db96d56Sopenharmony_ci 41757db96d56Sopenharmony_ci Removing the complex class from copyreg.dispatch_table made the 41767db96d56Sopenharmony_ci __reduce_ex__() method emit another complex object: 41777db96d56Sopenharmony_ci 41787db96d56Sopenharmony_ci >>> (1+1j).__reduce_ex__(2) 41797db96d56Sopenharmony_ci (<function __newobj__ at 0xb7b71c3c>, 41807db96d56Sopenharmony_ci (<class 'complex'>, (1+1j)), None, None, None) 41817db96d56Sopenharmony_ci 41827db96d56Sopenharmony_ci Thus when save() was called on newargstup (the 2nd item) recursion 41837db96d56Sopenharmony_ci ensued. Of course, the bug was in the complex class which had a 41847db96d56Sopenharmony_ci broken __getnewargs__() that emitted another complex object. But, 41857db96d56Sopenharmony_ci the point, here, is it is quite easy to end up with a broken reduce 41867db96d56Sopenharmony_ci function. */ 41877db96d56Sopenharmony_ci 41887db96d56Sopenharmony_ci /* Save the class and its __new__ arguments. */ 41897db96d56Sopenharmony_ci if (save(self, cls, 0) < 0) 41907db96d56Sopenharmony_ci return -1; 41917db96d56Sopenharmony_ci 41927db96d56Sopenharmony_ci newargtup = PyTuple_GetSlice(argtup, 1, PyTuple_GET_SIZE(argtup)); 41937db96d56Sopenharmony_ci if (newargtup == NULL) 41947db96d56Sopenharmony_ci return -1; 41957db96d56Sopenharmony_ci 41967db96d56Sopenharmony_ci p = save(self, newargtup, 0); 41977db96d56Sopenharmony_ci Py_DECREF(newargtup); 41987db96d56Sopenharmony_ci if (p < 0) 41997db96d56Sopenharmony_ci return -1; 42007db96d56Sopenharmony_ci 42017db96d56Sopenharmony_ci /* Add NEWOBJ opcode. */ 42027db96d56Sopenharmony_ci if (_Pickler_Write(self, &newobj_op, 1) < 0) 42037db96d56Sopenharmony_ci return -1; 42047db96d56Sopenharmony_ci } 42057db96d56Sopenharmony_ci else { /* Not using NEWOBJ. */ 42067db96d56Sopenharmony_ci if (save(self, callable, 0) < 0 || 42077db96d56Sopenharmony_ci save(self, argtup, 0) < 0 || 42087db96d56Sopenharmony_ci _Pickler_Write(self, &reduce_op, 1) < 0) 42097db96d56Sopenharmony_ci return -1; 42107db96d56Sopenharmony_ci } 42117db96d56Sopenharmony_ci 42127db96d56Sopenharmony_ci /* obj can be NULL when save_reduce() is used directly. A NULL obj means 42137db96d56Sopenharmony_ci the caller do not want to memoize the object. Not particularly useful, 42147db96d56Sopenharmony_ci but that is to mimic the behavior save_reduce() in pickle.py when 42157db96d56Sopenharmony_ci obj is None. */ 42167db96d56Sopenharmony_ci if (obj != NULL) { 42177db96d56Sopenharmony_ci /* If the object is already in the memo, this means it is 42187db96d56Sopenharmony_ci recursive. In this case, throw away everything we put on the 42197db96d56Sopenharmony_ci stack, and fetch the object back from the memo. */ 42207db96d56Sopenharmony_ci if (PyMemoTable_Get(self->memo, obj)) { 42217db96d56Sopenharmony_ci const char pop_op = POP; 42227db96d56Sopenharmony_ci 42237db96d56Sopenharmony_ci if (_Pickler_Write(self, &pop_op, 1) < 0) 42247db96d56Sopenharmony_ci return -1; 42257db96d56Sopenharmony_ci if (memo_get(self, obj) < 0) 42267db96d56Sopenharmony_ci return -1; 42277db96d56Sopenharmony_ci 42287db96d56Sopenharmony_ci return 0; 42297db96d56Sopenharmony_ci } 42307db96d56Sopenharmony_ci else if (memo_put(self, obj) < 0) 42317db96d56Sopenharmony_ci return -1; 42327db96d56Sopenharmony_ci } 42337db96d56Sopenharmony_ci 42347db96d56Sopenharmony_ci if (listitems && batch_list(self, listitems) < 0) 42357db96d56Sopenharmony_ci return -1; 42367db96d56Sopenharmony_ci 42377db96d56Sopenharmony_ci if (dictitems && batch_dict(self, dictitems) < 0) 42387db96d56Sopenharmony_ci return -1; 42397db96d56Sopenharmony_ci 42407db96d56Sopenharmony_ci if (state) { 42417db96d56Sopenharmony_ci if (state_setter == NULL) { 42427db96d56Sopenharmony_ci if (save(self, state, 0) < 0 || 42437db96d56Sopenharmony_ci _Pickler_Write(self, &build_op, 1) < 0) 42447db96d56Sopenharmony_ci return -1; 42457db96d56Sopenharmony_ci } 42467db96d56Sopenharmony_ci else { 42477db96d56Sopenharmony_ci 42487db96d56Sopenharmony_ci /* If a state_setter is specified, call it instead of load_build to 42497db96d56Sopenharmony_ci * update obj's with its previous state. 42507db96d56Sopenharmony_ci * The first 4 save/write instructions push state_setter and its 42517db96d56Sopenharmony_ci * tuple of expected arguments (obj, state) onto the stack. The 42527db96d56Sopenharmony_ci * REDUCE opcode triggers the state_setter(obj, state) function 42537db96d56Sopenharmony_ci * call. Finally, because state-updating routines only do in-place 42547db96d56Sopenharmony_ci * modification, the whole operation has to be stack-transparent. 42557db96d56Sopenharmony_ci * Thus, we finally pop the call's output from the stack.*/ 42567db96d56Sopenharmony_ci 42577db96d56Sopenharmony_ci const char tupletwo_op = TUPLE2; 42587db96d56Sopenharmony_ci const char pop_op = POP; 42597db96d56Sopenharmony_ci if (save(self, state_setter, 0) < 0 || 42607db96d56Sopenharmony_ci save(self, obj, 0) < 0 || save(self, state, 0) < 0 || 42617db96d56Sopenharmony_ci _Pickler_Write(self, &tupletwo_op, 1) < 0 || 42627db96d56Sopenharmony_ci _Pickler_Write(self, &reduce_op, 1) < 0 || 42637db96d56Sopenharmony_ci _Pickler_Write(self, &pop_op, 1) < 0) 42647db96d56Sopenharmony_ci return -1; 42657db96d56Sopenharmony_ci } 42667db96d56Sopenharmony_ci } 42677db96d56Sopenharmony_ci return 0; 42687db96d56Sopenharmony_ci} 42697db96d56Sopenharmony_ci 42707db96d56Sopenharmony_cistatic int 42717db96d56Sopenharmony_cisave(PicklerObject *self, PyObject *obj, int pers_save) 42727db96d56Sopenharmony_ci{ 42737db96d56Sopenharmony_ci PyTypeObject *type; 42747db96d56Sopenharmony_ci PyObject *reduce_func = NULL; 42757db96d56Sopenharmony_ci PyObject *reduce_value = NULL; 42767db96d56Sopenharmony_ci int status = 0; 42777db96d56Sopenharmony_ci 42787db96d56Sopenharmony_ci if (_Pickler_OpcodeBoundary(self) < 0) 42797db96d56Sopenharmony_ci return -1; 42807db96d56Sopenharmony_ci 42817db96d56Sopenharmony_ci /* The extra pers_save argument is necessary to avoid calling save_pers() 42827db96d56Sopenharmony_ci on its returned object. */ 42837db96d56Sopenharmony_ci if (!pers_save && self->pers_func) { 42847db96d56Sopenharmony_ci /* save_pers() returns: 42857db96d56Sopenharmony_ci -1 to signal an error; 42867db96d56Sopenharmony_ci 0 if it did nothing successfully; 42877db96d56Sopenharmony_ci 1 if a persistent id was saved. 42887db96d56Sopenharmony_ci */ 42897db96d56Sopenharmony_ci if ((status = save_pers(self, obj)) != 0) 42907db96d56Sopenharmony_ci return status; 42917db96d56Sopenharmony_ci } 42927db96d56Sopenharmony_ci 42937db96d56Sopenharmony_ci type = Py_TYPE(obj); 42947db96d56Sopenharmony_ci 42957db96d56Sopenharmony_ci /* The old cPickle had an optimization that used switch-case statement 42967db96d56Sopenharmony_ci dispatching on the first letter of the type name. This has was removed 42977db96d56Sopenharmony_ci since benchmarks shown that this optimization was actually slowing 42987db96d56Sopenharmony_ci things down. */ 42997db96d56Sopenharmony_ci 43007db96d56Sopenharmony_ci /* Atom types; these aren't memoized, so don't check the memo. */ 43017db96d56Sopenharmony_ci 43027db96d56Sopenharmony_ci if (obj == Py_None) { 43037db96d56Sopenharmony_ci return save_none(self, obj); 43047db96d56Sopenharmony_ci } 43057db96d56Sopenharmony_ci else if (obj == Py_False || obj == Py_True) { 43067db96d56Sopenharmony_ci return save_bool(self, obj); 43077db96d56Sopenharmony_ci } 43087db96d56Sopenharmony_ci else if (type == &PyLong_Type) { 43097db96d56Sopenharmony_ci return save_long(self, obj); 43107db96d56Sopenharmony_ci } 43117db96d56Sopenharmony_ci else if (type == &PyFloat_Type) { 43127db96d56Sopenharmony_ci return save_float(self, obj); 43137db96d56Sopenharmony_ci } 43147db96d56Sopenharmony_ci 43157db96d56Sopenharmony_ci /* Check the memo to see if it has the object. If so, generate 43167db96d56Sopenharmony_ci a GET (or BINGET) opcode, instead of pickling the object 43177db96d56Sopenharmony_ci once again. */ 43187db96d56Sopenharmony_ci if (PyMemoTable_Get(self->memo, obj)) { 43197db96d56Sopenharmony_ci return memo_get(self, obj); 43207db96d56Sopenharmony_ci } 43217db96d56Sopenharmony_ci 43227db96d56Sopenharmony_ci if (type == &PyBytes_Type) { 43237db96d56Sopenharmony_ci return save_bytes(self, obj); 43247db96d56Sopenharmony_ci } 43257db96d56Sopenharmony_ci else if (type == &PyUnicode_Type) { 43267db96d56Sopenharmony_ci return save_unicode(self, obj); 43277db96d56Sopenharmony_ci } 43287db96d56Sopenharmony_ci 43297db96d56Sopenharmony_ci /* We're only calling _Py_EnterRecursiveCall here so that atomic 43307db96d56Sopenharmony_ci types above are pickled faster. */ 43317db96d56Sopenharmony_ci if (_Py_EnterRecursiveCall(" while pickling an object")) { 43327db96d56Sopenharmony_ci return -1; 43337db96d56Sopenharmony_ci } 43347db96d56Sopenharmony_ci 43357db96d56Sopenharmony_ci if (type == &PyDict_Type) { 43367db96d56Sopenharmony_ci status = save_dict(self, obj); 43377db96d56Sopenharmony_ci goto done; 43387db96d56Sopenharmony_ci } 43397db96d56Sopenharmony_ci else if (type == &PySet_Type) { 43407db96d56Sopenharmony_ci status = save_set(self, obj); 43417db96d56Sopenharmony_ci goto done; 43427db96d56Sopenharmony_ci } 43437db96d56Sopenharmony_ci else if (type == &PyFrozenSet_Type) { 43447db96d56Sopenharmony_ci status = save_frozenset(self, obj); 43457db96d56Sopenharmony_ci goto done; 43467db96d56Sopenharmony_ci } 43477db96d56Sopenharmony_ci else if (type == &PyList_Type) { 43487db96d56Sopenharmony_ci status = save_list(self, obj); 43497db96d56Sopenharmony_ci goto done; 43507db96d56Sopenharmony_ci } 43517db96d56Sopenharmony_ci else if (type == &PyTuple_Type) { 43527db96d56Sopenharmony_ci status = save_tuple(self, obj); 43537db96d56Sopenharmony_ci goto done; 43547db96d56Sopenharmony_ci } 43557db96d56Sopenharmony_ci else if (type == &PyByteArray_Type) { 43567db96d56Sopenharmony_ci status = save_bytearray(self, obj); 43577db96d56Sopenharmony_ci goto done; 43587db96d56Sopenharmony_ci } 43597db96d56Sopenharmony_ci else if (type == &PyPickleBuffer_Type) { 43607db96d56Sopenharmony_ci status = save_picklebuffer(self, obj); 43617db96d56Sopenharmony_ci goto done; 43627db96d56Sopenharmony_ci } 43637db96d56Sopenharmony_ci 43647db96d56Sopenharmony_ci /* Now, check reducer_override. If it returns NotImplemented, 43657db96d56Sopenharmony_ci * fallback to save_type or save_global, and then perhaps to the 43667db96d56Sopenharmony_ci * regular reduction mechanism. 43677db96d56Sopenharmony_ci */ 43687db96d56Sopenharmony_ci if (self->reducer_override != NULL) { 43697db96d56Sopenharmony_ci reduce_value = PyObject_CallOneArg(self->reducer_override, obj); 43707db96d56Sopenharmony_ci if (reduce_value == NULL) { 43717db96d56Sopenharmony_ci goto error; 43727db96d56Sopenharmony_ci } 43737db96d56Sopenharmony_ci if (reduce_value != Py_NotImplemented) { 43747db96d56Sopenharmony_ci goto reduce; 43757db96d56Sopenharmony_ci } 43767db96d56Sopenharmony_ci Py_DECREF(reduce_value); 43777db96d56Sopenharmony_ci reduce_value = NULL; 43787db96d56Sopenharmony_ci } 43797db96d56Sopenharmony_ci 43807db96d56Sopenharmony_ci if (type == &PyType_Type) { 43817db96d56Sopenharmony_ci status = save_type(self, obj); 43827db96d56Sopenharmony_ci goto done; 43837db96d56Sopenharmony_ci } 43847db96d56Sopenharmony_ci else if (type == &PyFunction_Type) { 43857db96d56Sopenharmony_ci status = save_global(self, obj, NULL); 43867db96d56Sopenharmony_ci goto done; 43877db96d56Sopenharmony_ci } 43887db96d56Sopenharmony_ci 43897db96d56Sopenharmony_ci /* XXX: This part needs some unit tests. */ 43907db96d56Sopenharmony_ci 43917db96d56Sopenharmony_ci /* Get a reduction callable, and call it. This may come from 43927db96d56Sopenharmony_ci * self.dispatch_table, copyreg.dispatch_table, the object's 43937db96d56Sopenharmony_ci * __reduce_ex__ method, or the object's __reduce__ method. 43947db96d56Sopenharmony_ci */ 43957db96d56Sopenharmony_ci if (self->dispatch_table == NULL) { 43967db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 43977db96d56Sopenharmony_ci reduce_func = PyDict_GetItemWithError(st->dispatch_table, 43987db96d56Sopenharmony_ci (PyObject *)type); 43997db96d56Sopenharmony_ci if (reduce_func == NULL) { 44007db96d56Sopenharmony_ci if (PyErr_Occurred()) { 44017db96d56Sopenharmony_ci goto error; 44027db96d56Sopenharmony_ci } 44037db96d56Sopenharmony_ci } else { 44047db96d56Sopenharmony_ci /* PyDict_GetItemWithError() returns a borrowed reference. 44057db96d56Sopenharmony_ci Increase the reference count to be consistent with 44067db96d56Sopenharmony_ci PyObject_GetItem and _PyObject_GetAttrId used below. */ 44077db96d56Sopenharmony_ci Py_INCREF(reduce_func); 44087db96d56Sopenharmony_ci } 44097db96d56Sopenharmony_ci } else { 44107db96d56Sopenharmony_ci reduce_func = PyObject_GetItem(self->dispatch_table, 44117db96d56Sopenharmony_ci (PyObject *)type); 44127db96d56Sopenharmony_ci if (reduce_func == NULL) { 44137db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_KeyError)) 44147db96d56Sopenharmony_ci PyErr_Clear(); 44157db96d56Sopenharmony_ci else 44167db96d56Sopenharmony_ci goto error; 44177db96d56Sopenharmony_ci } 44187db96d56Sopenharmony_ci } 44197db96d56Sopenharmony_ci if (reduce_func != NULL) { 44207db96d56Sopenharmony_ci Py_INCREF(obj); 44217db96d56Sopenharmony_ci reduce_value = _Pickle_FastCall(reduce_func, obj); 44227db96d56Sopenharmony_ci } 44237db96d56Sopenharmony_ci else if (PyType_IsSubtype(type, &PyType_Type)) { 44247db96d56Sopenharmony_ci status = save_global(self, obj, NULL); 44257db96d56Sopenharmony_ci goto done; 44267db96d56Sopenharmony_ci } 44277db96d56Sopenharmony_ci else { 44287db96d56Sopenharmony_ci /* XXX: If the __reduce__ method is defined, __reduce_ex__ is 44297db96d56Sopenharmony_ci automatically defined as __reduce__. While this is convenient, this 44307db96d56Sopenharmony_ci make it impossible to know which method was actually called. Of 44317db96d56Sopenharmony_ci course, this is not a big deal. But still, it would be nice to let 44327db96d56Sopenharmony_ci the user know which method was called when something go 44337db96d56Sopenharmony_ci wrong. Incidentally, this means if __reduce_ex__ is not defined, we 44347db96d56Sopenharmony_ci don't actually have to check for a __reduce__ method. */ 44357db96d56Sopenharmony_ci 44367db96d56Sopenharmony_ci /* Check for a __reduce_ex__ method. */ 44377db96d56Sopenharmony_ci if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce_ex__), &reduce_func) < 0) { 44387db96d56Sopenharmony_ci goto error; 44397db96d56Sopenharmony_ci } 44407db96d56Sopenharmony_ci if (reduce_func != NULL) { 44417db96d56Sopenharmony_ci PyObject *proto; 44427db96d56Sopenharmony_ci proto = PyLong_FromLong(self->proto); 44437db96d56Sopenharmony_ci if (proto != NULL) { 44447db96d56Sopenharmony_ci reduce_value = _Pickle_FastCall(reduce_func, proto); 44457db96d56Sopenharmony_ci } 44467db96d56Sopenharmony_ci } 44477db96d56Sopenharmony_ci else { 44487db96d56Sopenharmony_ci /* Check for a __reduce__ method. */ 44497db96d56Sopenharmony_ci if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce__), &reduce_func) < 0) { 44507db96d56Sopenharmony_ci goto error; 44517db96d56Sopenharmony_ci } 44527db96d56Sopenharmony_ci if (reduce_func != NULL) { 44537db96d56Sopenharmony_ci reduce_value = PyObject_CallNoArgs(reduce_func); 44547db96d56Sopenharmony_ci } 44557db96d56Sopenharmony_ci else { 44567db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 44577db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 44587db96d56Sopenharmony_ci "can't pickle '%.200s' object: %R", 44597db96d56Sopenharmony_ci type->tp_name, obj); 44607db96d56Sopenharmony_ci goto error; 44617db96d56Sopenharmony_ci } 44627db96d56Sopenharmony_ci } 44637db96d56Sopenharmony_ci } 44647db96d56Sopenharmony_ci 44657db96d56Sopenharmony_ci if (reduce_value == NULL) 44667db96d56Sopenharmony_ci goto error; 44677db96d56Sopenharmony_ci 44687db96d56Sopenharmony_ci reduce: 44697db96d56Sopenharmony_ci if (PyUnicode_Check(reduce_value)) { 44707db96d56Sopenharmony_ci status = save_global(self, obj, reduce_value); 44717db96d56Sopenharmony_ci goto done; 44727db96d56Sopenharmony_ci } 44737db96d56Sopenharmony_ci 44747db96d56Sopenharmony_ci if (!PyTuple_Check(reduce_value)) { 44757db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 44767db96d56Sopenharmony_ci PyErr_SetString(st->PicklingError, 44777db96d56Sopenharmony_ci "__reduce__ must return a string or tuple"); 44787db96d56Sopenharmony_ci goto error; 44797db96d56Sopenharmony_ci } 44807db96d56Sopenharmony_ci 44817db96d56Sopenharmony_ci status = save_reduce(self, reduce_value, obj); 44827db96d56Sopenharmony_ci 44837db96d56Sopenharmony_ci if (0) { 44847db96d56Sopenharmony_ci error: 44857db96d56Sopenharmony_ci status = -1; 44867db96d56Sopenharmony_ci } 44877db96d56Sopenharmony_ci done: 44887db96d56Sopenharmony_ci 44897db96d56Sopenharmony_ci _Py_LeaveRecursiveCall(); 44907db96d56Sopenharmony_ci Py_XDECREF(reduce_func); 44917db96d56Sopenharmony_ci Py_XDECREF(reduce_value); 44927db96d56Sopenharmony_ci 44937db96d56Sopenharmony_ci return status; 44947db96d56Sopenharmony_ci} 44957db96d56Sopenharmony_ci 44967db96d56Sopenharmony_cistatic int 44977db96d56Sopenharmony_cidump(PicklerObject *self, PyObject *obj) 44987db96d56Sopenharmony_ci{ 44997db96d56Sopenharmony_ci const char stop_op = STOP; 45007db96d56Sopenharmony_ci int status = -1; 45017db96d56Sopenharmony_ci PyObject *tmp; 45027db96d56Sopenharmony_ci 45037db96d56Sopenharmony_ci if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(reducer_override), 45047db96d56Sopenharmony_ci &tmp) < 0) { 45057db96d56Sopenharmony_ci goto error; 45067db96d56Sopenharmony_ci } 45077db96d56Sopenharmony_ci /* Cache the reducer_override method, if it exists. */ 45087db96d56Sopenharmony_ci if (tmp != NULL) { 45097db96d56Sopenharmony_ci Py_XSETREF(self->reducer_override, tmp); 45107db96d56Sopenharmony_ci } 45117db96d56Sopenharmony_ci else { 45127db96d56Sopenharmony_ci Py_CLEAR(self->reducer_override); 45137db96d56Sopenharmony_ci } 45147db96d56Sopenharmony_ci 45157db96d56Sopenharmony_ci if (self->proto >= 2) { 45167db96d56Sopenharmony_ci char header[2]; 45177db96d56Sopenharmony_ci 45187db96d56Sopenharmony_ci header[0] = PROTO; 45197db96d56Sopenharmony_ci assert(self->proto >= 0 && self->proto < 256); 45207db96d56Sopenharmony_ci header[1] = (unsigned char)self->proto; 45217db96d56Sopenharmony_ci if (_Pickler_Write(self, header, 2) < 0) 45227db96d56Sopenharmony_ci goto error; 45237db96d56Sopenharmony_ci if (self->proto >= 4) 45247db96d56Sopenharmony_ci self->framing = 1; 45257db96d56Sopenharmony_ci } 45267db96d56Sopenharmony_ci 45277db96d56Sopenharmony_ci if (save(self, obj, 0) < 0 || 45287db96d56Sopenharmony_ci _Pickler_Write(self, &stop_op, 1) < 0 || 45297db96d56Sopenharmony_ci _Pickler_CommitFrame(self) < 0) 45307db96d56Sopenharmony_ci goto error; 45317db96d56Sopenharmony_ci 45327db96d56Sopenharmony_ci // Success 45337db96d56Sopenharmony_ci status = 0; 45347db96d56Sopenharmony_ci 45357db96d56Sopenharmony_ci error: 45367db96d56Sopenharmony_ci self->framing = 0; 45377db96d56Sopenharmony_ci 45387db96d56Sopenharmony_ci /* Break the reference cycle we generated at the beginning this function 45397db96d56Sopenharmony_ci * call when setting the reducer_override attribute of the Pickler instance 45407db96d56Sopenharmony_ci * to a bound method of the same instance. This is important as the Pickler 45417db96d56Sopenharmony_ci * instance holds a reference to each object it has pickled (through its 45427db96d56Sopenharmony_ci * memo): thus, these objects won't be garbage-collected as long as the 45437db96d56Sopenharmony_ci * Pickler itself is not collected. */ 45447db96d56Sopenharmony_ci Py_CLEAR(self->reducer_override); 45457db96d56Sopenharmony_ci return status; 45467db96d56Sopenharmony_ci} 45477db96d56Sopenharmony_ci 45487db96d56Sopenharmony_ci/*[clinic input] 45497db96d56Sopenharmony_ci 45507db96d56Sopenharmony_ci_pickle.Pickler.clear_memo 45517db96d56Sopenharmony_ci 45527db96d56Sopenharmony_ciClears the pickler's "memo". 45537db96d56Sopenharmony_ci 45547db96d56Sopenharmony_ciThe memo is the data structure that remembers which objects the 45557db96d56Sopenharmony_cipickler has already seen, so that shared or recursive objects are 45567db96d56Sopenharmony_cipickled by reference and not by value. This method is useful when 45577db96d56Sopenharmony_cire-using picklers. 45587db96d56Sopenharmony_ci[clinic start generated code]*/ 45597db96d56Sopenharmony_ci 45607db96d56Sopenharmony_cistatic PyObject * 45617db96d56Sopenharmony_ci_pickle_Pickler_clear_memo_impl(PicklerObject *self) 45627db96d56Sopenharmony_ci/*[clinic end generated code: output=8665c8658aaa094b input=01bdad52f3d93e56]*/ 45637db96d56Sopenharmony_ci{ 45647db96d56Sopenharmony_ci if (self->memo) 45657db96d56Sopenharmony_ci PyMemoTable_Clear(self->memo); 45667db96d56Sopenharmony_ci 45677db96d56Sopenharmony_ci Py_RETURN_NONE; 45687db96d56Sopenharmony_ci} 45697db96d56Sopenharmony_ci 45707db96d56Sopenharmony_ci/*[clinic input] 45717db96d56Sopenharmony_ci 45727db96d56Sopenharmony_ci_pickle.Pickler.dump 45737db96d56Sopenharmony_ci 45747db96d56Sopenharmony_ci obj: object 45757db96d56Sopenharmony_ci / 45767db96d56Sopenharmony_ci 45777db96d56Sopenharmony_ciWrite a pickled representation of the given object to the open file. 45787db96d56Sopenharmony_ci[clinic start generated code]*/ 45797db96d56Sopenharmony_ci 45807db96d56Sopenharmony_cistatic PyObject * 45817db96d56Sopenharmony_ci_pickle_Pickler_dump(PicklerObject *self, PyObject *obj) 45827db96d56Sopenharmony_ci/*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ 45837db96d56Sopenharmony_ci{ 45847db96d56Sopenharmony_ci /* Check whether the Pickler was initialized correctly (issue3664). 45857db96d56Sopenharmony_ci Developers often forget to call __init__() in their subclasses, which 45867db96d56Sopenharmony_ci would trigger a segfault without this check. */ 45877db96d56Sopenharmony_ci if (self->write == NULL) { 45887db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 45897db96d56Sopenharmony_ci PyErr_Format(st->PicklingError, 45907db96d56Sopenharmony_ci "Pickler.__init__() was not called by %s.__init__()", 45917db96d56Sopenharmony_ci Py_TYPE(self)->tp_name); 45927db96d56Sopenharmony_ci return NULL; 45937db96d56Sopenharmony_ci } 45947db96d56Sopenharmony_ci 45957db96d56Sopenharmony_ci if (_Pickler_ClearBuffer(self) < 0) 45967db96d56Sopenharmony_ci return NULL; 45977db96d56Sopenharmony_ci 45987db96d56Sopenharmony_ci if (dump(self, obj) < 0) 45997db96d56Sopenharmony_ci return NULL; 46007db96d56Sopenharmony_ci 46017db96d56Sopenharmony_ci if (_Pickler_FlushToFile(self) < 0) 46027db96d56Sopenharmony_ci return NULL; 46037db96d56Sopenharmony_ci 46047db96d56Sopenharmony_ci Py_RETURN_NONE; 46057db96d56Sopenharmony_ci} 46067db96d56Sopenharmony_ci 46077db96d56Sopenharmony_ci/*[clinic input] 46087db96d56Sopenharmony_ci 46097db96d56Sopenharmony_ci_pickle.Pickler.__sizeof__ -> Py_ssize_t 46107db96d56Sopenharmony_ci 46117db96d56Sopenharmony_ciReturns size in memory, in bytes. 46127db96d56Sopenharmony_ci[clinic start generated code]*/ 46137db96d56Sopenharmony_ci 46147db96d56Sopenharmony_cistatic Py_ssize_t 46157db96d56Sopenharmony_ci_pickle_Pickler___sizeof___impl(PicklerObject *self) 46167db96d56Sopenharmony_ci/*[clinic end generated code: output=106edb3123f332e1 input=8cbbec9bd5540d42]*/ 46177db96d56Sopenharmony_ci{ 46187db96d56Sopenharmony_ci Py_ssize_t res, s; 46197db96d56Sopenharmony_ci 46207db96d56Sopenharmony_ci res = _PyObject_SIZE(Py_TYPE(self)); 46217db96d56Sopenharmony_ci if (self->memo != NULL) { 46227db96d56Sopenharmony_ci res += sizeof(PyMemoTable); 46237db96d56Sopenharmony_ci res += self->memo->mt_allocated * sizeof(PyMemoEntry); 46247db96d56Sopenharmony_ci } 46257db96d56Sopenharmony_ci if (self->output_buffer != NULL) { 46267db96d56Sopenharmony_ci s = _PySys_GetSizeOf(self->output_buffer); 46277db96d56Sopenharmony_ci if (s == -1) 46287db96d56Sopenharmony_ci return -1; 46297db96d56Sopenharmony_ci res += s; 46307db96d56Sopenharmony_ci } 46317db96d56Sopenharmony_ci return res; 46327db96d56Sopenharmony_ci} 46337db96d56Sopenharmony_ci 46347db96d56Sopenharmony_cistatic struct PyMethodDef Pickler_methods[] = { 46357db96d56Sopenharmony_ci _PICKLE_PICKLER_DUMP_METHODDEF 46367db96d56Sopenharmony_ci _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF 46377db96d56Sopenharmony_ci _PICKLE_PICKLER___SIZEOF___METHODDEF 46387db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 46397db96d56Sopenharmony_ci}; 46407db96d56Sopenharmony_ci 46417db96d56Sopenharmony_cistatic void 46427db96d56Sopenharmony_ciPickler_dealloc(PicklerObject *self) 46437db96d56Sopenharmony_ci{ 46447db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 46457db96d56Sopenharmony_ci 46467db96d56Sopenharmony_ci Py_XDECREF(self->output_buffer); 46477db96d56Sopenharmony_ci Py_XDECREF(self->write); 46487db96d56Sopenharmony_ci Py_XDECREF(self->pers_func); 46497db96d56Sopenharmony_ci Py_XDECREF(self->dispatch_table); 46507db96d56Sopenharmony_ci Py_XDECREF(self->fast_memo); 46517db96d56Sopenharmony_ci Py_XDECREF(self->reducer_override); 46527db96d56Sopenharmony_ci Py_XDECREF(self->buffer_callback); 46537db96d56Sopenharmony_ci 46547db96d56Sopenharmony_ci PyMemoTable_Del(self->memo); 46557db96d56Sopenharmony_ci 46567db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject *)self); 46577db96d56Sopenharmony_ci} 46587db96d56Sopenharmony_ci 46597db96d56Sopenharmony_cistatic int 46607db96d56Sopenharmony_ciPickler_traverse(PicklerObject *self, visitproc visit, void *arg) 46617db96d56Sopenharmony_ci{ 46627db96d56Sopenharmony_ci Py_VISIT(self->write); 46637db96d56Sopenharmony_ci Py_VISIT(self->pers_func); 46647db96d56Sopenharmony_ci Py_VISIT(self->dispatch_table); 46657db96d56Sopenharmony_ci Py_VISIT(self->fast_memo); 46667db96d56Sopenharmony_ci Py_VISIT(self->reducer_override); 46677db96d56Sopenharmony_ci Py_VISIT(self->buffer_callback); 46687db96d56Sopenharmony_ci return 0; 46697db96d56Sopenharmony_ci} 46707db96d56Sopenharmony_ci 46717db96d56Sopenharmony_cistatic int 46727db96d56Sopenharmony_ciPickler_clear(PicklerObject *self) 46737db96d56Sopenharmony_ci{ 46747db96d56Sopenharmony_ci Py_CLEAR(self->output_buffer); 46757db96d56Sopenharmony_ci Py_CLEAR(self->write); 46767db96d56Sopenharmony_ci Py_CLEAR(self->pers_func); 46777db96d56Sopenharmony_ci Py_CLEAR(self->dispatch_table); 46787db96d56Sopenharmony_ci Py_CLEAR(self->fast_memo); 46797db96d56Sopenharmony_ci Py_CLEAR(self->reducer_override); 46807db96d56Sopenharmony_ci Py_CLEAR(self->buffer_callback); 46817db96d56Sopenharmony_ci 46827db96d56Sopenharmony_ci if (self->memo != NULL) { 46837db96d56Sopenharmony_ci PyMemoTable *memo = self->memo; 46847db96d56Sopenharmony_ci self->memo = NULL; 46857db96d56Sopenharmony_ci PyMemoTable_Del(memo); 46867db96d56Sopenharmony_ci } 46877db96d56Sopenharmony_ci return 0; 46887db96d56Sopenharmony_ci} 46897db96d56Sopenharmony_ci 46907db96d56Sopenharmony_ci 46917db96d56Sopenharmony_ci/*[clinic input] 46927db96d56Sopenharmony_ci 46937db96d56Sopenharmony_ci_pickle.Pickler.__init__ 46947db96d56Sopenharmony_ci 46957db96d56Sopenharmony_ci file: object 46967db96d56Sopenharmony_ci protocol: object = None 46977db96d56Sopenharmony_ci fix_imports: bool = True 46987db96d56Sopenharmony_ci buffer_callback: object = None 46997db96d56Sopenharmony_ci 47007db96d56Sopenharmony_ciThis takes a binary file for writing a pickle data stream. 47017db96d56Sopenharmony_ci 47027db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given 47037db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5. The default 47047db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible 47057db96d56Sopenharmony_ciwith previous versions. 47067db96d56Sopenharmony_ci 47077db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol 47087db96d56Sopenharmony_civersion supported. The higher the protocol used, the more recent the 47097db96d56Sopenharmony_civersion of Python needed to read the pickle produced. 47107db96d56Sopenharmony_ci 47117db96d56Sopenharmony_ciThe *file* argument must have a write() method that accepts a single 47127db96d56Sopenharmony_cibytes argument. It can thus be a file object opened for binary 47137db96d56Sopenharmony_ciwriting, an io.BytesIO instance, or any other custom object that meets 47147db96d56Sopenharmony_cithis interface. 47157db96d56Sopenharmony_ci 47167db96d56Sopenharmony_ciIf *fix_imports* is True and protocol is less than 3, pickle will try 47177db96d56Sopenharmony_cito map the new Python 3 names to the old module names used in Python 47187db96d56Sopenharmony_ci2, so that the pickle data stream is readable with Python 2. 47197db96d56Sopenharmony_ci 47207db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are 47217db96d56Sopenharmony_ciserialized into *file* as part of the pickle stream. 47227db96d56Sopenharmony_ci 47237db96d56Sopenharmony_ciIf *buffer_callback* is not None, then it can be called any number 47247db96d56Sopenharmony_ciof times with a buffer view. If the callback returns a false value 47257db96d56Sopenharmony_ci(such as None), the given buffer is out-of-band; otherwise the 47267db96d56Sopenharmony_cibuffer is serialized in-band, i.e. inside the pickle stream. 47277db96d56Sopenharmony_ci 47287db96d56Sopenharmony_ciIt is an error if *buffer_callback* is not None and *protocol* 47297db96d56Sopenharmony_ciis None or smaller than 5. 47307db96d56Sopenharmony_ci 47317db96d56Sopenharmony_ci[clinic start generated code]*/ 47327db96d56Sopenharmony_ci 47337db96d56Sopenharmony_cistatic int 47347db96d56Sopenharmony_ci_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, 47357db96d56Sopenharmony_ci PyObject *protocol, int fix_imports, 47367db96d56Sopenharmony_ci PyObject *buffer_callback) 47377db96d56Sopenharmony_ci/*[clinic end generated code: output=0abedc50590d259b input=a7c969699bf5dad3]*/ 47387db96d56Sopenharmony_ci{ 47397db96d56Sopenharmony_ci /* In case of multiple __init__() calls, clear previous content. */ 47407db96d56Sopenharmony_ci if (self->write != NULL) 47417db96d56Sopenharmony_ci (void)Pickler_clear(self); 47427db96d56Sopenharmony_ci 47437db96d56Sopenharmony_ci if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0) 47447db96d56Sopenharmony_ci return -1; 47457db96d56Sopenharmony_ci 47467db96d56Sopenharmony_ci if (_Pickler_SetOutputStream(self, file) < 0) 47477db96d56Sopenharmony_ci return -1; 47487db96d56Sopenharmony_ci 47497db96d56Sopenharmony_ci if (_Pickler_SetBufferCallback(self, buffer_callback) < 0) 47507db96d56Sopenharmony_ci return -1; 47517db96d56Sopenharmony_ci 47527db96d56Sopenharmony_ci /* memo and output_buffer may have already been created in _Pickler_New */ 47537db96d56Sopenharmony_ci if (self->memo == NULL) { 47547db96d56Sopenharmony_ci self->memo = PyMemoTable_New(); 47557db96d56Sopenharmony_ci if (self->memo == NULL) 47567db96d56Sopenharmony_ci return -1; 47577db96d56Sopenharmony_ci } 47587db96d56Sopenharmony_ci self->output_len = 0; 47597db96d56Sopenharmony_ci if (self->output_buffer == NULL) { 47607db96d56Sopenharmony_ci self->max_output_len = WRITE_BUF_SIZE; 47617db96d56Sopenharmony_ci self->output_buffer = PyBytes_FromStringAndSize(NULL, 47627db96d56Sopenharmony_ci self->max_output_len); 47637db96d56Sopenharmony_ci if (self->output_buffer == NULL) 47647db96d56Sopenharmony_ci return -1; 47657db96d56Sopenharmony_ci } 47667db96d56Sopenharmony_ci 47677db96d56Sopenharmony_ci self->fast = 0; 47687db96d56Sopenharmony_ci self->fast_nesting = 0; 47697db96d56Sopenharmony_ci self->fast_memo = NULL; 47707db96d56Sopenharmony_ci 47717db96d56Sopenharmony_ci if (init_method_ref((PyObject *)self, &_Py_ID(persistent_id), 47727db96d56Sopenharmony_ci &self->pers_func, &self->pers_func_self) < 0) 47737db96d56Sopenharmony_ci { 47747db96d56Sopenharmony_ci return -1; 47757db96d56Sopenharmony_ci } 47767db96d56Sopenharmony_ci if (self->dispatch_table != NULL) { 47777db96d56Sopenharmony_ci return 0; 47787db96d56Sopenharmony_ci } 47797db96d56Sopenharmony_ci if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(dispatch_table), 47807db96d56Sopenharmony_ci &self->dispatch_table) < 0) { 47817db96d56Sopenharmony_ci return -1; 47827db96d56Sopenharmony_ci } 47837db96d56Sopenharmony_ci 47847db96d56Sopenharmony_ci return 0; 47857db96d56Sopenharmony_ci} 47867db96d56Sopenharmony_ci 47877db96d56Sopenharmony_ci 47887db96d56Sopenharmony_ci/* Define a proxy object for the Pickler's internal memo object. This is to 47897db96d56Sopenharmony_ci * avoid breaking code like: 47907db96d56Sopenharmony_ci * pickler.memo.clear() 47917db96d56Sopenharmony_ci * and 47927db96d56Sopenharmony_ci * pickler.memo = saved_memo 47937db96d56Sopenharmony_ci * Is this a good idea? Not really, but we don't want to break code that uses 47947db96d56Sopenharmony_ci * it. Note that we don't implement the entire mapping API here. This is 47957db96d56Sopenharmony_ci * intentional, as these should be treated as black-box implementation details. 47967db96d56Sopenharmony_ci */ 47977db96d56Sopenharmony_ci 47987db96d56Sopenharmony_ci/*[clinic input] 47997db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.clear 48007db96d56Sopenharmony_ci 48017db96d56Sopenharmony_ciRemove all items from memo. 48027db96d56Sopenharmony_ci[clinic start generated code]*/ 48037db96d56Sopenharmony_ci 48047db96d56Sopenharmony_cistatic PyObject * 48057db96d56Sopenharmony_ci_pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self) 48067db96d56Sopenharmony_ci/*[clinic end generated code: output=5fb9370d48ae8b05 input=ccc186dacd0f1405]*/ 48077db96d56Sopenharmony_ci{ 48087db96d56Sopenharmony_ci if (self->pickler->memo) 48097db96d56Sopenharmony_ci PyMemoTable_Clear(self->pickler->memo); 48107db96d56Sopenharmony_ci Py_RETURN_NONE; 48117db96d56Sopenharmony_ci} 48127db96d56Sopenharmony_ci 48137db96d56Sopenharmony_ci/*[clinic input] 48147db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.copy 48157db96d56Sopenharmony_ci 48167db96d56Sopenharmony_ciCopy the memo to a new object. 48177db96d56Sopenharmony_ci[clinic start generated code]*/ 48187db96d56Sopenharmony_ci 48197db96d56Sopenharmony_cistatic PyObject * 48207db96d56Sopenharmony_ci_pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self) 48217db96d56Sopenharmony_ci/*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/ 48227db96d56Sopenharmony_ci{ 48237db96d56Sopenharmony_ci PyMemoTable *memo; 48247db96d56Sopenharmony_ci PyObject *new_memo = PyDict_New(); 48257db96d56Sopenharmony_ci if (new_memo == NULL) 48267db96d56Sopenharmony_ci return NULL; 48277db96d56Sopenharmony_ci 48287db96d56Sopenharmony_ci memo = self->pickler->memo; 48297db96d56Sopenharmony_ci for (size_t i = 0; i < memo->mt_allocated; ++i) { 48307db96d56Sopenharmony_ci PyMemoEntry entry = memo->mt_table[i]; 48317db96d56Sopenharmony_ci if (entry.me_key != NULL) { 48327db96d56Sopenharmony_ci int status; 48337db96d56Sopenharmony_ci PyObject *key, *value; 48347db96d56Sopenharmony_ci 48357db96d56Sopenharmony_ci key = PyLong_FromVoidPtr(entry.me_key); 48367db96d56Sopenharmony_ci value = Py_BuildValue("nO", entry.me_value, entry.me_key); 48377db96d56Sopenharmony_ci 48387db96d56Sopenharmony_ci if (key == NULL || value == NULL) { 48397db96d56Sopenharmony_ci Py_XDECREF(key); 48407db96d56Sopenharmony_ci Py_XDECREF(value); 48417db96d56Sopenharmony_ci goto error; 48427db96d56Sopenharmony_ci } 48437db96d56Sopenharmony_ci status = PyDict_SetItem(new_memo, key, value); 48447db96d56Sopenharmony_ci Py_DECREF(key); 48457db96d56Sopenharmony_ci Py_DECREF(value); 48467db96d56Sopenharmony_ci if (status < 0) 48477db96d56Sopenharmony_ci goto error; 48487db96d56Sopenharmony_ci } 48497db96d56Sopenharmony_ci } 48507db96d56Sopenharmony_ci return new_memo; 48517db96d56Sopenharmony_ci 48527db96d56Sopenharmony_ci error: 48537db96d56Sopenharmony_ci Py_XDECREF(new_memo); 48547db96d56Sopenharmony_ci return NULL; 48557db96d56Sopenharmony_ci} 48567db96d56Sopenharmony_ci 48577db96d56Sopenharmony_ci/*[clinic input] 48587db96d56Sopenharmony_ci_pickle.PicklerMemoProxy.__reduce__ 48597db96d56Sopenharmony_ci 48607db96d56Sopenharmony_ciImplement pickle support. 48617db96d56Sopenharmony_ci[clinic start generated code]*/ 48627db96d56Sopenharmony_ci 48637db96d56Sopenharmony_cistatic PyObject * 48647db96d56Sopenharmony_ci_pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self) 48657db96d56Sopenharmony_ci/*[clinic end generated code: output=bebba1168863ab1d input=2f7c540e24b7aae4]*/ 48667db96d56Sopenharmony_ci{ 48677db96d56Sopenharmony_ci PyObject *reduce_value, *dict_args; 48687db96d56Sopenharmony_ci PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self); 48697db96d56Sopenharmony_ci if (contents == NULL) 48707db96d56Sopenharmony_ci return NULL; 48717db96d56Sopenharmony_ci 48727db96d56Sopenharmony_ci reduce_value = PyTuple_New(2); 48737db96d56Sopenharmony_ci if (reduce_value == NULL) { 48747db96d56Sopenharmony_ci Py_DECREF(contents); 48757db96d56Sopenharmony_ci return NULL; 48767db96d56Sopenharmony_ci } 48777db96d56Sopenharmony_ci dict_args = PyTuple_New(1); 48787db96d56Sopenharmony_ci if (dict_args == NULL) { 48797db96d56Sopenharmony_ci Py_DECREF(contents); 48807db96d56Sopenharmony_ci Py_DECREF(reduce_value); 48817db96d56Sopenharmony_ci return NULL; 48827db96d56Sopenharmony_ci } 48837db96d56Sopenharmony_ci PyTuple_SET_ITEM(dict_args, 0, contents); 48847db96d56Sopenharmony_ci Py_INCREF((PyObject *)&PyDict_Type); 48857db96d56Sopenharmony_ci PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type); 48867db96d56Sopenharmony_ci PyTuple_SET_ITEM(reduce_value, 1, dict_args); 48877db96d56Sopenharmony_ci return reduce_value; 48887db96d56Sopenharmony_ci} 48897db96d56Sopenharmony_ci 48907db96d56Sopenharmony_cistatic PyMethodDef picklerproxy_methods[] = { 48917db96d56Sopenharmony_ci _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF 48927db96d56Sopenharmony_ci _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF 48937db96d56Sopenharmony_ci _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF 48947db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 48957db96d56Sopenharmony_ci}; 48967db96d56Sopenharmony_ci 48977db96d56Sopenharmony_cistatic void 48987db96d56Sopenharmony_ciPicklerMemoProxy_dealloc(PicklerMemoProxyObject *self) 48997db96d56Sopenharmony_ci{ 49007db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 49017db96d56Sopenharmony_ci Py_XDECREF(self->pickler); 49027db96d56Sopenharmony_ci PyObject_GC_Del((PyObject *)self); 49037db96d56Sopenharmony_ci} 49047db96d56Sopenharmony_ci 49057db96d56Sopenharmony_cistatic int 49067db96d56Sopenharmony_ciPicklerMemoProxy_traverse(PicklerMemoProxyObject *self, 49077db96d56Sopenharmony_ci visitproc visit, void *arg) 49087db96d56Sopenharmony_ci{ 49097db96d56Sopenharmony_ci Py_VISIT(self->pickler); 49107db96d56Sopenharmony_ci return 0; 49117db96d56Sopenharmony_ci} 49127db96d56Sopenharmony_ci 49137db96d56Sopenharmony_cistatic int 49147db96d56Sopenharmony_ciPicklerMemoProxy_clear(PicklerMemoProxyObject *self) 49157db96d56Sopenharmony_ci{ 49167db96d56Sopenharmony_ci Py_CLEAR(self->pickler); 49177db96d56Sopenharmony_ci return 0; 49187db96d56Sopenharmony_ci} 49197db96d56Sopenharmony_ci 49207db96d56Sopenharmony_cistatic PyTypeObject PicklerMemoProxyType = { 49217db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 49227db96d56Sopenharmony_ci "_pickle.PicklerMemoProxy", /*tp_name*/ 49237db96d56Sopenharmony_ci sizeof(PicklerMemoProxyObject), /*tp_basicsize*/ 49247db96d56Sopenharmony_ci 0, 49257db96d56Sopenharmony_ci (destructor)PicklerMemoProxy_dealloc, /* tp_dealloc */ 49267db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 49277db96d56Sopenharmony_ci 0, /* tp_getattr */ 49287db96d56Sopenharmony_ci 0, /* tp_setattr */ 49297db96d56Sopenharmony_ci 0, /* tp_as_async */ 49307db96d56Sopenharmony_ci 0, /* tp_repr */ 49317db96d56Sopenharmony_ci 0, /* tp_as_number */ 49327db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 49337db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 49347db96d56Sopenharmony_ci PyObject_HashNotImplemented, /* tp_hash */ 49357db96d56Sopenharmony_ci 0, /* tp_call */ 49367db96d56Sopenharmony_ci 0, /* tp_str */ 49377db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 49387db96d56Sopenharmony_ci PyObject_GenericSetAttr, /* tp_setattro */ 49397db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 49407db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 49417db96d56Sopenharmony_ci 0, /* tp_doc */ 49427db96d56Sopenharmony_ci (traverseproc)PicklerMemoProxy_traverse, /* tp_traverse */ 49437db96d56Sopenharmony_ci (inquiry)PicklerMemoProxy_clear, /* tp_clear */ 49447db96d56Sopenharmony_ci 0, /* tp_richcompare */ 49457db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 49467db96d56Sopenharmony_ci 0, /* tp_iter */ 49477db96d56Sopenharmony_ci 0, /* tp_iternext */ 49487db96d56Sopenharmony_ci picklerproxy_methods, /* tp_methods */ 49497db96d56Sopenharmony_ci}; 49507db96d56Sopenharmony_ci 49517db96d56Sopenharmony_cistatic PyObject * 49527db96d56Sopenharmony_ciPicklerMemoProxy_New(PicklerObject *pickler) 49537db96d56Sopenharmony_ci{ 49547db96d56Sopenharmony_ci PicklerMemoProxyObject *self; 49557db96d56Sopenharmony_ci 49567db96d56Sopenharmony_ci self = PyObject_GC_New(PicklerMemoProxyObject, &PicklerMemoProxyType); 49577db96d56Sopenharmony_ci if (self == NULL) 49587db96d56Sopenharmony_ci return NULL; 49597db96d56Sopenharmony_ci Py_INCREF(pickler); 49607db96d56Sopenharmony_ci self->pickler = pickler; 49617db96d56Sopenharmony_ci PyObject_GC_Track(self); 49627db96d56Sopenharmony_ci return (PyObject *)self; 49637db96d56Sopenharmony_ci} 49647db96d56Sopenharmony_ci 49657db96d56Sopenharmony_ci/*****************************************************************************/ 49667db96d56Sopenharmony_ci 49677db96d56Sopenharmony_cistatic PyObject * 49687db96d56Sopenharmony_ciPickler_get_memo(PicklerObject *self, void *Py_UNUSED(ignored)) 49697db96d56Sopenharmony_ci{ 49707db96d56Sopenharmony_ci return PicklerMemoProxy_New(self); 49717db96d56Sopenharmony_ci} 49727db96d56Sopenharmony_ci 49737db96d56Sopenharmony_cistatic int 49747db96d56Sopenharmony_ciPickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored)) 49757db96d56Sopenharmony_ci{ 49767db96d56Sopenharmony_ci PyMemoTable *new_memo = NULL; 49777db96d56Sopenharmony_ci 49787db96d56Sopenharmony_ci if (obj == NULL) { 49797db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 49807db96d56Sopenharmony_ci "attribute deletion is not supported"); 49817db96d56Sopenharmony_ci return -1; 49827db96d56Sopenharmony_ci } 49837db96d56Sopenharmony_ci 49847db96d56Sopenharmony_ci if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) { 49857db96d56Sopenharmony_ci PicklerObject *pickler = 49867db96d56Sopenharmony_ci ((PicklerMemoProxyObject *)obj)->pickler; 49877db96d56Sopenharmony_ci 49887db96d56Sopenharmony_ci new_memo = PyMemoTable_Copy(pickler->memo); 49897db96d56Sopenharmony_ci if (new_memo == NULL) 49907db96d56Sopenharmony_ci return -1; 49917db96d56Sopenharmony_ci } 49927db96d56Sopenharmony_ci else if (PyDict_Check(obj)) { 49937db96d56Sopenharmony_ci Py_ssize_t i = 0; 49947db96d56Sopenharmony_ci PyObject *key, *value; 49957db96d56Sopenharmony_ci 49967db96d56Sopenharmony_ci new_memo = PyMemoTable_New(); 49977db96d56Sopenharmony_ci if (new_memo == NULL) 49987db96d56Sopenharmony_ci return -1; 49997db96d56Sopenharmony_ci 50007db96d56Sopenharmony_ci while (PyDict_Next(obj, &i, &key, &value)) { 50017db96d56Sopenharmony_ci Py_ssize_t memo_id; 50027db96d56Sopenharmony_ci PyObject *memo_obj; 50037db96d56Sopenharmony_ci 50047db96d56Sopenharmony_ci if (!PyTuple_Check(value) || PyTuple_GET_SIZE(value) != 2) { 50057db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 50067db96d56Sopenharmony_ci "'memo' values must be 2-item tuples"); 50077db96d56Sopenharmony_ci goto error; 50087db96d56Sopenharmony_ci } 50097db96d56Sopenharmony_ci memo_id = PyLong_AsSsize_t(PyTuple_GET_ITEM(value, 0)); 50107db96d56Sopenharmony_ci if (memo_id == -1 && PyErr_Occurred()) 50117db96d56Sopenharmony_ci goto error; 50127db96d56Sopenharmony_ci memo_obj = PyTuple_GET_ITEM(value, 1); 50137db96d56Sopenharmony_ci if (PyMemoTable_Set(new_memo, memo_obj, memo_id) < 0) 50147db96d56Sopenharmony_ci goto error; 50157db96d56Sopenharmony_ci } 50167db96d56Sopenharmony_ci } 50177db96d56Sopenharmony_ci else { 50187db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 50197db96d56Sopenharmony_ci "'memo' attribute must be a PicklerMemoProxy object " 50207db96d56Sopenharmony_ci "or dict, not %.200s", Py_TYPE(obj)->tp_name); 50217db96d56Sopenharmony_ci return -1; 50227db96d56Sopenharmony_ci } 50237db96d56Sopenharmony_ci 50247db96d56Sopenharmony_ci PyMemoTable_Del(self->memo); 50257db96d56Sopenharmony_ci self->memo = new_memo; 50267db96d56Sopenharmony_ci 50277db96d56Sopenharmony_ci return 0; 50287db96d56Sopenharmony_ci 50297db96d56Sopenharmony_ci error: 50307db96d56Sopenharmony_ci if (new_memo) 50317db96d56Sopenharmony_ci PyMemoTable_Del(new_memo); 50327db96d56Sopenharmony_ci return -1; 50337db96d56Sopenharmony_ci} 50347db96d56Sopenharmony_ci 50357db96d56Sopenharmony_cistatic PyObject * 50367db96d56Sopenharmony_ciPickler_get_persid(PicklerObject *self, void *Py_UNUSED(ignored)) 50377db96d56Sopenharmony_ci{ 50387db96d56Sopenharmony_ci if (self->pers_func == NULL) { 50397db96d56Sopenharmony_ci PyErr_SetString(PyExc_AttributeError, "persistent_id"); 50407db96d56Sopenharmony_ci return NULL; 50417db96d56Sopenharmony_ci } 50427db96d56Sopenharmony_ci return reconstruct_method(self->pers_func, self->pers_func_self); 50437db96d56Sopenharmony_ci} 50447db96d56Sopenharmony_ci 50457db96d56Sopenharmony_cistatic int 50467db96d56Sopenharmony_ciPickler_set_persid(PicklerObject *self, PyObject *value, void *Py_UNUSED(ignored)) 50477db96d56Sopenharmony_ci{ 50487db96d56Sopenharmony_ci if (value == NULL) { 50497db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 50507db96d56Sopenharmony_ci "attribute deletion is not supported"); 50517db96d56Sopenharmony_ci return -1; 50527db96d56Sopenharmony_ci } 50537db96d56Sopenharmony_ci if (!PyCallable_Check(value)) { 50547db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 50557db96d56Sopenharmony_ci "persistent_id must be a callable taking one argument"); 50567db96d56Sopenharmony_ci return -1; 50577db96d56Sopenharmony_ci } 50587db96d56Sopenharmony_ci 50597db96d56Sopenharmony_ci self->pers_func_self = NULL; 50607db96d56Sopenharmony_ci Py_INCREF(value); 50617db96d56Sopenharmony_ci Py_XSETREF(self->pers_func, value); 50627db96d56Sopenharmony_ci 50637db96d56Sopenharmony_ci return 0; 50647db96d56Sopenharmony_ci} 50657db96d56Sopenharmony_ci 50667db96d56Sopenharmony_cistatic PyMemberDef Pickler_members[] = { 50677db96d56Sopenharmony_ci {"bin", T_INT, offsetof(PicklerObject, bin)}, 50687db96d56Sopenharmony_ci {"fast", T_INT, offsetof(PicklerObject, fast)}, 50697db96d56Sopenharmony_ci {"dispatch_table", T_OBJECT_EX, offsetof(PicklerObject, dispatch_table)}, 50707db96d56Sopenharmony_ci {NULL} 50717db96d56Sopenharmony_ci}; 50727db96d56Sopenharmony_ci 50737db96d56Sopenharmony_cistatic PyGetSetDef Pickler_getsets[] = { 50747db96d56Sopenharmony_ci {"memo", (getter)Pickler_get_memo, 50757db96d56Sopenharmony_ci (setter)Pickler_set_memo}, 50767db96d56Sopenharmony_ci {"persistent_id", (getter)Pickler_get_persid, 50777db96d56Sopenharmony_ci (setter)Pickler_set_persid}, 50787db96d56Sopenharmony_ci {NULL} 50797db96d56Sopenharmony_ci}; 50807db96d56Sopenharmony_ci 50817db96d56Sopenharmony_cistatic PyTypeObject Pickler_Type = { 50827db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 50837db96d56Sopenharmony_ci "_pickle.Pickler" , /*tp_name*/ 50847db96d56Sopenharmony_ci sizeof(PicklerObject), /*tp_basicsize*/ 50857db96d56Sopenharmony_ci 0, /*tp_itemsize*/ 50867db96d56Sopenharmony_ci (destructor)Pickler_dealloc, /*tp_dealloc*/ 50877db96d56Sopenharmony_ci 0, /*tp_vectorcall_offset*/ 50887db96d56Sopenharmony_ci 0, /*tp_getattr*/ 50897db96d56Sopenharmony_ci 0, /*tp_setattr*/ 50907db96d56Sopenharmony_ci 0, /*tp_as_async*/ 50917db96d56Sopenharmony_ci 0, /*tp_repr*/ 50927db96d56Sopenharmony_ci 0, /*tp_as_number*/ 50937db96d56Sopenharmony_ci 0, /*tp_as_sequence*/ 50947db96d56Sopenharmony_ci 0, /*tp_as_mapping*/ 50957db96d56Sopenharmony_ci 0, /*tp_hash*/ 50967db96d56Sopenharmony_ci 0, /*tp_call*/ 50977db96d56Sopenharmony_ci 0, /*tp_str*/ 50987db96d56Sopenharmony_ci 0, /*tp_getattro*/ 50997db96d56Sopenharmony_ci 0, /*tp_setattro*/ 51007db96d56Sopenharmony_ci 0, /*tp_as_buffer*/ 51017db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 51027db96d56Sopenharmony_ci _pickle_Pickler___init____doc__, /*tp_doc*/ 51037db96d56Sopenharmony_ci (traverseproc)Pickler_traverse, /*tp_traverse*/ 51047db96d56Sopenharmony_ci (inquiry)Pickler_clear, /*tp_clear*/ 51057db96d56Sopenharmony_ci 0, /*tp_richcompare*/ 51067db96d56Sopenharmony_ci 0, /*tp_weaklistoffset*/ 51077db96d56Sopenharmony_ci 0, /*tp_iter*/ 51087db96d56Sopenharmony_ci 0, /*tp_iternext*/ 51097db96d56Sopenharmony_ci Pickler_methods, /*tp_methods*/ 51107db96d56Sopenharmony_ci Pickler_members, /*tp_members*/ 51117db96d56Sopenharmony_ci Pickler_getsets, /*tp_getset*/ 51127db96d56Sopenharmony_ci 0, /*tp_base*/ 51137db96d56Sopenharmony_ci 0, /*tp_dict*/ 51147db96d56Sopenharmony_ci 0, /*tp_descr_get*/ 51157db96d56Sopenharmony_ci 0, /*tp_descr_set*/ 51167db96d56Sopenharmony_ci 0, /*tp_dictoffset*/ 51177db96d56Sopenharmony_ci _pickle_Pickler___init__, /*tp_init*/ 51187db96d56Sopenharmony_ci PyType_GenericAlloc, /*tp_alloc*/ 51197db96d56Sopenharmony_ci PyType_GenericNew, /*tp_new*/ 51207db96d56Sopenharmony_ci PyObject_GC_Del, /*tp_free*/ 51217db96d56Sopenharmony_ci 0, /*tp_is_gc*/ 51227db96d56Sopenharmony_ci}; 51237db96d56Sopenharmony_ci 51247db96d56Sopenharmony_ci/* Temporary helper for calling self.find_class(). 51257db96d56Sopenharmony_ci 51267db96d56Sopenharmony_ci XXX: It would be nice to able to avoid Python function call overhead, by 51277db96d56Sopenharmony_ci using directly the C version of find_class(), when find_class() is not 51287db96d56Sopenharmony_ci overridden by a subclass. Although, this could become rather hackish. A 51297db96d56Sopenharmony_ci simpler optimization would be to call the C function when self is not a 51307db96d56Sopenharmony_ci subclass instance. */ 51317db96d56Sopenharmony_cistatic PyObject * 51327db96d56Sopenharmony_cifind_class(UnpicklerObject *self, PyObject *module_name, PyObject *global_name) 51337db96d56Sopenharmony_ci{ 51347db96d56Sopenharmony_ci return PyObject_CallMethodObjArgs((PyObject *)self, &_Py_ID(find_class), 51357db96d56Sopenharmony_ci module_name, global_name, NULL); 51367db96d56Sopenharmony_ci} 51377db96d56Sopenharmony_ci 51387db96d56Sopenharmony_cistatic Py_ssize_t 51397db96d56Sopenharmony_cimarker(UnpicklerObject *self) 51407db96d56Sopenharmony_ci{ 51417db96d56Sopenharmony_ci Py_ssize_t mark; 51427db96d56Sopenharmony_ci 51437db96d56Sopenharmony_ci if (self->num_marks < 1) { 51447db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 51457db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "could not find MARK"); 51467db96d56Sopenharmony_ci return -1; 51477db96d56Sopenharmony_ci } 51487db96d56Sopenharmony_ci 51497db96d56Sopenharmony_ci mark = self->marks[--self->num_marks]; 51507db96d56Sopenharmony_ci self->stack->mark_set = self->num_marks != 0; 51517db96d56Sopenharmony_ci self->stack->fence = self->num_marks ? 51527db96d56Sopenharmony_ci self->marks[self->num_marks - 1] : 0; 51537db96d56Sopenharmony_ci return mark; 51547db96d56Sopenharmony_ci} 51557db96d56Sopenharmony_ci 51567db96d56Sopenharmony_cistatic int 51577db96d56Sopenharmony_ciload_none(UnpicklerObject *self) 51587db96d56Sopenharmony_ci{ 51597db96d56Sopenharmony_ci PDATA_APPEND(self->stack, Py_None, -1); 51607db96d56Sopenharmony_ci return 0; 51617db96d56Sopenharmony_ci} 51627db96d56Sopenharmony_ci 51637db96d56Sopenharmony_cistatic int 51647db96d56Sopenharmony_ciload_int(UnpicklerObject *self) 51657db96d56Sopenharmony_ci{ 51667db96d56Sopenharmony_ci PyObject *value; 51677db96d56Sopenharmony_ci char *endptr, *s; 51687db96d56Sopenharmony_ci Py_ssize_t len; 51697db96d56Sopenharmony_ci long x; 51707db96d56Sopenharmony_ci 51717db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 51727db96d56Sopenharmony_ci return -1; 51737db96d56Sopenharmony_ci if (len < 2) 51747db96d56Sopenharmony_ci return bad_readline(); 51757db96d56Sopenharmony_ci 51767db96d56Sopenharmony_ci errno = 0; 51777db96d56Sopenharmony_ci /* XXX: Should the base argument of strtol() be explicitly set to 10? 51787db96d56Sopenharmony_ci XXX(avassalotti): Should this uses PyOS_strtol()? */ 51797db96d56Sopenharmony_ci x = strtol(s, &endptr, 0); 51807db96d56Sopenharmony_ci 51817db96d56Sopenharmony_ci if (errno || (*endptr != '\n' && *endptr != '\0')) { 51827db96d56Sopenharmony_ci /* Hm, maybe we've got something long. Let's try reading 51837db96d56Sopenharmony_ci * it as a Python int object. */ 51847db96d56Sopenharmony_ci errno = 0; 51857db96d56Sopenharmony_ci /* XXX: Same thing about the base here. */ 51867db96d56Sopenharmony_ci value = PyLong_FromString(s, NULL, 0); 51877db96d56Sopenharmony_ci if (value == NULL) { 51887db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 51897db96d56Sopenharmony_ci "could not convert string to int"); 51907db96d56Sopenharmony_ci return -1; 51917db96d56Sopenharmony_ci } 51927db96d56Sopenharmony_ci } 51937db96d56Sopenharmony_ci else { 51947db96d56Sopenharmony_ci if (len == 3 && (x == 0 || x == 1)) { 51957db96d56Sopenharmony_ci if ((value = PyBool_FromLong(x)) == NULL) 51967db96d56Sopenharmony_ci return -1; 51977db96d56Sopenharmony_ci } 51987db96d56Sopenharmony_ci else { 51997db96d56Sopenharmony_ci if ((value = PyLong_FromLong(x)) == NULL) 52007db96d56Sopenharmony_ci return -1; 52017db96d56Sopenharmony_ci } 52027db96d56Sopenharmony_ci } 52037db96d56Sopenharmony_ci 52047db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 52057db96d56Sopenharmony_ci return 0; 52067db96d56Sopenharmony_ci} 52077db96d56Sopenharmony_ci 52087db96d56Sopenharmony_cistatic int 52097db96d56Sopenharmony_ciload_bool(UnpicklerObject *self, PyObject *boolean) 52107db96d56Sopenharmony_ci{ 52117db96d56Sopenharmony_ci assert(boolean == Py_True || boolean == Py_False); 52127db96d56Sopenharmony_ci PDATA_APPEND(self->stack, boolean, -1); 52137db96d56Sopenharmony_ci return 0; 52147db96d56Sopenharmony_ci} 52157db96d56Sopenharmony_ci 52167db96d56Sopenharmony_ci/* s contains x bytes of an unsigned little-endian integer. Return its value 52177db96d56Sopenharmony_ci * as a C Py_ssize_t, or -1 if it's higher than PY_SSIZE_T_MAX. 52187db96d56Sopenharmony_ci */ 52197db96d56Sopenharmony_cistatic Py_ssize_t 52207db96d56Sopenharmony_cicalc_binsize(char *bytes, int nbytes) 52217db96d56Sopenharmony_ci{ 52227db96d56Sopenharmony_ci unsigned char *s = (unsigned char *)bytes; 52237db96d56Sopenharmony_ci int i; 52247db96d56Sopenharmony_ci size_t x = 0; 52257db96d56Sopenharmony_ci 52267db96d56Sopenharmony_ci if (nbytes > (int)sizeof(size_t)) { 52277db96d56Sopenharmony_ci /* Check for integer overflow. BINBYTES8 and BINUNICODE8 opcodes 52287db96d56Sopenharmony_ci * have 64-bit size that can't be represented on 32-bit platform. 52297db96d56Sopenharmony_ci */ 52307db96d56Sopenharmony_ci for (i = (int)sizeof(size_t); i < nbytes; i++) { 52317db96d56Sopenharmony_ci if (s[i]) 52327db96d56Sopenharmony_ci return -1; 52337db96d56Sopenharmony_ci } 52347db96d56Sopenharmony_ci nbytes = (int)sizeof(size_t); 52357db96d56Sopenharmony_ci } 52367db96d56Sopenharmony_ci for (i = 0; i < nbytes; i++) { 52377db96d56Sopenharmony_ci x |= (size_t) s[i] << (8 * i); 52387db96d56Sopenharmony_ci } 52397db96d56Sopenharmony_ci 52407db96d56Sopenharmony_ci if (x > PY_SSIZE_T_MAX) 52417db96d56Sopenharmony_ci return -1; 52427db96d56Sopenharmony_ci else 52437db96d56Sopenharmony_ci return (Py_ssize_t) x; 52447db96d56Sopenharmony_ci} 52457db96d56Sopenharmony_ci 52467db96d56Sopenharmony_ci/* s contains x bytes of a little-endian integer. Return its value as a 52477db96d56Sopenharmony_ci * C int. Obscure: when x is 1 or 2, this is an unsigned little-endian 52487db96d56Sopenharmony_ci * int, but when x is 4 it's a signed one. This is a historical source 52497db96d56Sopenharmony_ci * of x-platform bugs. 52507db96d56Sopenharmony_ci */ 52517db96d56Sopenharmony_cistatic long 52527db96d56Sopenharmony_cicalc_binint(char *bytes, int nbytes) 52537db96d56Sopenharmony_ci{ 52547db96d56Sopenharmony_ci unsigned char *s = (unsigned char *)bytes; 52557db96d56Sopenharmony_ci Py_ssize_t i; 52567db96d56Sopenharmony_ci long x = 0; 52577db96d56Sopenharmony_ci 52587db96d56Sopenharmony_ci for (i = 0; i < nbytes; i++) { 52597db96d56Sopenharmony_ci x |= (long)s[i] << (8 * i); 52607db96d56Sopenharmony_ci } 52617db96d56Sopenharmony_ci 52627db96d56Sopenharmony_ci /* Unlike BININT1 and BININT2, BININT (more accurately BININT4) 52637db96d56Sopenharmony_ci * is signed, so on a box with longs bigger than 4 bytes we need 52647db96d56Sopenharmony_ci * to extend a BININT's sign bit to the full width. 52657db96d56Sopenharmony_ci */ 52667db96d56Sopenharmony_ci if (SIZEOF_LONG > 4 && nbytes == 4) { 52677db96d56Sopenharmony_ci x |= -(x & (1L << 31)); 52687db96d56Sopenharmony_ci } 52697db96d56Sopenharmony_ci 52707db96d56Sopenharmony_ci return x; 52717db96d56Sopenharmony_ci} 52727db96d56Sopenharmony_ci 52737db96d56Sopenharmony_cistatic int 52747db96d56Sopenharmony_ciload_binintx(UnpicklerObject *self, char *s, int size) 52757db96d56Sopenharmony_ci{ 52767db96d56Sopenharmony_ci PyObject *value; 52777db96d56Sopenharmony_ci long x; 52787db96d56Sopenharmony_ci 52797db96d56Sopenharmony_ci x = calc_binint(s, size); 52807db96d56Sopenharmony_ci 52817db96d56Sopenharmony_ci if ((value = PyLong_FromLong(x)) == NULL) 52827db96d56Sopenharmony_ci return -1; 52837db96d56Sopenharmony_ci 52847db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 52857db96d56Sopenharmony_ci return 0; 52867db96d56Sopenharmony_ci} 52877db96d56Sopenharmony_ci 52887db96d56Sopenharmony_cistatic int 52897db96d56Sopenharmony_ciload_binint(UnpicklerObject *self) 52907db96d56Sopenharmony_ci{ 52917db96d56Sopenharmony_ci char *s; 52927db96d56Sopenharmony_ci 52937db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 4) < 0) 52947db96d56Sopenharmony_ci return -1; 52957db96d56Sopenharmony_ci 52967db96d56Sopenharmony_ci return load_binintx(self, s, 4); 52977db96d56Sopenharmony_ci} 52987db96d56Sopenharmony_ci 52997db96d56Sopenharmony_cistatic int 53007db96d56Sopenharmony_ciload_binint1(UnpicklerObject *self) 53017db96d56Sopenharmony_ci{ 53027db96d56Sopenharmony_ci char *s; 53037db96d56Sopenharmony_ci 53047db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 1) < 0) 53057db96d56Sopenharmony_ci return -1; 53067db96d56Sopenharmony_ci 53077db96d56Sopenharmony_ci return load_binintx(self, s, 1); 53087db96d56Sopenharmony_ci} 53097db96d56Sopenharmony_ci 53107db96d56Sopenharmony_cistatic int 53117db96d56Sopenharmony_ciload_binint2(UnpicklerObject *self) 53127db96d56Sopenharmony_ci{ 53137db96d56Sopenharmony_ci char *s; 53147db96d56Sopenharmony_ci 53157db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 2) < 0) 53167db96d56Sopenharmony_ci return -1; 53177db96d56Sopenharmony_ci 53187db96d56Sopenharmony_ci return load_binintx(self, s, 2); 53197db96d56Sopenharmony_ci} 53207db96d56Sopenharmony_ci 53217db96d56Sopenharmony_cistatic int 53227db96d56Sopenharmony_ciload_long(UnpicklerObject *self) 53237db96d56Sopenharmony_ci{ 53247db96d56Sopenharmony_ci PyObject *value; 53257db96d56Sopenharmony_ci char *s = NULL; 53267db96d56Sopenharmony_ci Py_ssize_t len; 53277db96d56Sopenharmony_ci 53287db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 53297db96d56Sopenharmony_ci return -1; 53307db96d56Sopenharmony_ci if (len < 2) 53317db96d56Sopenharmony_ci return bad_readline(); 53327db96d56Sopenharmony_ci 53337db96d56Sopenharmony_ci /* s[len-2] will usually be 'L' (and s[len-1] is '\n'); we need to remove 53347db96d56Sopenharmony_ci the 'L' before calling PyLong_FromString. In order to maintain 53357db96d56Sopenharmony_ci compatibility with Python 3.0.0, we don't actually *require* 53367db96d56Sopenharmony_ci the 'L' to be present. */ 53377db96d56Sopenharmony_ci if (s[len-2] == 'L') 53387db96d56Sopenharmony_ci s[len-2] = '\0'; 53397db96d56Sopenharmony_ci /* XXX: Should the base argument explicitly set to 10? */ 53407db96d56Sopenharmony_ci value = PyLong_FromString(s, NULL, 0); 53417db96d56Sopenharmony_ci if (value == NULL) 53427db96d56Sopenharmony_ci return -1; 53437db96d56Sopenharmony_ci 53447db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 53457db96d56Sopenharmony_ci return 0; 53467db96d56Sopenharmony_ci} 53477db96d56Sopenharmony_ci 53487db96d56Sopenharmony_ci/* 'size' bytes contain the # of bytes of little-endian 256's-complement 53497db96d56Sopenharmony_ci * data following. 53507db96d56Sopenharmony_ci */ 53517db96d56Sopenharmony_cistatic int 53527db96d56Sopenharmony_ciload_counted_long(UnpicklerObject *self, int size) 53537db96d56Sopenharmony_ci{ 53547db96d56Sopenharmony_ci PyObject *value; 53557db96d56Sopenharmony_ci char *nbytes; 53567db96d56Sopenharmony_ci char *pdata; 53577db96d56Sopenharmony_ci 53587db96d56Sopenharmony_ci assert(size == 1 || size == 4); 53597db96d56Sopenharmony_ci if (_Unpickler_Read(self, &nbytes, size) < 0) 53607db96d56Sopenharmony_ci return -1; 53617db96d56Sopenharmony_ci 53627db96d56Sopenharmony_ci size = calc_binint(nbytes, size); 53637db96d56Sopenharmony_ci if (size < 0) { 53647db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 53657db96d56Sopenharmony_ci /* Corrupt or hostile pickle -- we never write one like this */ 53667db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 53677db96d56Sopenharmony_ci "LONG pickle has negative byte count"); 53687db96d56Sopenharmony_ci return -1; 53697db96d56Sopenharmony_ci } 53707db96d56Sopenharmony_ci 53717db96d56Sopenharmony_ci if (size == 0) 53727db96d56Sopenharmony_ci value = PyLong_FromLong(0L); 53737db96d56Sopenharmony_ci else { 53747db96d56Sopenharmony_ci /* Read the raw little-endian bytes and convert. */ 53757db96d56Sopenharmony_ci if (_Unpickler_Read(self, &pdata, size) < 0) 53767db96d56Sopenharmony_ci return -1; 53777db96d56Sopenharmony_ci value = _PyLong_FromByteArray((unsigned char *)pdata, (size_t)size, 53787db96d56Sopenharmony_ci 1 /* little endian */ , 1 /* signed */ ); 53797db96d56Sopenharmony_ci } 53807db96d56Sopenharmony_ci if (value == NULL) 53817db96d56Sopenharmony_ci return -1; 53827db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 53837db96d56Sopenharmony_ci return 0; 53847db96d56Sopenharmony_ci} 53857db96d56Sopenharmony_ci 53867db96d56Sopenharmony_cistatic int 53877db96d56Sopenharmony_ciload_float(UnpicklerObject *self) 53887db96d56Sopenharmony_ci{ 53897db96d56Sopenharmony_ci PyObject *value; 53907db96d56Sopenharmony_ci char *endptr, *s; 53917db96d56Sopenharmony_ci Py_ssize_t len; 53927db96d56Sopenharmony_ci double d; 53937db96d56Sopenharmony_ci 53947db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 53957db96d56Sopenharmony_ci return -1; 53967db96d56Sopenharmony_ci if (len < 2) 53977db96d56Sopenharmony_ci return bad_readline(); 53987db96d56Sopenharmony_ci 53997db96d56Sopenharmony_ci errno = 0; 54007db96d56Sopenharmony_ci d = PyOS_string_to_double(s, &endptr, PyExc_OverflowError); 54017db96d56Sopenharmony_ci if (d == -1.0 && PyErr_Occurred()) 54027db96d56Sopenharmony_ci return -1; 54037db96d56Sopenharmony_ci if ((endptr[0] != '\n') && (endptr[0] != '\0')) { 54047db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "could not convert string to float"); 54057db96d56Sopenharmony_ci return -1; 54067db96d56Sopenharmony_ci } 54077db96d56Sopenharmony_ci value = PyFloat_FromDouble(d); 54087db96d56Sopenharmony_ci if (value == NULL) 54097db96d56Sopenharmony_ci return -1; 54107db96d56Sopenharmony_ci 54117db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 54127db96d56Sopenharmony_ci return 0; 54137db96d56Sopenharmony_ci} 54147db96d56Sopenharmony_ci 54157db96d56Sopenharmony_cistatic int 54167db96d56Sopenharmony_ciload_binfloat(UnpicklerObject *self) 54177db96d56Sopenharmony_ci{ 54187db96d56Sopenharmony_ci PyObject *value; 54197db96d56Sopenharmony_ci double x; 54207db96d56Sopenharmony_ci char *s; 54217db96d56Sopenharmony_ci 54227db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 8) < 0) 54237db96d56Sopenharmony_ci return -1; 54247db96d56Sopenharmony_ci 54257db96d56Sopenharmony_ci x = PyFloat_Unpack8(s, 0); 54267db96d56Sopenharmony_ci if (x == -1.0 && PyErr_Occurred()) 54277db96d56Sopenharmony_ci return -1; 54287db96d56Sopenharmony_ci 54297db96d56Sopenharmony_ci if ((value = PyFloat_FromDouble(x)) == NULL) 54307db96d56Sopenharmony_ci return -1; 54317db96d56Sopenharmony_ci 54327db96d56Sopenharmony_ci PDATA_PUSH(self->stack, value, -1); 54337db96d56Sopenharmony_ci return 0; 54347db96d56Sopenharmony_ci} 54357db96d56Sopenharmony_ci 54367db96d56Sopenharmony_cistatic int 54377db96d56Sopenharmony_ciload_string(UnpicklerObject *self) 54387db96d56Sopenharmony_ci{ 54397db96d56Sopenharmony_ci PyObject *bytes; 54407db96d56Sopenharmony_ci PyObject *obj; 54417db96d56Sopenharmony_ci Py_ssize_t len; 54427db96d56Sopenharmony_ci char *s, *p; 54437db96d56Sopenharmony_ci 54447db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 54457db96d56Sopenharmony_ci return -1; 54467db96d56Sopenharmony_ci /* Strip the newline */ 54477db96d56Sopenharmony_ci len--; 54487db96d56Sopenharmony_ci /* Strip outermost quotes */ 54497db96d56Sopenharmony_ci if (len >= 2 && s[0] == s[len - 1] && (s[0] == '\'' || s[0] == '"')) { 54507db96d56Sopenharmony_ci p = s + 1; 54517db96d56Sopenharmony_ci len -= 2; 54527db96d56Sopenharmony_ci } 54537db96d56Sopenharmony_ci else { 54547db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 54557db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 54567db96d56Sopenharmony_ci "the STRING opcode argument must be quoted"); 54577db96d56Sopenharmony_ci return -1; 54587db96d56Sopenharmony_ci } 54597db96d56Sopenharmony_ci assert(len >= 0); 54607db96d56Sopenharmony_ci 54617db96d56Sopenharmony_ci /* Use the PyBytes API to decode the string, since that is what is used 54627db96d56Sopenharmony_ci to encode, and then coerce the result to Unicode. */ 54637db96d56Sopenharmony_ci bytes = PyBytes_DecodeEscape(p, len, NULL, 0, NULL); 54647db96d56Sopenharmony_ci if (bytes == NULL) 54657db96d56Sopenharmony_ci return -1; 54667db96d56Sopenharmony_ci 54677db96d56Sopenharmony_ci /* Leave the Python 2.x strings as bytes if the *encoding* given to the 54687db96d56Sopenharmony_ci Unpickler was 'bytes'. Otherwise, convert them to unicode. */ 54697db96d56Sopenharmony_ci if (strcmp(self->encoding, "bytes") == 0) { 54707db96d56Sopenharmony_ci obj = bytes; 54717db96d56Sopenharmony_ci } 54727db96d56Sopenharmony_ci else { 54737db96d56Sopenharmony_ci obj = PyUnicode_FromEncodedObject(bytes, self->encoding, self->errors); 54747db96d56Sopenharmony_ci Py_DECREF(bytes); 54757db96d56Sopenharmony_ci if (obj == NULL) { 54767db96d56Sopenharmony_ci return -1; 54777db96d56Sopenharmony_ci } 54787db96d56Sopenharmony_ci } 54797db96d56Sopenharmony_ci 54807db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 54817db96d56Sopenharmony_ci return 0; 54827db96d56Sopenharmony_ci} 54837db96d56Sopenharmony_ci 54847db96d56Sopenharmony_cistatic int 54857db96d56Sopenharmony_ciload_counted_binstring(UnpicklerObject *self, int nbytes) 54867db96d56Sopenharmony_ci{ 54877db96d56Sopenharmony_ci PyObject *obj; 54887db96d56Sopenharmony_ci Py_ssize_t size; 54897db96d56Sopenharmony_ci char *s; 54907db96d56Sopenharmony_ci 54917db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, nbytes) < 0) 54927db96d56Sopenharmony_ci return -1; 54937db96d56Sopenharmony_ci 54947db96d56Sopenharmony_ci size = calc_binsize(s, nbytes); 54957db96d56Sopenharmony_ci if (size < 0) { 54967db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 54977db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, 54987db96d56Sopenharmony_ci "BINSTRING exceeds system's maximum size of %zd bytes", 54997db96d56Sopenharmony_ci PY_SSIZE_T_MAX); 55007db96d56Sopenharmony_ci return -1; 55017db96d56Sopenharmony_ci } 55027db96d56Sopenharmony_ci 55037db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, size) < 0) 55047db96d56Sopenharmony_ci return -1; 55057db96d56Sopenharmony_ci 55067db96d56Sopenharmony_ci /* Convert Python 2.x strings to bytes if the *encoding* given to the 55077db96d56Sopenharmony_ci Unpickler was 'bytes'. Otherwise, convert them to unicode. */ 55087db96d56Sopenharmony_ci if (strcmp(self->encoding, "bytes") == 0) { 55097db96d56Sopenharmony_ci obj = PyBytes_FromStringAndSize(s, size); 55107db96d56Sopenharmony_ci } 55117db96d56Sopenharmony_ci else { 55127db96d56Sopenharmony_ci obj = PyUnicode_Decode(s, size, self->encoding, self->errors); 55137db96d56Sopenharmony_ci } 55147db96d56Sopenharmony_ci if (obj == NULL) { 55157db96d56Sopenharmony_ci return -1; 55167db96d56Sopenharmony_ci } 55177db96d56Sopenharmony_ci 55187db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 55197db96d56Sopenharmony_ci return 0; 55207db96d56Sopenharmony_ci} 55217db96d56Sopenharmony_ci 55227db96d56Sopenharmony_cistatic int 55237db96d56Sopenharmony_ciload_counted_binbytes(UnpicklerObject *self, int nbytes) 55247db96d56Sopenharmony_ci{ 55257db96d56Sopenharmony_ci PyObject *bytes; 55267db96d56Sopenharmony_ci Py_ssize_t size; 55277db96d56Sopenharmony_ci char *s; 55287db96d56Sopenharmony_ci 55297db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, nbytes) < 0) 55307db96d56Sopenharmony_ci return -1; 55317db96d56Sopenharmony_ci 55327db96d56Sopenharmony_ci size = calc_binsize(s, nbytes); 55337db96d56Sopenharmony_ci if (size < 0) { 55347db96d56Sopenharmony_ci PyErr_Format(PyExc_OverflowError, 55357db96d56Sopenharmony_ci "BINBYTES exceeds system's maximum size of %zd bytes", 55367db96d56Sopenharmony_ci PY_SSIZE_T_MAX); 55377db96d56Sopenharmony_ci return -1; 55387db96d56Sopenharmony_ci } 55397db96d56Sopenharmony_ci 55407db96d56Sopenharmony_ci bytes = PyBytes_FromStringAndSize(NULL, size); 55417db96d56Sopenharmony_ci if (bytes == NULL) 55427db96d56Sopenharmony_ci return -1; 55437db96d56Sopenharmony_ci if (_Unpickler_ReadInto(self, PyBytes_AS_STRING(bytes), size) < 0) { 55447db96d56Sopenharmony_ci Py_DECREF(bytes); 55457db96d56Sopenharmony_ci return -1; 55467db96d56Sopenharmony_ci } 55477db96d56Sopenharmony_ci 55487db96d56Sopenharmony_ci PDATA_PUSH(self->stack, bytes, -1); 55497db96d56Sopenharmony_ci return 0; 55507db96d56Sopenharmony_ci} 55517db96d56Sopenharmony_ci 55527db96d56Sopenharmony_cistatic int 55537db96d56Sopenharmony_ciload_counted_bytearray(UnpicklerObject *self) 55547db96d56Sopenharmony_ci{ 55557db96d56Sopenharmony_ci PyObject *bytearray; 55567db96d56Sopenharmony_ci Py_ssize_t size; 55577db96d56Sopenharmony_ci char *s; 55587db96d56Sopenharmony_ci 55597db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 8) < 0) { 55607db96d56Sopenharmony_ci return -1; 55617db96d56Sopenharmony_ci } 55627db96d56Sopenharmony_ci 55637db96d56Sopenharmony_ci size = calc_binsize(s, 8); 55647db96d56Sopenharmony_ci if (size < 0) { 55657db96d56Sopenharmony_ci PyErr_Format(PyExc_OverflowError, 55667db96d56Sopenharmony_ci "BYTEARRAY8 exceeds system's maximum size of %zd bytes", 55677db96d56Sopenharmony_ci PY_SSIZE_T_MAX); 55687db96d56Sopenharmony_ci return -1; 55697db96d56Sopenharmony_ci } 55707db96d56Sopenharmony_ci 55717db96d56Sopenharmony_ci bytearray = PyByteArray_FromStringAndSize(NULL, size); 55727db96d56Sopenharmony_ci if (bytearray == NULL) { 55737db96d56Sopenharmony_ci return -1; 55747db96d56Sopenharmony_ci } 55757db96d56Sopenharmony_ci if (_Unpickler_ReadInto(self, PyByteArray_AS_STRING(bytearray), size) < 0) { 55767db96d56Sopenharmony_ci Py_DECREF(bytearray); 55777db96d56Sopenharmony_ci return -1; 55787db96d56Sopenharmony_ci } 55797db96d56Sopenharmony_ci 55807db96d56Sopenharmony_ci PDATA_PUSH(self->stack, bytearray, -1); 55817db96d56Sopenharmony_ci return 0; 55827db96d56Sopenharmony_ci} 55837db96d56Sopenharmony_ci 55847db96d56Sopenharmony_cistatic int 55857db96d56Sopenharmony_ciload_next_buffer(UnpicklerObject *self) 55867db96d56Sopenharmony_ci{ 55877db96d56Sopenharmony_ci if (self->buffers == NULL) { 55887db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 55897db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 55907db96d56Sopenharmony_ci "pickle stream refers to out-of-band data " 55917db96d56Sopenharmony_ci "but no *buffers* argument was given"); 55927db96d56Sopenharmony_ci return -1; 55937db96d56Sopenharmony_ci } 55947db96d56Sopenharmony_ci PyObject *buf = PyIter_Next(self->buffers); 55957db96d56Sopenharmony_ci if (buf == NULL) { 55967db96d56Sopenharmony_ci if (!PyErr_Occurred()) { 55977db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 55987db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 55997db96d56Sopenharmony_ci "not enough out-of-band buffers"); 56007db96d56Sopenharmony_ci } 56017db96d56Sopenharmony_ci return -1; 56027db96d56Sopenharmony_ci } 56037db96d56Sopenharmony_ci 56047db96d56Sopenharmony_ci PDATA_PUSH(self->stack, buf, -1); 56057db96d56Sopenharmony_ci return 0; 56067db96d56Sopenharmony_ci} 56077db96d56Sopenharmony_ci 56087db96d56Sopenharmony_cistatic int 56097db96d56Sopenharmony_ciload_readonly_buffer(UnpicklerObject *self) 56107db96d56Sopenharmony_ci{ 56117db96d56Sopenharmony_ci Py_ssize_t len = Py_SIZE(self->stack); 56127db96d56Sopenharmony_ci if (len <= self->stack->fence) { 56137db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 56147db96d56Sopenharmony_ci } 56157db96d56Sopenharmony_ci 56167db96d56Sopenharmony_ci PyObject *obj = self->stack->data[len - 1]; 56177db96d56Sopenharmony_ci PyObject *view = PyMemoryView_FromObject(obj); 56187db96d56Sopenharmony_ci if (view == NULL) { 56197db96d56Sopenharmony_ci return -1; 56207db96d56Sopenharmony_ci } 56217db96d56Sopenharmony_ci if (!PyMemoryView_GET_BUFFER(view)->readonly) { 56227db96d56Sopenharmony_ci /* Original object is writable */ 56237db96d56Sopenharmony_ci PyMemoryView_GET_BUFFER(view)->readonly = 1; 56247db96d56Sopenharmony_ci self->stack->data[len - 1] = view; 56257db96d56Sopenharmony_ci Py_DECREF(obj); 56267db96d56Sopenharmony_ci } 56277db96d56Sopenharmony_ci else { 56287db96d56Sopenharmony_ci /* Original object is read-only, no need to replace it */ 56297db96d56Sopenharmony_ci Py_DECREF(view); 56307db96d56Sopenharmony_ci } 56317db96d56Sopenharmony_ci return 0; 56327db96d56Sopenharmony_ci} 56337db96d56Sopenharmony_ci 56347db96d56Sopenharmony_cistatic int 56357db96d56Sopenharmony_ciload_unicode(UnpicklerObject *self) 56367db96d56Sopenharmony_ci{ 56377db96d56Sopenharmony_ci PyObject *str; 56387db96d56Sopenharmony_ci Py_ssize_t len; 56397db96d56Sopenharmony_ci char *s = NULL; 56407db96d56Sopenharmony_ci 56417db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 56427db96d56Sopenharmony_ci return -1; 56437db96d56Sopenharmony_ci if (len < 1) 56447db96d56Sopenharmony_ci return bad_readline(); 56457db96d56Sopenharmony_ci 56467db96d56Sopenharmony_ci str = PyUnicode_DecodeRawUnicodeEscape(s, len - 1, NULL); 56477db96d56Sopenharmony_ci if (str == NULL) 56487db96d56Sopenharmony_ci return -1; 56497db96d56Sopenharmony_ci 56507db96d56Sopenharmony_ci PDATA_PUSH(self->stack, str, -1); 56517db96d56Sopenharmony_ci return 0; 56527db96d56Sopenharmony_ci} 56537db96d56Sopenharmony_ci 56547db96d56Sopenharmony_cistatic int 56557db96d56Sopenharmony_ciload_counted_binunicode(UnpicklerObject *self, int nbytes) 56567db96d56Sopenharmony_ci{ 56577db96d56Sopenharmony_ci PyObject *str; 56587db96d56Sopenharmony_ci Py_ssize_t size; 56597db96d56Sopenharmony_ci char *s; 56607db96d56Sopenharmony_ci 56617db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, nbytes) < 0) 56627db96d56Sopenharmony_ci return -1; 56637db96d56Sopenharmony_ci 56647db96d56Sopenharmony_ci size = calc_binsize(s, nbytes); 56657db96d56Sopenharmony_ci if (size < 0) { 56667db96d56Sopenharmony_ci PyErr_Format(PyExc_OverflowError, 56677db96d56Sopenharmony_ci "BINUNICODE exceeds system's maximum size of %zd bytes", 56687db96d56Sopenharmony_ci PY_SSIZE_T_MAX); 56697db96d56Sopenharmony_ci return -1; 56707db96d56Sopenharmony_ci } 56717db96d56Sopenharmony_ci 56727db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, size) < 0) 56737db96d56Sopenharmony_ci return -1; 56747db96d56Sopenharmony_ci 56757db96d56Sopenharmony_ci str = PyUnicode_DecodeUTF8(s, size, "surrogatepass"); 56767db96d56Sopenharmony_ci if (str == NULL) 56777db96d56Sopenharmony_ci return -1; 56787db96d56Sopenharmony_ci 56797db96d56Sopenharmony_ci PDATA_PUSH(self->stack, str, -1); 56807db96d56Sopenharmony_ci return 0; 56817db96d56Sopenharmony_ci} 56827db96d56Sopenharmony_ci 56837db96d56Sopenharmony_cistatic int 56847db96d56Sopenharmony_ciload_counted_tuple(UnpicklerObject *self, Py_ssize_t len) 56857db96d56Sopenharmony_ci{ 56867db96d56Sopenharmony_ci PyObject *tuple; 56877db96d56Sopenharmony_ci 56887db96d56Sopenharmony_ci if (Py_SIZE(self->stack) < len) 56897db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 56907db96d56Sopenharmony_ci 56917db96d56Sopenharmony_ci tuple = Pdata_poptuple(self->stack, Py_SIZE(self->stack) - len); 56927db96d56Sopenharmony_ci if (tuple == NULL) 56937db96d56Sopenharmony_ci return -1; 56947db96d56Sopenharmony_ci PDATA_PUSH(self->stack, tuple, -1); 56957db96d56Sopenharmony_ci return 0; 56967db96d56Sopenharmony_ci} 56977db96d56Sopenharmony_ci 56987db96d56Sopenharmony_cistatic int 56997db96d56Sopenharmony_ciload_tuple(UnpicklerObject *self) 57007db96d56Sopenharmony_ci{ 57017db96d56Sopenharmony_ci Py_ssize_t i; 57027db96d56Sopenharmony_ci 57037db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 57047db96d56Sopenharmony_ci return -1; 57057db96d56Sopenharmony_ci 57067db96d56Sopenharmony_ci return load_counted_tuple(self, Py_SIZE(self->stack) - i); 57077db96d56Sopenharmony_ci} 57087db96d56Sopenharmony_ci 57097db96d56Sopenharmony_cistatic int 57107db96d56Sopenharmony_ciload_empty_list(UnpicklerObject *self) 57117db96d56Sopenharmony_ci{ 57127db96d56Sopenharmony_ci PyObject *list; 57137db96d56Sopenharmony_ci 57147db96d56Sopenharmony_ci if ((list = PyList_New(0)) == NULL) 57157db96d56Sopenharmony_ci return -1; 57167db96d56Sopenharmony_ci PDATA_PUSH(self->stack, list, -1); 57177db96d56Sopenharmony_ci return 0; 57187db96d56Sopenharmony_ci} 57197db96d56Sopenharmony_ci 57207db96d56Sopenharmony_cistatic int 57217db96d56Sopenharmony_ciload_empty_dict(UnpicklerObject *self) 57227db96d56Sopenharmony_ci{ 57237db96d56Sopenharmony_ci PyObject *dict; 57247db96d56Sopenharmony_ci 57257db96d56Sopenharmony_ci if ((dict = PyDict_New()) == NULL) 57267db96d56Sopenharmony_ci return -1; 57277db96d56Sopenharmony_ci PDATA_PUSH(self->stack, dict, -1); 57287db96d56Sopenharmony_ci return 0; 57297db96d56Sopenharmony_ci} 57307db96d56Sopenharmony_ci 57317db96d56Sopenharmony_cistatic int 57327db96d56Sopenharmony_ciload_empty_set(UnpicklerObject *self) 57337db96d56Sopenharmony_ci{ 57347db96d56Sopenharmony_ci PyObject *set; 57357db96d56Sopenharmony_ci 57367db96d56Sopenharmony_ci if ((set = PySet_New(NULL)) == NULL) 57377db96d56Sopenharmony_ci return -1; 57387db96d56Sopenharmony_ci PDATA_PUSH(self->stack, set, -1); 57397db96d56Sopenharmony_ci return 0; 57407db96d56Sopenharmony_ci} 57417db96d56Sopenharmony_ci 57427db96d56Sopenharmony_cistatic int 57437db96d56Sopenharmony_ciload_list(UnpicklerObject *self) 57447db96d56Sopenharmony_ci{ 57457db96d56Sopenharmony_ci PyObject *list; 57467db96d56Sopenharmony_ci Py_ssize_t i; 57477db96d56Sopenharmony_ci 57487db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 57497db96d56Sopenharmony_ci return -1; 57507db96d56Sopenharmony_ci 57517db96d56Sopenharmony_ci list = Pdata_poplist(self->stack, i); 57527db96d56Sopenharmony_ci if (list == NULL) 57537db96d56Sopenharmony_ci return -1; 57547db96d56Sopenharmony_ci PDATA_PUSH(self->stack, list, -1); 57557db96d56Sopenharmony_ci return 0; 57567db96d56Sopenharmony_ci} 57577db96d56Sopenharmony_ci 57587db96d56Sopenharmony_cistatic int 57597db96d56Sopenharmony_ciload_dict(UnpicklerObject *self) 57607db96d56Sopenharmony_ci{ 57617db96d56Sopenharmony_ci PyObject *dict, *key, *value; 57627db96d56Sopenharmony_ci Py_ssize_t i, j, k; 57637db96d56Sopenharmony_ci 57647db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 57657db96d56Sopenharmony_ci return -1; 57667db96d56Sopenharmony_ci j = Py_SIZE(self->stack); 57677db96d56Sopenharmony_ci 57687db96d56Sopenharmony_ci if ((dict = PyDict_New()) == NULL) 57697db96d56Sopenharmony_ci return -1; 57707db96d56Sopenharmony_ci 57717db96d56Sopenharmony_ci if ((j - i) % 2 != 0) { 57727db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 57737db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "odd number of items for DICT"); 57747db96d56Sopenharmony_ci Py_DECREF(dict); 57757db96d56Sopenharmony_ci return -1; 57767db96d56Sopenharmony_ci } 57777db96d56Sopenharmony_ci 57787db96d56Sopenharmony_ci for (k = i + 1; k < j; k += 2) { 57797db96d56Sopenharmony_ci key = self->stack->data[k - 1]; 57807db96d56Sopenharmony_ci value = self->stack->data[k]; 57817db96d56Sopenharmony_ci if (PyDict_SetItem(dict, key, value) < 0) { 57827db96d56Sopenharmony_ci Py_DECREF(dict); 57837db96d56Sopenharmony_ci return -1; 57847db96d56Sopenharmony_ci } 57857db96d56Sopenharmony_ci } 57867db96d56Sopenharmony_ci Pdata_clear(self->stack, i); 57877db96d56Sopenharmony_ci PDATA_PUSH(self->stack, dict, -1); 57887db96d56Sopenharmony_ci return 0; 57897db96d56Sopenharmony_ci} 57907db96d56Sopenharmony_ci 57917db96d56Sopenharmony_cistatic int 57927db96d56Sopenharmony_ciload_frozenset(UnpicklerObject *self) 57937db96d56Sopenharmony_ci{ 57947db96d56Sopenharmony_ci PyObject *items; 57957db96d56Sopenharmony_ci PyObject *frozenset; 57967db96d56Sopenharmony_ci Py_ssize_t i; 57977db96d56Sopenharmony_ci 57987db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 57997db96d56Sopenharmony_ci return -1; 58007db96d56Sopenharmony_ci 58017db96d56Sopenharmony_ci items = Pdata_poptuple(self->stack, i); 58027db96d56Sopenharmony_ci if (items == NULL) 58037db96d56Sopenharmony_ci return -1; 58047db96d56Sopenharmony_ci 58057db96d56Sopenharmony_ci frozenset = PyFrozenSet_New(items); 58067db96d56Sopenharmony_ci Py_DECREF(items); 58077db96d56Sopenharmony_ci if (frozenset == NULL) 58087db96d56Sopenharmony_ci return -1; 58097db96d56Sopenharmony_ci 58107db96d56Sopenharmony_ci PDATA_PUSH(self->stack, frozenset, -1); 58117db96d56Sopenharmony_ci return 0; 58127db96d56Sopenharmony_ci} 58137db96d56Sopenharmony_ci 58147db96d56Sopenharmony_cistatic PyObject * 58157db96d56Sopenharmony_ciinstantiate(PyObject *cls, PyObject *args) 58167db96d56Sopenharmony_ci{ 58177db96d56Sopenharmony_ci /* Caller must assure args are a tuple. Normally, args come from 58187db96d56Sopenharmony_ci Pdata_poptuple which packs objects from the top of the stack 58197db96d56Sopenharmony_ci into a newly created tuple. */ 58207db96d56Sopenharmony_ci assert(PyTuple_Check(args)); 58217db96d56Sopenharmony_ci if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) { 58227db96d56Sopenharmony_ci PyObject *func; 58237db96d56Sopenharmony_ci if (_PyObject_LookupAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) { 58247db96d56Sopenharmony_ci return NULL; 58257db96d56Sopenharmony_ci } 58267db96d56Sopenharmony_ci if (func == NULL) { 58277db96d56Sopenharmony_ci return PyObject_CallMethodOneArg(cls, &_Py_ID(__new__), cls); 58287db96d56Sopenharmony_ci } 58297db96d56Sopenharmony_ci Py_DECREF(func); 58307db96d56Sopenharmony_ci } 58317db96d56Sopenharmony_ci return PyObject_CallObject(cls, args); 58327db96d56Sopenharmony_ci} 58337db96d56Sopenharmony_ci 58347db96d56Sopenharmony_cistatic int 58357db96d56Sopenharmony_ciload_obj(UnpicklerObject *self) 58367db96d56Sopenharmony_ci{ 58377db96d56Sopenharmony_ci PyObject *cls, *args, *obj = NULL; 58387db96d56Sopenharmony_ci Py_ssize_t i; 58397db96d56Sopenharmony_ci 58407db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 58417db96d56Sopenharmony_ci return -1; 58427db96d56Sopenharmony_ci 58437db96d56Sopenharmony_ci if (Py_SIZE(self->stack) - i < 1) 58447db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 58457db96d56Sopenharmony_ci 58467db96d56Sopenharmony_ci args = Pdata_poptuple(self->stack, i + 1); 58477db96d56Sopenharmony_ci if (args == NULL) 58487db96d56Sopenharmony_ci return -1; 58497db96d56Sopenharmony_ci 58507db96d56Sopenharmony_ci PDATA_POP(self->stack, cls); 58517db96d56Sopenharmony_ci if (cls) { 58527db96d56Sopenharmony_ci obj = instantiate(cls, args); 58537db96d56Sopenharmony_ci Py_DECREF(cls); 58547db96d56Sopenharmony_ci } 58557db96d56Sopenharmony_ci Py_DECREF(args); 58567db96d56Sopenharmony_ci if (obj == NULL) 58577db96d56Sopenharmony_ci return -1; 58587db96d56Sopenharmony_ci 58597db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 58607db96d56Sopenharmony_ci return 0; 58617db96d56Sopenharmony_ci} 58627db96d56Sopenharmony_ci 58637db96d56Sopenharmony_cistatic int 58647db96d56Sopenharmony_ciload_inst(UnpicklerObject *self) 58657db96d56Sopenharmony_ci{ 58667db96d56Sopenharmony_ci PyObject *cls = NULL; 58677db96d56Sopenharmony_ci PyObject *args = NULL; 58687db96d56Sopenharmony_ci PyObject *obj = NULL; 58697db96d56Sopenharmony_ci PyObject *module_name; 58707db96d56Sopenharmony_ci PyObject *class_name; 58717db96d56Sopenharmony_ci Py_ssize_t len; 58727db96d56Sopenharmony_ci Py_ssize_t i; 58737db96d56Sopenharmony_ci char *s; 58747db96d56Sopenharmony_ci 58757db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 58767db96d56Sopenharmony_ci return -1; 58777db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 58787db96d56Sopenharmony_ci return -1; 58797db96d56Sopenharmony_ci if (len < 2) 58807db96d56Sopenharmony_ci return bad_readline(); 58817db96d56Sopenharmony_ci 58827db96d56Sopenharmony_ci /* Here it is safe to use PyUnicode_DecodeASCII(), even though non-ASCII 58837db96d56Sopenharmony_ci identifiers are permitted in Python 3.0, since the INST opcode is only 58847db96d56Sopenharmony_ci supported by older protocols on Python 2.x. */ 58857db96d56Sopenharmony_ci module_name = PyUnicode_DecodeASCII(s, len - 1, "strict"); 58867db96d56Sopenharmony_ci if (module_name == NULL) 58877db96d56Sopenharmony_ci return -1; 58887db96d56Sopenharmony_ci 58897db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) >= 0) { 58907db96d56Sopenharmony_ci if (len < 2) { 58917db96d56Sopenharmony_ci Py_DECREF(module_name); 58927db96d56Sopenharmony_ci return bad_readline(); 58937db96d56Sopenharmony_ci } 58947db96d56Sopenharmony_ci class_name = PyUnicode_DecodeASCII(s, len - 1, "strict"); 58957db96d56Sopenharmony_ci if (class_name != NULL) { 58967db96d56Sopenharmony_ci cls = find_class(self, module_name, class_name); 58977db96d56Sopenharmony_ci Py_DECREF(class_name); 58987db96d56Sopenharmony_ci } 58997db96d56Sopenharmony_ci } 59007db96d56Sopenharmony_ci Py_DECREF(module_name); 59017db96d56Sopenharmony_ci 59027db96d56Sopenharmony_ci if (cls == NULL) 59037db96d56Sopenharmony_ci return -1; 59047db96d56Sopenharmony_ci 59057db96d56Sopenharmony_ci if ((args = Pdata_poptuple(self->stack, i)) != NULL) { 59067db96d56Sopenharmony_ci obj = instantiate(cls, args); 59077db96d56Sopenharmony_ci Py_DECREF(args); 59087db96d56Sopenharmony_ci } 59097db96d56Sopenharmony_ci Py_DECREF(cls); 59107db96d56Sopenharmony_ci 59117db96d56Sopenharmony_ci if (obj == NULL) 59127db96d56Sopenharmony_ci return -1; 59137db96d56Sopenharmony_ci 59147db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 59157db96d56Sopenharmony_ci return 0; 59167db96d56Sopenharmony_ci} 59177db96d56Sopenharmony_ci 59187db96d56Sopenharmony_cistatic void 59197db96d56Sopenharmony_cinewobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg) 59207db96d56Sopenharmony_ci{ 59217db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 59227db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, msg, 59237db96d56Sopenharmony_ci use_kwargs ? "NEWOBJ_EX" : "NEWOBJ", 59247db96d56Sopenharmony_ci Py_TYPE(arg)->tp_name); 59257db96d56Sopenharmony_ci} 59267db96d56Sopenharmony_ci 59277db96d56Sopenharmony_cistatic int 59287db96d56Sopenharmony_ciload_newobj(UnpicklerObject *self, int use_kwargs) 59297db96d56Sopenharmony_ci{ 59307db96d56Sopenharmony_ci PyObject *cls, *args, *kwargs = NULL; 59317db96d56Sopenharmony_ci PyObject *obj; 59327db96d56Sopenharmony_ci 59337db96d56Sopenharmony_ci /* Stack is ... cls args [kwargs], and we want to call 59347db96d56Sopenharmony_ci * cls.__new__(cls, *args, **kwargs). 59357db96d56Sopenharmony_ci */ 59367db96d56Sopenharmony_ci if (use_kwargs) { 59377db96d56Sopenharmony_ci PDATA_POP(self->stack, kwargs); 59387db96d56Sopenharmony_ci if (kwargs == NULL) { 59397db96d56Sopenharmony_ci return -1; 59407db96d56Sopenharmony_ci } 59417db96d56Sopenharmony_ci } 59427db96d56Sopenharmony_ci PDATA_POP(self->stack, args); 59437db96d56Sopenharmony_ci if (args == NULL) { 59447db96d56Sopenharmony_ci Py_XDECREF(kwargs); 59457db96d56Sopenharmony_ci return -1; 59467db96d56Sopenharmony_ci } 59477db96d56Sopenharmony_ci PDATA_POP(self->stack, cls); 59487db96d56Sopenharmony_ci if (cls == NULL) { 59497db96d56Sopenharmony_ci Py_XDECREF(kwargs); 59507db96d56Sopenharmony_ci Py_DECREF(args); 59517db96d56Sopenharmony_ci return -1; 59527db96d56Sopenharmony_ci } 59537db96d56Sopenharmony_ci 59547db96d56Sopenharmony_ci if (!PyType_Check(cls)) { 59557db96d56Sopenharmony_ci newobj_unpickling_error("%s class argument must be a type, not %.200s", 59567db96d56Sopenharmony_ci use_kwargs, cls); 59577db96d56Sopenharmony_ci goto error; 59587db96d56Sopenharmony_ci } 59597db96d56Sopenharmony_ci if (((PyTypeObject *)cls)->tp_new == NULL) { 59607db96d56Sopenharmony_ci newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__", 59617db96d56Sopenharmony_ci use_kwargs, cls); 59627db96d56Sopenharmony_ci goto error; 59637db96d56Sopenharmony_ci } 59647db96d56Sopenharmony_ci if (!PyTuple_Check(args)) { 59657db96d56Sopenharmony_ci newobj_unpickling_error("%s args argument must be a tuple, not %.200s", 59667db96d56Sopenharmony_ci use_kwargs, args); 59677db96d56Sopenharmony_ci goto error; 59687db96d56Sopenharmony_ci } 59697db96d56Sopenharmony_ci if (use_kwargs && !PyDict_Check(kwargs)) { 59707db96d56Sopenharmony_ci newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s", 59717db96d56Sopenharmony_ci use_kwargs, kwargs); 59727db96d56Sopenharmony_ci goto error; 59737db96d56Sopenharmony_ci } 59747db96d56Sopenharmony_ci 59757db96d56Sopenharmony_ci obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs); 59767db96d56Sopenharmony_ci if (obj == NULL) { 59777db96d56Sopenharmony_ci goto error; 59787db96d56Sopenharmony_ci } 59797db96d56Sopenharmony_ci Py_XDECREF(kwargs); 59807db96d56Sopenharmony_ci Py_DECREF(args); 59817db96d56Sopenharmony_ci Py_DECREF(cls); 59827db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 59837db96d56Sopenharmony_ci return 0; 59847db96d56Sopenharmony_ci 59857db96d56Sopenharmony_cierror: 59867db96d56Sopenharmony_ci Py_XDECREF(kwargs); 59877db96d56Sopenharmony_ci Py_DECREF(args); 59887db96d56Sopenharmony_ci Py_DECREF(cls); 59897db96d56Sopenharmony_ci return -1; 59907db96d56Sopenharmony_ci} 59917db96d56Sopenharmony_ci 59927db96d56Sopenharmony_cistatic int 59937db96d56Sopenharmony_ciload_global(UnpicklerObject *self) 59947db96d56Sopenharmony_ci{ 59957db96d56Sopenharmony_ci PyObject *global = NULL; 59967db96d56Sopenharmony_ci PyObject *module_name; 59977db96d56Sopenharmony_ci PyObject *global_name; 59987db96d56Sopenharmony_ci Py_ssize_t len; 59997db96d56Sopenharmony_ci char *s; 60007db96d56Sopenharmony_ci 60017db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 60027db96d56Sopenharmony_ci return -1; 60037db96d56Sopenharmony_ci if (len < 2) 60047db96d56Sopenharmony_ci return bad_readline(); 60057db96d56Sopenharmony_ci module_name = PyUnicode_DecodeUTF8(s, len - 1, "strict"); 60067db96d56Sopenharmony_ci if (!module_name) 60077db96d56Sopenharmony_ci return -1; 60087db96d56Sopenharmony_ci 60097db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) >= 0) { 60107db96d56Sopenharmony_ci if (len < 2) { 60117db96d56Sopenharmony_ci Py_DECREF(module_name); 60127db96d56Sopenharmony_ci return bad_readline(); 60137db96d56Sopenharmony_ci } 60147db96d56Sopenharmony_ci global_name = PyUnicode_DecodeUTF8(s, len - 1, "strict"); 60157db96d56Sopenharmony_ci if (global_name) { 60167db96d56Sopenharmony_ci global = find_class(self, module_name, global_name); 60177db96d56Sopenharmony_ci Py_DECREF(global_name); 60187db96d56Sopenharmony_ci } 60197db96d56Sopenharmony_ci } 60207db96d56Sopenharmony_ci Py_DECREF(module_name); 60217db96d56Sopenharmony_ci 60227db96d56Sopenharmony_ci if (global == NULL) 60237db96d56Sopenharmony_ci return -1; 60247db96d56Sopenharmony_ci PDATA_PUSH(self->stack, global, -1); 60257db96d56Sopenharmony_ci return 0; 60267db96d56Sopenharmony_ci} 60277db96d56Sopenharmony_ci 60287db96d56Sopenharmony_cistatic int 60297db96d56Sopenharmony_ciload_stack_global(UnpicklerObject *self) 60307db96d56Sopenharmony_ci{ 60317db96d56Sopenharmony_ci PyObject *global; 60327db96d56Sopenharmony_ci PyObject *module_name; 60337db96d56Sopenharmony_ci PyObject *global_name; 60347db96d56Sopenharmony_ci 60357db96d56Sopenharmony_ci PDATA_POP(self->stack, global_name); 60367db96d56Sopenharmony_ci PDATA_POP(self->stack, module_name); 60377db96d56Sopenharmony_ci if (module_name == NULL || !PyUnicode_CheckExact(module_name) || 60387db96d56Sopenharmony_ci global_name == NULL || !PyUnicode_CheckExact(global_name)) { 60397db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 60407db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str"); 60417db96d56Sopenharmony_ci Py_XDECREF(global_name); 60427db96d56Sopenharmony_ci Py_XDECREF(module_name); 60437db96d56Sopenharmony_ci return -1; 60447db96d56Sopenharmony_ci } 60457db96d56Sopenharmony_ci global = find_class(self, module_name, global_name); 60467db96d56Sopenharmony_ci Py_DECREF(global_name); 60477db96d56Sopenharmony_ci Py_DECREF(module_name); 60487db96d56Sopenharmony_ci if (global == NULL) 60497db96d56Sopenharmony_ci return -1; 60507db96d56Sopenharmony_ci PDATA_PUSH(self->stack, global, -1); 60517db96d56Sopenharmony_ci return 0; 60527db96d56Sopenharmony_ci} 60537db96d56Sopenharmony_ci 60547db96d56Sopenharmony_cistatic int 60557db96d56Sopenharmony_ciload_persid(UnpicklerObject *self) 60567db96d56Sopenharmony_ci{ 60577db96d56Sopenharmony_ci PyObject *pid, *obj; 60587db96d56Sopenharmony_ci Py_ssize_t len; 60597db96d56Sopenharmony_ci char *s; 60607db96d56Sopenharmony_ci 60617db96d56Sopenharmony_ci if (self->pers_func) { 60627db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 60637db96d56Sopenharmony_ci return -1; 60647db96d56Sopenharmony_ci if (len < 1) 60657db96d56Sopenharmony_ci return bad_readline(); 60667db96d56Sopenharmony_ci 60677db96d56Sopenharmony_ci pid = PyUnicode_DecodeASCII(s, len - 1, "strict"); 60687db96d56Sopenharmony_ci if (pid == NULL) { 60697db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { 60707db96d56Sopenharmony_ci PyErr_SetString(_Pickle_GetGlobalState()->UnpicklingError, 60717db96d56Sopenharmony_ci "persistent IDs in protocol 0 must be " 60727db96d56Sopenharmony_ci "ASCII strings"); 60737db96d56Sopenharmony_ci } 60747db96d56Sopenharmony_ci return -1; 60757db96d56Sopenharmony_ci } 60767db96d56Sopenharmony_ci 60777db96d56Sopenharmony_ci obj = call_method(self->pers_func, self->pers_func_self, pid); 60787db96d56Sopenharmony_ci Py_DECREF(pid); 60797db96d56Sopenharmony_ci if (obj == NULL) 60807db96d56Sopenharmony_ci return -1; 60817db96d56Sopenharmony_ci 60827db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 60837db96d56Sopenharmony_ci return 0; 60847db96d56Sopenharmony_ci } 60857db96d56Sopenharmony_ci else { 60867db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 60877db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 60887db96d56Sopenharmony_ci "A load persistent id instruction was encountered,\n" 60897db96d56Sopenharmony_ci "but no persistent_load function was specified."); 60907db96d56Sopenharmony_ci return -1; 60917db96d56Sopenharmony_ci } 60927db96d56Sopenharmony_ci} 60937db96d56Sopenharmony_ci 60947db96d56Sopenharmony_cistatic int 60957db96d56Sopenharmony_ciload_binpersid(UnpicklerObject *self) 60967db96d56Sopenharmony_ci{ 60977db96d56Sopenharmony_ci PyObject *pid, *obj; 60987db96d56Sopenharmony_ci 60997db96d56Sopenharmony_ci if (self->pers_func) { 61007db96d56Sopenharmony_ci PDATA_POP(self->stack, pid); 61017db96d56Sopenharmony_ci if (pid == NULL) 61027db96d56Sopenharmony_ci return -1; 61037db96d56Sopenharmony_ci 61047db96d56Sopenharmony_ci obj = call_method(self->pers_func, self->pers_func_self, pid); 61057db96d56Sopenharmony_ci Py_DECREF(pid); 61067db96d56Sopenharmony_ci if (obj == NULL) 61077db96d56Sopenharmony_ci return -1; 61087db96d56Sopenharmony_ci 61097db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 61107db96d56Sopenharmony_ci return 0; 61117db96d56Sopenharmony_ci } 61127db96d56Sopenharmony_ci else { 61137db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 61147db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 61157db96d56Sopenharmony_ci "A load persistent id instruction was encountered,\n" 61167db96d56Sopenharmony_ci "but no persistent_load function was specified."); 61177db96d56Sopenharmony_ci return -1; 61187db96d56Sopenharmony_ci } 61197db96d56Sopenharmony_ci} 61207db96d56Sopenharmony_ci 61217db96d56Sopenharmony_cistatic int 61227db96d56Sopenharmony_ciload_pop(UnpicklerObject *self) 61237db96d56Sopenharmony_ci{ 61247db96d56Sopenharmony_ci Py_ssize_t len = Py_SIZE(self->stack); 61257db96d56Sopenharmony_ci 61267db96d56Sopenharmony_ci /* Note that we split the (pickle.py) stack into two stacks, 61277db96d56Sopenharmony_ci * an object stack and a mark stack. We have to be clever and 61287db96d56Sopenharmony_ci * pop the right one. We do this by looking at the top of the 61297db96d56Sopenharmony_ci * mark stack first, and only signalling a stack underflow if 61307db96d56Sopenharmony_ci * the object stack is empty and the mark stack doesn't match 61317db96d56Sopenharmony_ci * our expectations. 61327db96d56Sopenharmony_ci */ 61337db96d56Sopenharmony_ci if (self->num_marks > 0 && self->marks[self->num_marks - 1] == len) { 61347db96d56Sopenharmony_ci self->num_marks--; 61357db96d56Sopenharmony_ci self->stack->mark_set = self->num_marks != 0; 61367db96d56Sopenharmony_ci self->stack->fence = self->num_marks ? 61377db96d56Sopenharmony_ci self->marks[self->num_marks - 1] : 0; 61387db96d56Sopenharmony_ci } else if (len <= self->stack->fence) 61397db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 61407db96d56Sopenharmony_ci else { 61417db96d56Sopenharmony_ci len--; 61427db96d56Sopenharmony_ci Py_DECREF(self->stack->data[len]); 61437db96d56Sopenharmony_ci Py_SET_SIZE(self->stack, len); 61447db96d56Sopenharmony_ci } 61457db96d56Sopenharmony_ci return 0; 61467db96d56Sopenharmony_ci} 61477db96d56Sopenharmony_ci 61487db96d56Sopenharmony_cistatic int 61497db96d56Sopenharmony_ciload_pop_mark(UnpicklerObject *self) 61507db96d56Sopenharmony_ci{ 61517db96d56Sopenharmony_ci Py_ssize_t i; 61527db96d56Sopenharmony_ci 61537db96d56Sopenharmony_ci if ((i = marker(self)) < 0) 61547db96d56Sopenharmony_ci return -1; 61557db96d56Sopenharmony_ci 61567db96d56Sopenharmony_ci Pdata_clear(self->stack, i); 61577db96d56Sopenharmony_ci 61587db96d56Sopenharmony_ci return 0; 61597db96d56Sopenharmony_ci} 61607db96d56Sopenharmony_ci 61617db96d56Sopenharmony_cistatic int 61627db96d56Sopenharmony_ciload_dup(UnpicklerObject *self) 61637db96d56Sopenharmony_ci{ 61647db96d56Sopenharmony_ci PyObject *last; 61657db96d56Sopenharmony_ci Py_ssize_t len = Py_SIZE(self->stack); 61667db96d56Sopenharmony_ci 61677db96d56Sopenharmony_ci if (len <= self->stack->fence) 61687db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 61697db96d56Sopenharmony_ci last = self->stack->data[len - 1]; 61707db96d56Sopenharmony_ci PDATA_APPEND(self->stack, last, -1); 61717db96d56Sopenharmony_ci return 0; 61727db96d56Sopenharmony_ci} 61737db96d56Sopenharmony_ci 61747db96d56Sopenharmony_cistatic int 61757db96d56Sopenharmony_ciload_get(UnpicklerObject *self) 61767db96d56Sopenharmony_ci{ 61777db96d56Sopenharmony_ci PyObject *key, *value; 61787db96d56Sopenharmony_ci Py_ssize_t idx; 61797db96d56Sopenharmony_ci Py_ssize_t len; 61807db96d56Sopenharmony_ci char *s; 61817db96d56Sopenharmony_ci 61827db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 61837db96d56Sopenharmony_ci return -1; 61847db96d56Sopenharmony_ci if (len < 2) 61857db96d56Sopenharmony_ci return bad_readline(); 61867db96d56Sopenharmony_ci 61877db96d56Sopenharmony_ci key = PyLong_FromString(s, NULL, 10); 61887db96d56Sopenharmony_ci if (key == NULL) 61897db96d56Sopenharmony_ci return -1; 61907db96d56Sopenharmony_ci idx = PyLong_AsSsize_t(key); 61917db96d56Sopenharmony_ci if (idx == -1 && PyErr_Occurred()) { 61927db96d56Sopenharmony_ci Py_DECREF(key); 61937db96d56Sopenharmony_ci return -1; 61947db96d56Sopenharmony_ci } 61957db96d56Sopenharmony_ci 61967db96d56Sopenharmony_ci value = _Unpickler_MemoGet(self, idx); 61977db96d56Sopenharmony_ci if (value == NULL) { 61987db96d56Sopenharmony_ci if (!PyErr_Occurred()) { 61997db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 62007db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx); 62017db96d56Sopenharmony_ci } 62027db96d56Sopenharmony_ci Py_DECREF(key); 62037db96d56Sopenharmony_ci return -1; 62047db96d56Sopenharmony_ci } 62057db96d56Sopenharmony_ci Py_DECREF(key); 62067db96d56Sopenharmony_ci 62077db96d56Sopenharmony_ci PDATA_APPEND(self->stack, value, -1); 62087db96d56Sopenharmony_ci return 0; 62097db96d56Sopenharmony_ci} 62107db96d56Sopenharmony_ci 62117db96d56Sopenharmony_cistatic int 62127db96d56Sopenharmony_ciload_binget(UnpicklerObject *self) 62137db96d56Sopenharmony_ci{ 62147db96d56Sopenharmony_ci PyObject *value; 62157db96d56Sopenharmony_ci Py_ssize_t idx; 62167db96d56Sopenharmony_ci char *s; 62177db96d56Sopenharmony_ci 62187db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 1) < 0) 62197db96d56Sopenharmony_ci return -1; 62207db96d56Sopenharmony_ci 62217db96d56Sopenharmony_ci idx = Py_CHARMASK(s[0]); 62227db96d56Sopenharmony_ci 62237db96d56Sopenharmony_ci value = _Unpickler_MemoGet(self, idx); 62247db96d56Sopenharmony_ci if (value == NULL) { 62257db96d56Sopenharmony_ci PyObject *key = PyLong_FromSsize_t(idx); 62267db96d56Sopenharmony_ci if (key != NULL) { 62277db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 62287db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx); 62297db96d56Sopenharmony_ci Py_DECREF(key); 62307db96d56Sopenharmony_ci } 62317db96d56Sopenharmony_ci return -1; 62327db96d56Sopenharmony_ci } 62337db96d56Sopenharmony_ci 62347db96d56Sopenharmony_ci PDATA_APPEND(self->stack, value, -1); 62357db96d56Sopenharmony_ci return 0; 62367db96d56Sopenharmony_ci} 62377db96d56Sopenharmony_ci 62387db96d56Sopenharmony_cistatic int 62397db96d56Sopenharmony_ciload_long_binget(UnpicklerObject *self) 62407db96d56Sopenharmony_ci{ 62417db96d56Sopenharmony_ci PyObject *value; 62427db96d56Sopenharmony_ci Py_ssize_t idx; 62437db96d56Sopenharmony_ci char *s; 62447db96d56Sopenharmony_ci 62457db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 4) < 0) 62467db96d56Sopenharmony_ci return -1; 62477db96d56Sopenharmony_ci 62487db96d56Sopenharmony_ci idx = calc_binsize(s, 4); 62497db96d56Sopenharmony_ci 62507db96d56Sopenharmony_ci value = _Unpickler_MemoGet(self, idx); 62517db96d56Sopenharmony_ci if (value == NULL) { 62527db96d56Sopenharmony_ci PyObject *key = PyLong_FromSsize_t(idx); 62537db96d56Sopenharmony_ci if (key != NULL) { 62547db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 62557db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx); 62567db96d56Sopenharmony_ci Py_DECREF(key); 62577db96d56Sopenharmony_ci } 62587db96d56Sopenharmony_ci return -1; 62597db96d56Sopenharmony_ci } 62607db96d56Sopenharmony_ci 62617db96d56Sopenharmony_ci PDATA_APPEND(self->stack, value, -1); 62627db96d56Sopenharmony_ci return 0; 62637db96d56Sopenharmony_ci} 62647db96d56Sopenharmony_ci 62657db96d56Sopenharmony_ci/* Push an object from the extension registry (EXT[124]). nbytes is 62667db96d56Sopenharmony_ci * the number of bytes following the opcode, holding the index (code) value. 62677db96d56Sopenharmony_ci */ 62687db96d56Sopenharmony_cistatic int 62697db96d56Sopenharmony_ciload_extension(UnpicklerObject *self, int nbytes) 62707db96d56Sopenharmony_ci{ 62717db96d56Sopenharmony_ci char *codebytes; /* the nbytes bytes after the opcode */ 62727db96d56Sopenharmony_ci long code; /* calc_binint returns long */ 62737db96d56Sopenharmony_ci PyObject *py_code; /* code as a Python int */ 62747db96d56Sopenharmony_ci PyObject *obj; /* the object to push */ 62757db96d56Sopenharmony_ci PyObject *pair; /* (module_name, class_name) */ 62767db96d56Sopenharmony_ci PyObject *module_name, *class_name; 62777db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 62787db96d56Sopenharmony_ci 62797db96d56Sopenharmony_ci assert(nbytes == 1 || nbytes == 2 || nbytes == 4); 62807db96d56Sopenharmony_ci if (_Unpickler_Read(self, &codebytes, nbytes) < 0) 62817db96d56Sopenharmony_ci return -1; 62827db96d56Sopenharmony_ci code = calc_binint(codebytes, nbytes); 62837db96d56Sopenharmony_ci if (code <= 0) { /* note that 0 is forbidden */ 62847db96d56Sopenharmony_ci /* Corrupt or hostile pickle. */ 62857db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "EXT specifies code <= 0"); 62867db96d56Sopenharmony_ci return -1; 62877db96d56Sopenharmony_ci } 62887db96d56Sopenharmony_ci 62897db96d56Sopenharmony_ci /* Look for the code in the cache. */ 62907db96d56Sopenharmony_ci py_code = PyLong_FromLong(code); 62917db96d56Sopenharmony_ci if (py_code == NULL) 62927db96d56Sopenharmony_ci return -1; 62937db96d56Sopenharmony_ci obj = PyDict_GetItemWithError(st->extension_cache, py_code); 62947db96d56Sopenharmony_ci if (obj != NULL) { 62957db96d56Sopenharmony_ci /* Bingo. */ 62967db96d56Sopenharmony_ci Py_DECREF(py_code); 62977db96d56Sopenharmony_ci PDATA_APPEND(self->stack, obj, -1); 62987db96d56Sopenharmony_ci return 0; 62997db96d56Sopenharmony_ci } 63007db96d56Sopenharmony_ci if (PyErr_Occurred()) { 63017db96d56Sopenharmony_ci Py_DECREF(py_code); 63027db96d56Sopenharmony_ci return -1; 63037db96d56Sopenharmony_ci } 63047db96d56Sopenharmony_ci 63057db96d56Sopenharmony_ci /* Look up the (module_name, class_name) pair. */ 63067db96d56Sopenharmony_ci pair = PyDict_GetItemWithError(st->inverted_registry, py_code); 63077db96d56Sopenharmony_ci if (pair == NULL) { 63087db96d56Sopenharmony_ci Py_DECREF(py_code); 63097db96d56Sopenharmony_ci if (!PyErr_Occurred()) { 63107db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "unregistered extension " 63117db96d56Sopenharmony_ci "code %ld", code); 63127db96d56Sopenharmony_ci } 63137db96d56Sopenharmony_ci return -1; 63147db96d56Sopenharmony_ci } 63157db96d56Sopenharmony_ci /* Since the extension registry is manipulable via Python code, 63167db96d56Sopenharmony_ci * confirm that pair is really a 2-tuple of strings. 63177db96d56Sopenharmony_ci */ 63187db96d56Sopenharmony_ci if (!PyTuple_Check(pair) || PyTuple_Size(pair) != 2) { 63197db96d56Sopenharmony_ci goto error; 63207db96d56Sopenharmony_ci } 63217db96d56Sopenharmony_ci 63227db96d56Sopenharmony_ci module_name = PyTuple_GET_ITEM(pair, 0); 63237db96d56Sopenharmony_ci if (!PyUnicode_Check(module_name)) { 63247db96d56Sopenharmony_ci goto error; 63257db96d56Sopenharmony_ci } 63267db96d56Sopenharmony_ci 63277db96d56Sopenharmony_ci class_name = PyTuple_GET_ITEM(pair, 1); 63287db96d56Sopenharmony_ci if (!PyUnicode_Check(class_name)) { 63297db96d56Sopenharmony_ci goto error; 63307db96d56Sopenharmony_ci } 63317db96d56Sopenharmony_ci 63327db96d56Sopenharmony_ci /* Load the object. */ 63337db96d56Sopenharmony_ci obj = find_class(self, module_name, class_name); 63347db96d56Sopenharmony_ci if (obj == NULL) { 63357db96d56Sopenharmony_ci Py_DECREF(py_code); 63367db96d56Sopenharmony_ci return -1; 63377db96d56Sopenharmony_ci } 63387db96d56Sopenharmony_ci /* Cache code -> obj. */ 63397db96d56Sopenharmony_ci code = PyDict_SetItem(st->extension_cache, py_code, obj); 63407db96d56Sopenharmony_ci Py_DECREF(py_code); 63417db96d56Sopenharmony_ci if (code < 0) { 63427db96d56Sopenharmony_ci Py_DECREF(obj); 63437db96d56Sopenharmony_ci return -1; 63447db96d56Sopenharmony_ci } 63457db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 63467db96d56Sopenharmony_ci return 0; 63477db96d56Sopenharmony_ci 63487db96d56Sopenharmony_cierror: 63497db96d56Sopenharmony_ci Py_DECREF(py_code); 63507db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "_inverted_registry[%ld] " 63517db96d56Sopenharmony_ci "isn't a 2-tuple of strings", code); 63527db96d56Sopenharmony_ci return -1; 63537db96d56Sopenharmony_ci} 63547db96d56Sopenharmony_ci 63557db96d56Sopenharmony_cistatic int 63567db96d56Sopenharmony_ciload_put(UnpicklerObject *self) 63577db96d56Sopenharmony_ci{ 63587db96d56Sopenharmony_ci PyObject *key, *value; 63597db96d56Sopenharmony_ci Py_ssize_t idx; 63607db96d56Sopenharmony_ci Py_ssize_t len; 63617db96d56Sopenharmony_ci char *s = NULL; 63627db96d56Sopenharmony_ci 63637db96d56Sopenharmony_ci if ((len = _Unpickler_Readline(self, &s)) < 0) 63647db96d56Sopenharmony_ci return -1; 63657db96d56Sopenharmony_ci if (len < 2) 63667db96d56Sopenharmony_ci return bad_readline(); 63677db96d56Sopenharmony_ci if (Py_SIZE(self->stack) <= self->stack->fence) 63687db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 63697db96d56Sopenharmony_ci value = self->stack->data[Py_SIZE(self->stack) - 1]; 63707db96d56Sopenharmony_ci 63717db96d56Sopenharmony_ci key = PyLong_FromString(s, NULL, 10); 63727db96d56Sopenharmony_ci if (key == NULL) 63737db96d56Sopenharmony_ci return -1; 63747db96d56Sopenharmony_ci idx = PyLong_AsSsize_t(key); 63757db96d56Sopenharmony_ci Py_DECREF(key); 63767db96d56Sopenharmony_ci if (idx < 0) { 63777db96d56Sopenharmony_ci if (!PyErr_Occurred()) 63787db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 63797db96d56Sopenharmony_ci "negative PUT argument"); 63807db96d56Sopenharmony_ci return -1; 63817db96d56Sopenharmony_ci } 63827db96d56Sopenharmony_ci 63837db96d56Sopenharmony_ci return _Unpickler_MemoPut(self, idx, value); 63847db96d56Sopenharmony_ci} 63857db96d56Sopenharmony_ci 63867db96d56Sopenharmony_cistatic int 63877db96d56Sopenharmony_ciload_binput(UnpicklerObject *self) 63887db96d56Sopenharmony_ci{ 63897db96d56Sopenharmony_ci PyObject *value; 63907db96d56Sopenharmony_ci Py_ssize_t idx; 63917db96d56Sopenharmony_ci char *s; 63927db96d56Sopenharmony_ci 63937db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 1) < 0) 63947db96d56Sopenharmony_ci return -1; 63957db96d56Sopenharmony_ci 63967db96d56Sopenharmony_ci if (Py_SIZE(self->stack) <= self->stack->fence) 63977db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 63987db96d56Sopenharmony_ci value = self->stack->data[Py_SIZE(self->stack) - 1]; 63997db96d56Sopenharmony_ci 64007db96d56Sopenharmony_ci idx = Py_CHARMASK(s[0]); 64017db96d56Sopenharmony_ci 64027db96d56Sopenharmony_ci return _Unpickler_MemoPut(self, idx, value); 64037db96d56Sopenharmony_ci} 64047db96d56Sopenharmony_ci 64057db96d56Sopenharmony_cistatic int 64067db96d56Sopenharmony_ciload_long_binput(UnpicklerObject *self) 64077db96d56Sopenharmony_ci{ 64087db96d56Sopenharmony_ci PyObject *value; 64097db96d56Sopenharmony_ci Py_ssize_t idx; 64107db96d56Sopenharmony_ci char *s; 64117db96d56Sopenharmony_ci 64127db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 4) < 0) 64137db96d56Sopenharmony_ci return -1; 64147db96d56Sopenharmony_ci 64157db96d56Sopenharmony_ci if (Py_SIZE(self->stack) <= self->stack->fence) 64167db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 64177db96d56Sopenharmony_ci value = self->stack->data[Py_SIZE(self->stack) - 1]; 64187db96d56Sopenharmony_ci 64197db96d56Sopenharmony_ci idx = calc_binsize(s, 4); 64207db96d56Sopenharmony_ci if (idx < 0) { 64217db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 64227db96d56Sopenharmony_ci "negative LONG_BINPUT argument"); 64237db96d56Sopenharmony_ci return -1; 64247db96d56Sopenharmony_ci } 64257db96d56Sopenharmony_ci 64267db96d56Sopenharmony_ci return _Unpickler_MemoPut(self, idx, value); 64277db96d56Sopenharmony_ci} 64287db96d56Sopenharmony_ci 64297db96d56Sopenharmony_cistatic int 64307db96d56Sopenharmony_ciload_memoize(UnpicklerObject *self) 64317db96d56Sopenharmony_ci{ 64327db96d56Sopenharmony_ci PyObject *value; 64337db96d56Sopenharmony_ci 64347db96d56Sopenharmony_ci if (Py_SIZE(self->stack) <= self->stack->fence) 64357db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 64367db96d56Sopenharmony_ci value = self->stack->data[Py_SIZE(self->stack) - 1]; 64377db96d56Sopenharmony_ci 64387db96d56Sopenharmony_ci return _Unpickler_MemoPut(self, self->memo_len, value); 64397db96d56Sopenharmony_ci} 64407db96d56Sopenharmony_ci 64417db96d56Sopenharmony_cistatic int 64427db96d56Sopenharmony_cido_append(UnpicklerObject *self, Py_ssize_t x) 64437db96d56Sopenharmony_ci{ 64447db96d56Sopenharmony_ci PyObject *value; 64457db96d56Sopenharmony_ci PyObject *slice; 64467db96d56Sopenharmony_ci PyObject *list; 64477db96d56Sopenharmony_ci PyObject *result; 64487db96d56Sopenharmony_ci Py_ssize_t len, i; 64497db96d56Sopenharmony_ci 64507db96d56Sopenharmony_ci len = Py_SIZE(self->stack); 64517db96d56Sopenharmony_ci if (x > len || x <= self->stack->fence) 64527db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 64537db96d56Sopenharmony_ci if (len == x) /* nothing to do */ 64547db96d56Sopenharmony_ci return 0; 64557db96d56Sopenharmony_ci 64567db96d56Sopenharmony_ci list = self->stack->data[x - 1]; 64577db96d56Sopenharmony_ci 64587db96d56Sopenharmony_ci if (PyList_CheckExact(list)) { 64597db96d56Sopenharmony_ci Py_ssize_t list_len; 64607db96d56Sopenharmony_ci int ret; 64617db96d56Sopenharmony_ci 64627db96d56Sopenharmony_ci slice = Pdata_poplist(self->stack, x); 64637db96d56Sopenharmony_ci if (!slice) 64647db96d56Sopenharmony_ci return -1; 64657db96d56Sopenharmony_ci list_len = PyList_GET_SIZE(list); 64667db96d56Sopenharmony_ci ret = PyList_SetSlice(list, list_len, list_len, slice); 64677db96d56Sopenharmony_ci Py_DECREF(slice); 64687db96d56Sopenharmony_ci return ret; 64697db96d56Sopenharmony_ci } 64707db96d56Sopenharmony_ci else { 64717db96d56Sopenharmony_ci PyObject *extend_func; 64727db96d56Sopenharmony_ci 64737db96d56Sopenharmony_ci if (_PyObject_LookupAttr(list, &_Py_ID(extend), &extend_func) < 0) { 64747db96d56Sopenharmony_ci return -1; 64757db96d56Sopenharmony_ci } 64767db96d56Sopenharmony_ci if (extend_func != NULL) { 64777db96d56Sopenharmony_ci slice = Pdata_poplist(self->stack, x); 64787db96d56Sopenharmony_ci if (!slice) { 64797db96d56Sopenharmony_ci Py_DECREF(extend_func); 64807db96d56Sopenharmony_ci return -1; 64817db96d56Sopenharmony_ci } 64827db96d56Sopenharmony_ci result = _Pickle_FastCall(extend_func, slice); 64837db96d56Sopenharmony_ci Py_DECREF(extend_func); 64847db96d56Sopenharmony_ci if (result == NULL) 64857db96d56Sopenharmony_ci return -1; 64867db96d56Sopenharmony_ci Py_DECREF(result); 64877db96d56Sopenharmony_ci } 64887db96d56Sopenharmony_ci else { 64897db96d56Sopenharmony_ci PyObject *append_func; 64907db96d56Sopenharmony_ci 64917db96d56Sopenharmony_ci /* Even if the PEP 307 requires extend() and append() methods, 64927db96d56Sopenharmony_ci fall back on append() if the object has no extend() method 64937db96d56Sopenharmony_ci for backward compatibility. */ 64947db96d56Sopenharmony_ci append_func = PyObject_GetAttr(list, &_Py_ID(append)); 64957db96d56Sopenharmony_ci if (append_func == NULL) 64967db96d56Sopenharmony_ci return -1; 64977db96d56Sopenharmony_ci for (i = x; i < len; i++) { 64987db96d56Sopenharmony_ci value = self->stack->data[i]; 64997db96d56Sopenharmony_ci result = _Pickle_FastCall(append_func, value); 65007db96d56Sopenharmony_ci if (result == NULL) { 65017db96d56Sopenharmony_ci Pdata_clear(self->stack, i + 1); 65027db96d56Sopenharmony_ci Py_SET_SIZE(self->stack, x); 65037db96d56Sopenharmony_ci Py_DECREF(append_func); 65047db96d56Sopenharmony_ci return -1; 65057db96d56Sopenharmony_ci } 65067db96d56Sopenharmony_ci Py_DECREF(result); 65077db96d56Sopenharmony_ci } 65087db96d56Sopenharmony_ci Py_SET_SIZE(self->stack, x); 65097db96d56Sopenharmony_ci Py_DECREF(append_func); 65107db96d56Sopenharmony_ci } 65117db96d56Sopenharmony_ci } 65127db96d56Sopenharmony_ci 65137db96d56Sopenharmony_ci return 0; 65147db96d56Sopenharmony_ci} 65157db96d56Sopenharmony_ci 65167db96d56Sopenharmony_cistatic int 65177db96d56Sopenharmony_ciload_append(UnpicklerObject *self) 65187db96d56Sopenharmony_ci{ 65197db96d56Sopenharmony_ci if (Py_SIZE(self->stack) - 1 <= self->stack->fence) 65207db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 65217db96d56Sopenharmony_ci return do_append(self, Py_SIZE(self->stack) - 1); 65227db96d56Sopenharmony_ci} 65237db96d56Sopenharmony_ci 65247db96d56Sopenharmony_cistatic int 65257db96d56Sopenharmony_ciload_appends(UnpicklerObject *self) 65267db96d56Sopenharmony_ci{ 65277db96d56Sopenharmony_ci Py_ssize_t i = marker(self); 65287db96d56Sopenharmony_ci if (i < 0) 65297db96d56Sopenharmony_ci return -1; 65307db96d56Sopenharmony_ci return do_append(self, i); 65317db96d56Sopenharmony_ci} 65327db96d56Sopenharmony_ci 65337db96d56Sopenharmony_cistatic int 65347db96d56Sopenharmony_cido_setitems(UnpicklerObject *self, Py_ssize_t x) 65357db96d56Sopenharmony_ci{ 65367db96d56Sopenharmony_ci PyObject *value, *key; 65377db96d56Sopenharmony_ci PyObject *dict; 65387db96d56Sopenharmony_ci Py_ssize_t len, i; 65397db96d56Sopenharmony_ci int status = 0; 65407db96d56Sopenharmony_ci 65417db96d56Sopenharmony_ci len = Py_SIZE(self->stack); 65427db96d56Sopenharmony_ci if (x > len || x <= self->stack->fence) 65437db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 65447db96d56Sopenharmony_ci if (len == x) /* nothing to do */ 65457db96d56Sopenharmony_ci return 0; 65467db96d56Sopenharmony_ci if ((len - x) % 2 != 0) { 65477db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 65487db96d56Sopenharmony_ci /* Corrupt or hostile pickle -- we never write one like this. */ 65497db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 65507db96d56Sopenharmony_ci "odd number of items for SETITEMS"); 65517db96d56Sopenharmony_ci return -1; 65527db96d56Sopenharmony_ci } 65537db96d56Sopenharmony_ci 65547db96d56Sopenharmony_ci /* Here, dict does not actually need to be a PyDict; it could be anything 65557db96d56Sopenharmony_ci that supports the __setitem__ attribute. */ 65567db96d56Sopenharmony_ci dict = self->stack->data[x - 1]; 65577db96d56Sopenharmony_ci 65587db96d56Sopenharmony_ci for (i = x + 1; i < len; i += 2) { 65597db96d56Sopenharmony_ci key = self->stack->data[i - 1]; 65607db96d56Sopenharmony_ci value = self->stack->data[i]; 65617db96d56Sopenharmony_ci if (PyObject_SetItem(dict, key, value) < 0) { 65627db96d56Sopenharmony_ci status = -1; 65637db96d56Sopenharmony_ci break; 65647db96d56Sopenharmony_ci } 65657db96d56Sopenharmony_ci } 65667db96d56Sopenharmony_ci 65677db96d56Sopenharmony_ci Pdata_clear(self->stack, x); 65687db96d56Sopenharmony_ci return status; 65697db96d56Sopenharmony_ci} 65707db96d56Sopenharmony_ci 65717db96d56Sopenharmony_cistatic int 65727db96d56Sopenharmony_ciload_setitem(UnpicklerObject *self) 65737db96d56Sopenharmony_ci{ 65747db96d56Sopenharmony_ci return do_setitems(self, Py_SIZE(self->stack) - 2); 65757db96d56Sopenharmony_ci} 65767db96d56Sopenharmony_ci 65777db96d56Sopenharmony_cistatic int 65787db96d56Sopenharmony_ciload_setitems(UnpicklerObject *self) 65797db96d56Sopenharmony_ci{ 65807db96d56Sopenharmony_ci Py_ssize_t i = marker(self); 65817db96d56Sopenharmony_ci if (i < 0) 65827db96d56Sopenharmony_ci return -1; 65837db96d56Sopenharmony_ci return do_setitems(self, i); 65847db96d56Sopenharmony_ci} 65857db96d56Sopenharmony_ci 65867db96d56Sopenharmony_cistatic int 65877db96d56Sopenharmony_ciload_additems(UnpicklerObject *self) 65887db96d56Sopenharmony_ci{ 65897db96d56Sopenharmony_ci PyObject *set; 65907db96d56Sopenharmony_ci Py_ssize_t mark, len, i; 65917db96d56Sopenharmony_ci 65927db96d56Sopenharmony_ci mark = marker(self); 65937db96d56Sopenharmony_ci if (mark < 0) 65947db96d56Sopenharmony_ci return -1; 65957db96d56Sopenharmony_ci len = Py_SIZE(self->stack); 65967db96d56Sopenharmony_ci if (mark > len || mark <= self->stack->fence) 65977db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 65987db96d56Sopenharmony_ci if (len == mark) /* nothing to do */ 65997db96d56Sopenharmony_ci return 0; 66007db96d56Sopenharmony_ci 66017db96d56Sopenharmony_ci set = self->stack->data[mark - 1]; 66027db96d56Sopenharmony_ci 66037db96d56Sopenharmony_ci if (PySet_Check(set)) { 66047db96d56Sopenharmony_ci PyObject *items; 66057db96d56Sopenharmony_ci int status; 66067db96d56Sopenharmony_ci 66077db96d56Sopenharmony_ci items = Pdata_poptuple(self->stack, mark); 66087db96d56Sopenharmony_ci if (items == NULL) 66097db96d56Sopenharmony_ci return -1; 66107db96d56Sopenharmony_ci 66117db96d56Sopenharmony_ci status = _PySet_Update(set, items); 66127db96d56Sopenharmony_ci Py_DECREF(items); 66137db96d56Sopenharmony_ci return status; 66147db96d56Sopenharmony_ci } 66157db96d56Sopenharmony_ci else { 66167db96d56Sopenharmony_ci PyObject *add_func; 66177db96d56Sopenharmony_ci 66187db96d56Sopenharmony_ci add_func = PyObject_GetAttr(set, &_Py_ID(add)); 66197db96d56Sopenharmony_ci if (add_func == NULL) 66207db96d56Sopenharmony_ci return -1; 66217db96d56Sopenharmony_ci for (i = mark; i < len; i++) { 66227db96d56Sopenharmony_ci PyObject *result; 66237db96d56Sopenharmony_ci PyObject *item; 66247db96d56Sopenharmony_ci 66257db96d56Sopenharmony_ci item = self->stack->data[i]; 66267db96d56Sopenharmony_ci result = _Pickle_FastCall(add_func, item); 66277db96d56Sopenharmony_ci if (result == NULL) { 66287db96d56Sopenharmony_ci Pdata_clear(self->stack, i + 1); 66297db96d56Sopenharmony_ci Py_SET_SIZE(self->stack, mark); 66307db96d56Sopenharmony_ci return -1; 66317db96d56Sopenharmony_ci } 66327db96d56Sopenharmony_ci Py_DECREF(result); 66337db96d56Sopenharmony_ci } 66347db96d56Sopenharmony_ci Py_SET_SIZE(self->stack, mark); 66357db96d56Sopenharmony_ci } 66367db96d56Sopenharmony_ci 66377db96d56Sopenharmony_ci return 0; 66387db96d56Sopenharmony_ci} 66397db96d56Sopenharmony_ci 66407db96d56Sopenharmony_cistatic int 66417db96d56Sopenharmony_ciload_build(UnpicklerObject *self) 66427db96d56Sopenharmony_ci{ 66437db96d56Sopenharmony_ci PyObject *state, *inst, *slotstate; 66447db96d56Sopenharmony_ci PyObject *setstate; 66457db96d56Sopenharmony_ci int status = 0; 66467db96d56Sopenharmony_ci 66477db96d56Sopenharmony_ci /* Stack is ... instance, state. We want to leave instance at 66487db96d56Sopenharmony_ci * the stack top, possibly mutated via instance.__setstate__(state). 66497db96d56Sopenharmony_ci */ 66507db96d56Sopenharmony_ci if (Py_SIZE(self->stack) - 2 < self->stack->fence) 66517db96d56Sopenharmony_ci return Pdata_stack_underflow(self->stack); 66527db96d56Sopenharmony_ci 66537db96d56Sopenharmony_ci PDATA_POP(self->stack, state); 66547db96d56Sopenharmony_ci if (state == NULL) 66557db96d56Sopenharmony_ci return -1; 66567db96d56Sopenharmony_ci 66577db96d56Sopenharmony_ci inst = self->stack->data[Py_SIZE(self->stack) - 1]; 66587db96d56Sopenharmony_ci 66597db96d56Sopenharmony_ci if (_PyObject_LookupAttr(inst, &_Py_ID(__setstate__), &setstate) < 0) { 66607db96d56Sopenharmony_ci Py_DECREF(state); 66617db96d56Sopenharmony_ci return -1; 66627db96d56Sopenharmony_ci } 66637db96d56Sopenharmony_ci if (setstate != NULL) { 66647db96d56Sopenharmony_ci PyObject *result; 66657db96d56Sopenharmony_ci 66667db96d56Sopenharmony_ci /* The explicit __setstate__ is responsible for everything. */ 66677db96d56Sopenharmony_ci result = _Pickle_FastCall(setstate, state); 66687db96d56Sopenharmony_ci Py_DECREF(setstate); 66697db96d56Sopenharmony_ci if (result == NULL) 66707db96d56Sopenharmony_ci return -1; 66717db96d56Sopenharmony_ci Py_DECREF(result); 66727db96d56Sopenharmony_ci return 0; 66737db96d56Sopenharmony_ci } 66747db96d56Sopenharmony_ci 66757db96d56Sopenharmony_ci /* A default __setstate__. First see whether state embeds a 66767db96d56Sopenharmony_ci * slot state dict too (a proto 2 addition). 66777db96d56Sopenharmony_ci */ 66787db96d56Sopenharmony_ci if (PyTuple_Check(state) && PyTuple_GET_SIZE(state) == 2) { 66797db96d56Sopenharmony_ci PyObject *tmp = state; 66807db96d56Sopenharmony_ci 66817db96d56Sopenharmony_ci state = PyTuple_GET_ITEM(tmp, 0); 66827db96d56Sopenharmony_ci slotstate = PyTuple_GET_ITEM(tmp, 1); 66837db96d56Sopenharmony_ci Py_INCREF(state); 66847db96d56Sopenharmony_ci Py_INCREF(slotstate); 66857db96d56Sopenharmony_ci Py_DECREF(tmp); 66867db96d56Sopenharmony_ci } 66877db96d56Sopenharmony_ci else 66887db96d56Sopenharmony_ci slotstate = NULL; 66897db96d56Sopenharmony_ci 66907db96d56Sopenharmony_ci /* Set inst.__dict__ from the state dict (if any). */ 66917db96d56Sopenharmony_ci if (state != Py_None) { 66927db96d56Sopenharmony_ci PyObject *dict; 66937db96d56Sopenharmony_ci PyObject *d_key, *d_value; 66947db96d56Sopenharmony_ci Py_ssize_t i; 66957db96d56Sopenharmony_ci 66967db96d56Sopenharmony_ci if (!PyDict_Check(state)) { 66977db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 66987db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, "state is not a dictionary"); 66997db96d56Sopenharmony_ci goto error; 67007db96d56Sopenharmony_ci } 67017db96d56Sopenharmony_ci dict = PyObject_GetAttr(inst, &_Py_ID(__dict__)); 67027db96d56Sopenharmony_ci if (dict == NULL) 67037db96d56Sopenharmony_ci goto error; 67047db96d56Sopenharmony_ci 67057db96d56Sopenharmony_ci i = 0; 67067db96d56Sopenharmony_ci while (PyDict_Next(state, &i, &d_key, &d_value)) { 67077db96d56Sopenharmony_ci /* normally the keys for instance attributes are 67087db96d56Sopenharmony_ci interned. we should try to do that here. */ 67097db96d56Sopenharmony_ci Py_INCREF(d_key); 67107db96d56Sopenharmony_ci if (PyUnicode_CheckExact(d_key)) 67117db96d56Sopenharmony_ci PyUnicode_InternInPlace(&d_key); 67127db96d56Sopenharmony_ci if (PyObject_SetItem(dict, d_key, d_value) < 0) { 67137db96d56Sopenharmony_ci Py_DECREF(d_key); 67147db96d56Sopenharmony_ci goto error; 67157db96d56Sopenharmony_ci } 67167db96d56Sopenharmony_ci Py_DECREF(d_key); 67177db96d56Sopenharmony_ci } 67187db96d56Sopenharmony_ci Py_DECREF(dict); 67197db96d56Sopenharmony_ci } 67207db96d56Sopenharmony_ci 67217db96d56Sopenharmony_ci /* Also set instance attributes from the slotstate dict (if any). */ 67227db96d56Sopenharmony_ci if (slotstate != NULL) { 67237db96d56Sopenharmony_ci PyObject *d_key, *d_value; 67247db96d56Sopenharmony_ci Py_ssize_t i; 67257db96d56Sopenharmony_ci 67267db96d56Sopenharmony_ci if (!PyDict_Check(slotstate)) { 67277db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 67287db96d56Sopenharmony_ci PyErr_SetString(st->UnpicklingError, 67297db96d56Sopenharmony_ci "slot state is not a dictionary"); 67307db96d56Sopenharmony_ci goto error; 67317db96d56Sopenharmony_ci } 67327db96d56Sopenharmony_ci i = 0; 67337db96d56Sopenharmony_ci while (PyDict_Next(slotstate, &i, &d_key, &d_value)) { 67347db96d56Sopenharmony_ci if (PyObject_SetAttr(inst, d_key, d_value) < 0) 67357db96d56Sopenharmony_ci goto error; 67367db96d56Sopenharmony_ci } 67377db96d56Sopenharmony_ci } 67387db96d56Sopenharmony_ci 67397db96d56Sopenharmony_ci if (0) { 67407db96d56Sopenharmony_ci error: 67417db96d56Sopenharmony_ci status = -1; 67427db96d56Sopenharmony_ci } 67437db96d56Sopenharmony_ci 67447db96d56Sopenharmony_ci Py_DECREF(state); 67457db96d56Sopenharmony_ci Py_XDECREF(slotstate); 67467db96d56Sopenharmony_ci return status; 67477db96d56Sopenharmony_ci} 67487db96d56Sopenharmony_ci 67497db96d56Sopenharmony_cistatic int 67507db96d56Sopenharmony_ciload_mark(UnpicklerObject *self) 67517db96d56Sopenharmony_ci{ 67527db96d56Sopenharmony_ci 67537db96d56Sopenharmony_ci /* Note that we split the (pickle.py) stack into two stacks, an 67547db96d56Sopenharmony_ci * object stack and a mark stack. Here we push a mark onto the 67557db96d56Sopenharmony_ci * mark stack. 67567db96d56Sopenharmony_ci */ 67577db96d56Sopenharmony_ci 67587db96d56Sopenharmony_ci if (self->num_marks >= self->marks_size) { 67597db96d56Sopenharmony_ci size_t alloc = ((size_t)self->num_marks << 1) + 20; 67607db96d56Sopenharmony_ci Py_ssize_t *marks_new = self->marks; 67617db96d56Sopenharmony_ci PyMem_RESIZE(marks_new, Py_ssize_t, alloc); 67627db96d56Sopenharmony_ci if (marks_new == NULL) { 67637db96d56Sopenharmony_ci PyErr_NoMemory(); 67647db96d56Sopenharmony_ci return -1; 67657db96d56Sopenharmony_ci } 67667db96d56Sopenharmony_ci self->marks = marks_new; 67677db96d56Sopenharmony_ci self->marks_size = (Py_ssize_t)alloc; 67687db96d56Sopenharmony_ci } 67697db96d56Sopenharmony_ci 67707db96d56Sopenharmony_ci self->stack->mark_set = 1; 67717db96d56Sopenharmony_ci self->marks[self->num_marks++] = self->stack->fence = Py_SIZE(self->stack); 67727db96d56Sopenharmony_ci 67737db96d56Sopenharmony_ci return 0; 67747db96d56Sopenharmony_ci} 67757db96d56Sopenharmony_ci 67767db96d56Sopenharmony_cistatic int 67777db96d56Sopenharmony_ciload_reduce(UnpicklerObject *self) 67787db96d56Sopenharmony_ci{ 67797db96d56Sopenharmony_ci PyObject *callable = NULL; 67807db96d56Sopenharmony_ci PyObject *argtup = NULL; 67817db96d56Sopenharmony_ci PyObject *obj = NULL; 67827db96d56Sopenharmony_ci 67837db96d56Sopenharmony_ci PDATA_POP(self->stack, argtup); 67847db96d56Sopenharmony_ci if (argtup == NULL) 67857db96d56Sopenharmony_ci return -1; 67867db96d56Sopenharmony_ci PDATA_POP(self->stack, callable); 67877db96d56Sopenharmony_ci if (callable) { 67887db96d56Sopenharmony_ci obj = PyObject_CallObject(callable, argtup); 67897db96d56Sopenharmony_ci Py_DECREF(callable); 67907db96d56Sopenharmony_ci } 67917db96d56Sopenharmony_ci Py_DECREF(argtup); 67927db96d56Sopenharmony_ci 67937db96d56Sopenharmony_ci if (obj == NULL) 67947db96d56Sopenharmony_ci return -1; 67957db96d56Sopenharmony_ci 67967db96d56Sopenharmony_ci PDATA_PUSH(self->stack, obj, -1); 67977db96d56Sopenharmony_ci return 0; 67987db96d56Sopenharmony_ci} 67997db96d56Sopenharmony_ci 68007db96d56Sopenharmony_ci/* Just raises an error if we don't know the protocol specified. PROTO 68017db96d56Sopenharmony_ci * is the first opcode for protocols >= 2. 68027db96d56Sopenharmony_ci */ 68037db96d56Sopenharmony_cistatic int 68047db96d56Sopenharmony_ciload_proto(UnpicklerObject *self) 68057db96d56Sopenharmony_ci{ 68067db96d56Sopenharmony_ci char *s; 68077db96d56Sopenharmony_ci int i; 68087db96d56Sopenharmony_ci 68097db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 1) < 0) 68107db96d56Sopenharmony_ci return -1; 68117db96d56Sopenharmony_ci 68127db96d56Sopenharmony_ci i = (unsigned char)s[0]; 68137db96d56Sopenharmony_ci if (i <= HIGHEST_PROTOCOL) { 68147db96d56Sopenharmony_ci self->proto = i; 68157db96d56Sopenharmony_ci return 0; 68167db96d56Sopenharmony_ci } 68177db96d56Sopenharmony_ci 68187db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "unsupported pickle protocol: %d", i); 68197db96d56Sopenharmony_ci return -1; 68207db96d56Sopenharmony_ci} 68217db96d56Sopenharmony_ci 68227db96d56Sopenharmony_cistatic int 68237db96d56Sopenharmony_ciload_frame(UnpicklerObject *self) 68247db96d56Sopenharmony_ci{ 68257db96d56Sopenharmony_ci char *s; 68267db96d56Sopenharmony_ci Py_ssize_t frame_len; 68277db96d56Sopenharmony_ci 68287db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 8) < 0) 68297db96d56Sopenharmony_ci return -1; 68307db96d56Sopenharmony_ci 68317db96d56Sopenharmony_ci frame_len = calc_binsize(s, 8); 68327db96d56Sopenharmony_ci if (frame_len < 0) { 68337db96d56Sopenharmony_ci PyErr_Format(PyExc_OverflowError, 68347db96d56Sopenharmony_ci "FRAME length exceeds system's maximum of %zd bytes", 68357db96d56Sopenharmony_ci PY_SSIZE_T_MAX); 68367db96d56Sopenharmony_ci return -1; 68377db96d56Sopenharmony_ci } 68387db96d56Sopenharmony_ci 68397db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, frame_len) < 0) 68407db96d56Sopenharmony_ci return -1; 68417db96d56Sopenharmony_ci 68427db96d56Sopenharmony_ci /* Rewind to start of frame */ 68437db96d56Sopenharmony_ci self->next_read_idx -= frame_len; 68447db96d56Sopenharmony_ci return 0; 68457db96d56Sopenharmony_ci} 68467db96d56Sopenharmony_ci 68477db96d56Sopenharmony_cistatic PyObject * 68487db96d56Sopenharmony_ciload(UnpicklerObject *self) 68497db96d56Sopenharmony_ci{ 68507db96d56Sopenharmony_ci PyObject *value = NULL; 68517db96d56Sopenharmony_ci char *s = NULL; 68527db96d56Sopenharmony_ci 68537db96d56Sopenharmony_ci self->num_marks = 0; 68547db96d56Sopenharmony_ci self->stack->mark_set = 0; 68557db96d56Sopenharmony_ci self->stack->fence = 0; 68567db96d56Sopenharmony_ci self->proto = 0; 68577db96d56Sopenharmony_ci if (Py_SIZE(self->stack)) 68587db96d56Sopenharmony_ci Pdata_clear(self->stack, 0); 68597db96d56Sopenharmony_ci 68607db96d56Sopenharmony_ci /* Convenient macros for the dispatch while-switch loop just below. */ 68617db96d56Sopenharmony_ci#define OP(opcode, load_func) \ 68627db96d56Sopenharmony_ci case opcode: if (load_func(self) < 0) break; continue; 68637db96d56Sopenharmony_ci 68647db96d56Sopenharmony_ci#define OP_ARG(opcode, load_func, arg) \ 68657db96d56Sopenharmony_ci case opcode: if (load_func(self, (arg)) < 0) break; continue; 68667db96d56Sopenharmony_ci 68677db96d56Sopenharmony_ci while (1) { 68687db96d56Sopenharmony_ci if (_Unpickler_Read(self, &s, 1) < 0) { 68697db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 68707db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(st->UnpicklingError)) { 68717db96d56Sopenharmony_ci PyErr_Format(PyExc_EOFError, "Ran out of input"); 68727db96d56Sopenharmony_ci } 68737db96d56Sopenharmony_ci return NULL; 68747db96d56Sopenharmony_ci } 68757db96d56Sopenharmony_ci 68767db96d56Sopenharmony_ci switch ((enum opcode)s[0]) { 68777db96d56Sopenharmony_ci OP(NONE, load_none) 68787db96d56Sopenharmony_ci OP(BININT, load_binint) 68797db96d56Sopenharmony_ci OP(BININT1, load_binint1) 68807db96d56Sopenharmony_ci OP(BININT2, load_binint2) 68817db96d56Sopenharmony_ci OP(INT, load_int) 68827db96d56Sopenharmony_ci OP(LONG, load_long) 68837db96d56Sopenharmony_ci OP_ARG(LONG1, load_counted_long, 1) 68847db96d56Sopenharmony_ci OP_ARG(LONG4, load_counted_long, 4) 68857db96d56Sopenharmony_ci OP(FLOAT, load_float) 68867db96d56Sopenharmony_ci OP(BINFLOAT, load_binfloat) 68877db96d56Sopenharmony_ci OP_ARG(SHORT_BINBYTES, load_counted_binbytes, 1) 68887db96d56Sopenharmony_ci OP_ARG(BINBYTES, load_counted_binbytes, 4) 68897db96d56Sopenharmony_ci OP_ARG(BINBYTES8, load_counted_binbytes, 8) 68907db96d56Sopenharmony_ci OP(BYTEARRAY8, load_counted_bytearray) 68917db96d56Sopenharmony_ci OP(NEXT_BUFFER, load_next_buffer) 68927db96d56Sopenharmony_ci OP(READONLY_BUFFER, load_readonly_buffer) 68937db96d56Sopenharmony_ci OP_ARG(SHORT_BINSTRING, load_counted_binstring, 1) 68947db96d56Sopenharmony_ci OP_ARG(BINSTRING, load_counted_binstring, 4) 68957db96d56Sopenharmony_ci OP(STRING, load_string) 68967db96d56Sopenharmony_ci OP(UNICODE, load_unicode) 68977db96d56Sopenharmony_ci OP_ARG(SHORT_BINUNICODE, load_counted_binunicode, 1) 68987db96d56Sopenharmony_ci OP_ARG(BINUNICODE, load_counted_binunicode, 4) 68997db96d56Sopenharmony_ci OP_ARG(BINUNICODE8, load_counted_binunicode, 8) 69007db96d56Sopenharmony_ci OP_ARG(EMPTY_TUPLE, load_counted_tuple, 0) 69017db96d56Sopenharmony_ci OP_ARG(TUPLE1, load_counted_tuple, 1) 69027db96d56Sopenharmony_ci OP_ARG(TUPLE2, load_counted_tuple, 2) 69037db96d56Sopenharmony_ci OP_ARG(TUPLE3, load_counted_tuple, 3) 69047db96d56Sopenharmony_ci OP(TUPLE, load_tuple) 69057db96d56Sopenharmony_ci OP(EMPTY_LIST, load_empty_list) 69067db96d56Sopenharmony_ci OP(LIST, load_list) 69077db96d56Sopenharmony_ci OP(EMPTY_DICT, load_empty_dict) 69087db96d56Sopenharmony_ci OP(DICT, load_dict) 69097db96d56Sopenharmony_ci OP(EMPTY_SET, load_empty_set) 69107db96d56Sopenharmony_ci OP(ADDITEMS, load_additems) 69117db96d56Sopenharmony_ci OP(FROZENSET, load_frozenset) 69127db96d56Sopenharmony_ci OP(OBJ, load_obj) 69137db96d56Sopenharmony_ci OP(INST, load_inst) 69147db96d56Sopenharmony_ci OP_ARG(NEWOBJ, load_newobj, 0) 69157db96d56Sopenharmony_ci OP_ARG(NEWOBJ_EX, load_newobj, 1) 69167db96d56Sopenharmony_ci OP(GLOBAL, load_global) 69177db96d56Sopenharmony_ci OP(STACK_GLOBAL, load_stack_global) 69187db96d56Sopenharmony_ci OP(APPEND, load_append) 69197db96d56Sopenharmony_ci OP(APPENDS, load_appends) 69207db96d56Sopenharmony_ci OP(BUILD, load_build) 69217db96d56Sopenharmony_ci OP(DUP, load_dup) 69227db96d56Sopenharmony_ci OP(BINGET, load_binget) 69237db96d56Sopenharmony_ci OP(LONG_BINGET, load_long_binget) 69247db96d56Sopenharmony_ci OP(GET, load_get) 69257db96d56Sopenharmony_ci OP(MARK, load_mark) 69267db96d56Sopenharmony_ci OP(BINPUT, load_binput) 69277db96d56Sopenharmony_ci OP(LONG_BINPUT, load_long_binput) 69287db96d56Sopenharmony_ci OP(PUT, load_put) 69297db96d56Sopenharmony_ci OP(MEMOIZE, load_memoize) 69307db96d56Sopenharmony_ci OP(POP, load_pop) 69317db96d56Sopenharmony_ci OP(POP_MARK, load_pop_mark) 69327db96d56Sopenharmony_ci OP(SETITEM, load_setitem) 69337db96d56Sopenharmony_ci OP(SETITEMS, load_setitems) 69347db96d56Sopenharmony_ci OP(PERSID, load_persid) 69357db96d56Sopenharmony_ci OP(BINPERSID, load_binpersid) 69367db96d56Sopenharmony_ci OP(REDUCE, load_reduce) 69377db96d56Sopenharmony_ci OP(PROTO, load_proto) 69387db96d56Sopenharmony_ci OP(FRAME, load_frame) 69397db96d56Sopenharmony_ci OP_ARG(EXT1, load_extension, 1) 69407db96d56Sopenharmony_ci OP_ARG(EXT2, load_extension, 2) 69417db96d56Sopenharmony_ci OP_ARG(EXT4, load_extension, 4) 69427db96d56Sopenharmony_ci OP_ARG(NEWTRUE, load_bool, Py_True) 69437db96d56Sopenharmony_ci OP_ARG(NEWFALSE, load_bool, Py_False) 69447db96d56Sopenharmony_ci 69457db96d56Sopenharmony_ci case STOP: 69467db96d56Sopenharmony_ci break; 69477db96d56Sopenharmony_ci 69487db96d56Sopenharmony_ci default: 69497db96d56Sopenharmony_ci { 69507db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 69517db96d56Sopenharmony_ci unsigned char c = (unsigned char) *s; 69527db96d56Sopenharmony_ci if (0x20 <= c && c <= 0x7e && c != '\'' && c != '\\') { 69537db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, 69547db96d56Sopenharmony_ci "invalid load key, '%c'.", c); 69557db96d56Sopenharmony_ci } 69567db96d56Sopenharmony_ci else { 69577db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, 69587db96d56Sopenharmony_ci "invalid load key, '\\x%02x'.", c); 69597db96d56Sopenharmony_ci } 69607db96d56Sopenharmony_ci return NULL; 69617db96d56Sopenharmony_ci } 69627db96d56Sopenharmony_ci } 69637db96d56Sopenharmony_ci 69647db96d56Sopenharmony_ci break; /* and we are done! */ 69657db96d56Sopenharmony_ci } 69667db96d56Sopenharmony_ci 69677db96d56Sopenharmony_ci if (PyErr_Occurred()) { 69687db96d56Sopenharmony_ci return NULL; 69697db96d56Sopenharmony_ci } 69707db96d56Sopenharmony_ci 69717db96d56Sopenharmony_ci if (_Unpickler_SkipConsumed(self) < 0) 69727db96d56Sopenharmony_ci return NULL; 69737db96d56Sopenharmony_ci 69747db96d56Sopenharmony_ci PDATA_POP(self->stack, value); 69757db96d56Sopenharmony_ci return value; 69767db96d56Sopenharmony_ci} 69777db96d56Sopenharmony_ci 69787db96d56Sopenharmony_ci/*[clinic input] 69797db96d56Sopenharmony_ci 69807db96d56Sopenharmony_ci_pickle.Unpickler.load 69817db96d56Sopenharmony_ci 69827db96d56Sopenharmony_ciLoad a pickle. 69837db96d56Sopenharmony_ci 69847db96d56Sopenharmony_ciRead a pickled object representation from the open file object given 69857db96d56Sopenharmony_ciin the constructor, and return the reconstituted object hierarchy 69867db96d56Sopenharmony_cispecified therein. 69877db96d56Sopenharmony_ci[clinic start generated code]*/ 69887db96d56Sopenharmony_ci 69897db96d56Sopenharmony_cistatic PyObject * 69907db96d56Sopenharmony_ci_pickle_Unpickler_load_impl(UnpicklerObject *self) 69917db96d56Sopenharmony_ci/*[clinic end generated code: output=fdcc488aad675b14 input=acbb91a42fa9b7b9]*/ 69927db96d56Sopenharmony_ci{ 69937db96d56Sopenharmony_ci UnpicklerObject *unpickler = (UnpicklerObject*)self; 69947db96d56Sopenharmony_ci 69957db96d56Sopenharmony_ci /* Check whether the Unpickler was initialized correctly. This prevents 69967db96d56Sopenharmony_ci segfaulting if a subclass overridden __init__ with a function that does 69977db96d56Sopenharmony_ci not call Unpickler.__init__(). Here, we simply ensure that self->read 69987db96d56Sopenharmony_ci is not NULL. */ 69997db96d56Sopenharmony_ci if (unpickler->read == NULL) { 70007db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 70017db96d56Sopenharmony_ci PyErr_Format(st->UnpicklingError, 70027db96d56Sopenharmony_ci "Unpickler.__init__() was not called by %s.__init__()", 70037db96d56Sopenharmony_ci Py_TYPE(unpickler)->tp_name); 70047db96d56Sopenharmony_ci return NULL; 70057db96d56Sopenharmony_ci } 70067db96d56Sopenharmony_ci 70077db96d56Sopenharmony_ci return load(unpickler); 70087db96d56Sopenharmony_ci} 70097db96d56Sopenharmony_ci 70107db96d56Sopenharmony_ci/* The name of find_class() is misleading. In newer pickle protocols, this 70117db96d56Sopenharmony_ci function is used for loading any global (i.e., functions), not just 70127db96d56Sopenharmony_ci classes. The name is kept only for backward compatibility. */ 70137db96d56Sopenharmony_ci 70147db96d56Sopenharmony_ci/*[clinic input] 70157db96d56Sopenharmony_ci 70167db96d56Sopenharmony_ci_pickle.Unpickler.find_class 70177db96d56Sopenharmony_ci 70187db96d56Sopenharmony_ci module_name: object 70197db96d56Sopenharmony_ci global_name: object 70207db96d56Sopenharmony_ci / 70217db96d56Sopenharmony_ci 70227db96d56Sopenharmony_ciReturn an object from a specified module. 70237db96d56Sopenharmony_ci 70247db96d56Sopenharmony_ciIf necessary, the module will be imported. Subclasses may override 70257db96d56Sopenharmony_cithis method (e.g. to restrict unpickling of arbitrary classes and 70267db96d56Sopenharmony_cifunctions). 70277db96d56Sopenharmony_ci 70287db96d56Sopenharmony_ciThis method is called whenever a class or a function object is 70297db96d56Sopenharmony_cineeded. Both arguments passed are str objects. 70307db96d56Sopenharmony_ci[clinic start generated code]*/ 70317db96d56Sopenharmony_ci 70327db96d56Sopenharmony_cistatic PyObject * 70337db96d56Sopenharmony_ci_pickle_Unpickler_find_class_impl(UnpicklerObject *self, 70347db96d56Sopenharmony_ci PyObject *module_name, 70357db96d56Sopenharmony_ci PyObject *global_name) 70367db96d56Sopenharmony_ci/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/ 70377db96d56Sopenharmony_ci{ 70387db96d56Sopenharmony_ci PyObject *global; 70397db96d56Sopenharmony_ci PyObject *module; 70407db96d56Sopenharmony_ci 70417db96d56Sopenharmony_ci if (PySys_Audit("pickle.find_class", "OO", 70427db96d56Sopenharmony_ci module_name, global_name) < 0) { 70437db96d56Sopenharmony_ci return NULL; 70447db96d56Sopenharmony_ci } 70457db96d56Sopenharmony_ci 70467db96d56Sopenharmony_ci /* Try to map the old names used in Python 2.x to the new ones used in 70477db96d56Sopenharmony_ci Python 3.x. We do this only with old pickle protocols and when the 70487db96d56Sopenharmony_ci user has not disabled the feature. */ 70497db96d56Sopenharmony_ci if (self->proto < 3 && self->fix_imports) { 70507db96d56Sopenharmony_ci PyObject *key; 70517db96d56Sopenharmony_ci PyObject *item; 70527db96d56Sopenharmony_ci PickleState *st = _Pickle_GetGlobalState(); 70537db96d56Sopenharmony_ci 70547db96d56Sopenharmony_ci /* Check if the global (i.e., a function or a class) was renamed 70557db96d56Sopenharmony_ci or moved to another module. */ 70567db96d56Sopenharmony_ci key = PyTuple_Pack(2, module_name, global_name); 70577db96d56Sopenharmony_ci if (key == NULL) 70587db96d56Sopenharmony_ci return NULL; 70597db96d56Sopenharmony_ci item = PyDict_GetItemWithError(st->name_mapping_2to3, key); 70607db96d56Sopenharmony_ci Py_DECREF(key); 70617db96d56Sopenharmony_ci if (item) { 70627db96d56Sopenharmony_ci if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) { 70637db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 70647db96d56Sopenharmony_ci "_compat_pickle.NAME_MAPPING values should be " 70657db96d56Sopenharmony_ci "2-tuples, not %.200s", Py_TYPE(item)->tp_name); 70667db96d56Sopenharmony_ci return NULL; 70677db96d56Sopenharmony_ci } 70687db96d56Sopenharmony_ci module_name = PyTuple_GET_ITEM(item, 0); 70697db96d56Sopenharmony_ci global_name = PyTuple_GET_ITEM(item, 1); 70707db96d56Sopenharmony_ci if (!PyUnicode_Check(module_name) || 70717db96d56Sopenharmony_ci !PyUnicode_Check(global_name)) { 70727db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 70737db96d56Sopenharmony_ci "_compat_pickle.NAME_MAPPING values should be " 70747db96d56Sopenharmony_ci "pairs of str, not (%.200s, %.200s)", 70757db96d56Sopenharmony_ci Py_TYPE(module_name)->tp_name, 70767db96d56Sopenharmony_ci Py_TYPE(global_name)->tp_name); 70777db96d56Sopenharmony_ci return NULL; 70787db96d56Sopenharmony_ci } 70797db96d56Sopenharmony_ci } 70807db96d56Sopenharmony_ci else if (PyErr_Occurred()) { 70817db96d56Sopenharmony_ci return NULL; 70827db96d56Sopenharmony_ci } 70837db96d56Sopenharmony_ci else { 70847db96d56Sopenharmony_ci /* Check if the module was renamed. */ 70857db96d56Sopenharmony_ci item = PyDict_GetItemWithError(st->import_mapping_2to3, module_name); 70867db96d56Sopenharmony_ci if (item) { 70877db96d56Sopenharmony_ci if (!PyUnicode_Check(item)) { 70887db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, 70897db96d56Sopenharmony_ci "_compat_pickle.IMPORT_MAPPING values should be " 70907db96d56Sopenharmony_ci "strings, not %.200s", Py_TYPE(item)->tp_name); 70917db96d56Sopenharmony_ci return NULL; 70927db96d56Sopenharmony_ci } 70937db96d56Sopenharmony_ci module_name = item; 70947db96d56Sopenharmony_ci } 70957db96d56Sopenharmony_ci else if (PyErr_Occurred()) { 70967db96d56Sopenharmony_ci return NULL; 70977db96d56Sopenharmony_ci } 70987db96d56Sopenharmony_ci } 70997db96d56Sopenharmony_ci } 71007db96d56Sopenharmony_ci 71017db96d56Sopenharmony_ci /* 71027db96d56Sopenharmony_ci * we don't use PyImport_GetModule here, because it can return partially- 71037db96d56Sopenharmony_ci * initialised modules, which then cause the getattribute to fail. 71047db96d56Sopenharmony_ci */ 71057db96d56Sopenharmony_ci module = PyImport_Import(module_name); 71067db96d56Sopenharmony_ci if (module == NULL) { 71077db96d56Sopenharmony_ci return NULL; 71087db96d56Sopenharmony_ci } 71097db96d56Sopenharmony_ci global = getattribute(module, global_name, self->proto >= 4); 71107db96d56Sopenharmony_ci Py_DECREF(module); 71117db96d56Sopenharmony_ci return global; 71127db96d56Sopenharmony_ci} 71137db96d56Sopenharmony_ci 71147db96d56Sopenharmony_ci/*[clinic input] 71157db96d56Sopenharmony_ci 71167db96d56Sopenharmony_ci_pickle.Unpickler.__sizeof__ -> Py_ssize_t 71177db96d56Sopenharmony_ci 71187db96d56Sopenharmony_ciReturns size in memory, in bytes. 71197db96d56Sopenharmony_ci[clinic start generated code]*/ 71207db96d56Sopenharmony_ci 71217db96d56Sopenharmony_cistatic Py_ssize_t 71227db96d56Sopenharmony_ci_pickle_Unpickler___sizeof___impl(UnpicklerObject *self) 71237db96d56Sopenharmony_ci/*[clinic end generated code: output=119d9d03ad4c7651 input=13333471fdeedf5e]*/ 71247db96d56Sopenharmony_ci{ 71257db96d56Sopenharmony_ci Py_ssize_t res; 71267db96d56Sopenharmony_ci 71277db96d56Sopenharmony_ci res = _PyObject_SIZE(Py_TYPE(self)); 71287db96d56Sopenharmony_ci if (self->memo != NULL) 71297db96d56Sopenharmony_ci res += self->memo_size * sizeof(PyObject *); 71307db96d56Sopenharmony_ci if (self->marks != NULL) 71317db96d56Sopenharmony_ci res += self->marks_size * sizeof(Py_ssize_t); 71327db96d56Sopenharmony_ci if (self->input_line != NULL) 71337db96d56Sopenharmony_ci res += strlen(self->input_line) + 1; 71347db96d56Sopenharmony_ci if (self->encoding != NULL) 71357db96d56Sopenharmony_ci res += strlen(self->encoding) + 1; 71367db96d56Sopenharmony_ci if (self->errors != NULL) 71377db96d56Sopenharmony_ci res += strlen(self->errors) + 1; 71387db96d56Sopenharmony_ci return res; 71397db96d56Sopenharmony_ci} 71407db96d56Sopenharmony_ci 71417db96d56Sopenharmony_cistatic struct PyMethodDef Unpickler_methods[] = { 71427db96d56Sopenharmony_ci _PICKLE_UNPICKLER_LOAD_METHODDEF 71437db96d56Sopenharmony_ci _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF 71447db96d56Sopenharmony_ci _PICKLE_UNPICKLER___SIZEOF___METHODDEF 71457db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 71467db96d56Sopenharmony_ci}; 71477db96d56Sopenharmony_ci 71487db96d56Sopenharmony_cistatic void 71497db96d56Sopenharmony_ciUnpickler_dealloc(UnpicklerObject *self) 71507db96d56Sopenharmony_ci{ 71517db96d56Sopenharmony_ci PyObject_GC_UnTrack((PyObject *)self); 71527db96d56Sopenharmony_ci Py_XDECREF(self->readline); 71537db96d56Sopenharmony_ci Py_XDECREF(self->readinto); 71547db96d56Sopenharmony_ci Py_XDECREF(self->read); 71557db96d56Sopenharmony_ci Py_XDECREF(self->peek); 71567db96d56Sopenharmony_ci Py_XDECREF(self->stack); 71577db96d56Sopenharmony_ci Py_XDECREF(self->pers_func); 71587db96d56Sopenharmony_ci Py_XDECREF(self->buffers); 71597db96d56Sopenharmony_ci if (self->buffer.buf != NULL) { 71607db96d56Sopenharmony_ci PyBuffer_Release(&self->buffer); 71617db96d56Sopenharmony_ci self->buffer.buf = NULL; 71627db96d56Sopenharmony_ci } 71637db96d56Sopenharmony_ci 71647db96d56Sopenharmony_ci _Unpickler_MemoCleanup(self); 71657db96d56Sopenharmony_ci PyMem_Free(self->marks); 71667db96d56Sopenharmony_ci PyMem_Free(self->input_line); 71677db96d56Sopenharmony_ci PyMem_Free(self->encoding); 71687db96d56Sopenharmony_ci PyMem_Free(self->errors); 71697db96d56Sopenharmony_ci 71707db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject *)self); 71717db96d56Sopenharmony_ci} 71727db96d56Sopenharmony_ci 71737db96d56Sopenharmony_cistatic int 71747db96d56Sopenharmony_ciUnpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg) 71757db96d56Sopenharmony_ci{ 71767db96d56Sopenharmony_ci Py_VISIT(self->readline); 71777db96d56Sopenharmony_ci Py_VISIT(self->readinto); 71787db96d56Sopenharmony_ci Py_VISIT(self->read); 71797db96d56Sopenharmony_ci Py_VISIT(self->peek); 71807db96d56Sopenharmony_ci Py_VISIT(self->stack); 71817db96d56Sopenharmony_ci Py_VISIT(self->pers_func); 71827db96d56Sopenharmony_ci Py_VISIT(self->buffers); 71837db96d56Sopenharmony_ci return 0; 71847db96d56Sopenharmony_ci} 71857db96d56Sopenharmony_ci 71867db96d56Sopenharmony_cistatic int 71877db96d56Sopenharmony_ciUnpickler_clear(UnpicklerObject *self) 71887db96d56Sopenharmony_ci{ 71897db96d56Sopenharmony_ci Py_CLEAR(self->readline); 71907db96d56Sopenharmony_ci Py_CLEAR(self->readinto); 71917db96d56Sopenharmony_ci Py_CLEAR(self->read); 71927db96d56Sopenharmony_ci Py_CLEAR(self->peek); 71937db96d56Sopenharmony_ci Py_CLEAR(self->stack); 71947db96d56Sopenharmony_ci Py_CLEAR(self->pers_func); 71957db96d56Sopenharmony_ci Py_CLEAR(self->buffers); 71967db96d56Sopenharmony_ci if (self->buffer.buf != NULL) { 71977db96d56Sopenharmony_ci PyBuffer_Release(&self->buffer); 71987db96d56Sopenharmony_ci self->buffer.buf = NULL; 71997db96d56Sopenharmony_ci } 72007db96d56Sopenharmony_ci 72017db96d56Sopenharmony_ci _Unpickler_MemoCleanup(self); 72027db96d56Sopenharmony_ci PyMem_Free(self->marks); 72037db96d56Sopenharmony_ci self->marks = NULL; 72047db96d56Sopenharmony_ci PyMem_Free(self->input_line); 72057db96d56Sopenharmony_ci self->input_line = NULL; 72067db96d56Sopenharmony_ci PyMem_Free(self->encoding); 72077db96d56Sopenharmony_ci self->encoding = NULL; 72087db96d56Sopenharmony_ci PyMem_Free(self->errors); 72097db96d56Sopenharmony_ci self->errors = NULL; 72107db96d56Sopenharmony_ci 72117db96d56Sopenharmony_ci return 0; 72127db96d56Sopenharmony_ci} 72137db96d56Sopenharmony_ci 72147db96d56Sopenharmony_ci/*[clinic input] 72157db96d56Sopenharmony_ci 72167db96d56Sopenharmony_ci_pickle.Unpickler.__init__ 72177db96d56Sopenharmony_ci 72187db96d56Sopenharmony_ci file: object 72197db96d56Sopenharmony_ci * 72207db96d56Sopenharmony_ci fix_imports: bool = True 72217db96d56Sopenharmony_ci encoding: str = 'ASCII' 72227db96d56Sopenharmony_ci errors: str = 'strict' 72237db96d56Sopenharmony_ci buffers: object(c_default="NULL") = () 72247db96d56Sopenharmony_ci 72257db96d56Sopenharmony_ciThis takes a binary file for reading a pickle data stream. 72267db96d56Sopenharmony_ci 72277db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no 72287db96d56Sopenharmony_ciprotocol argument is needed. Bytes past the pickled object's 72297db96d56Sopenharmony_cirepresentation are ignored. 72307db96d56Sopenharmony_ci 72317db96d56Sopenharmony_ciThe argument *file* must have two methods, a read() method that takes 72327db96d56Sopenharmony_cian integer argument, and a readline() method that requires no 72337db96d56Sopenharmony_ciarguments. Both methods should return bytes. Thus *file* can be a 72347db96d56Sopenharmony_cibinary file object opened for reading, an io.BytesIO object, or any 72357db96d56Sopenharmony_ciother custom object that meets this interface. 72367db96d56Sopenharmony_ci 72377db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*, 72387db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream 72397db96d56Sopenharmony_cigenerated by Python 2. If *fix_imports* is True, pickle will try to 72407db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3. The 72417db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string 72427db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict', 72437db96d56Sopenharmony_cirespectively. The *encoding* can be 'bytes' to read these 8-bit 72447db96d56Sopenharmony_cistring instances as bytes objects. 72457db96d56Sopenharmony_ci[clinic start generated code]*/ 72467db96d56Sopenharmony_ci 72477db96d56Sopenharmony_cistatic int 72487db96d56Sopenharmony_ci_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, 72497db96d56Sopenharmony_ci int fix_imports, const char *encoding, 72507db96d56Sopenharmony_ci const char *errors, PyObject *buffers) 72517db96d56Sopenharmony_ci/*[clinic end generated code: output=09f0192649ea3f85 input=ca4c1faea9553121]*/ 72527db96d56Sopenharmony_ci{ 72537db96d56Sopenharmony_ci /* In case of multiple __init__() calls, clear previous content. */ 72547db96d56Sopenharmony_ci if (self->read != NULL) 72557db96d56Sopenharmony_ci (void)Unpickler_clear(self); 72567db96d56Sopenharmony_ci 72577db96d56Sopenharmony_ci if (_Unpickler_SetInputStream(self, file) < 0) 72587db96d56Sopenharmony_ci return -1; 72597db96d56Sopenharmony_ci 72607db96d56Sopenharmony_ci if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0) 72617db96d56Sopenharmony_ci return -1; 72627db96d56Sopenharmony_ci 72637db96d56Sopenharmony_ci if (_Unpickler_SetBuffers(self, buffers) < 0) 72647db96d56Sopenharmony_ci return -1; 72657db96d56Sopenharmony_ci 72667db96d56Sopenharmony_ci self->fix_imports = fix_imports; 72677db96d56Sopenharmony_ci 72687db96d56Sopenharmony_ci if (init_method_ref((PyObject *)self, &_Py_ID(persistent_load), 72697db96d56Sopenharmony_ci &self->pers_func, &self->pers_func_self) < 0) 72707db96d56Sopenharmony_ci { 72717db96d56Sopenharmony_ci return -1; 72727db96d56Sopenharmony_ci } 72737db96d56Sopenharmony_ci 72747db96d56Sopenharmony_ci self->stack = (Pdata *)Pdata_New(); 72757db96d56Sopenharmony_ci if (self->stack == NULL) 72767db96d56Sopenharmony_ci return -1; 72777db96d56Sopenharmony_ci 72787db96d56Sopenharmony_ci self->memo_size = 32; 72797db96d56Sopenharmony_ci self->memo = _Unpickler_NewMemo(self->memo_size); 72807db96d56Sopenharmony_ci if (self->memo == NULL) 72817db96d56Sopenharmony_ci return -1; 72827db96d56Sopenharmony_ci 72837db96d56Sopenharmony_ci self->proto = 0; 72847db96d56Sopenharmony_ci 72857db96d56Sopenharmony_ci return 0; 72867db96d56Sopenharmony_ci} 72877db96d56Sopenharmony_ci 72887db96d56Sopenharmony_ci 72897db96d56Sopenharmony_ci/* Define a proxy object for the Unpickler's internal memo object. This is to 72907db96d56Sopenharmony_ci * avoid breaking code like: 72917db96d56Sopenharmony_ci * unpickler.memo.clear() 72927db96d56Sopenharmony_ci * and 72937db96d56Sopenharmony_ci * unpickler.memo = saved_memo 72947db96d56Sopenharmony_ci * Is this a good idea? Not really, but we don't want to break code that uses 72957db96d56Sopenharmony_ci * it. Note that we don't implement the entire mapping API here. This is 72967db96d56Sopenharmony_ci * intentional, as these should be treated as black-box implementation details. 72977db96d56Sopenharmony_ci * 72987db96d56Sopenharmony_ci * We do, however, have to implement pickling/unpickling support because of 72997db96d56Sopenharmony_ci * real-world code like cvs2svn. 73007db96d56Sopenharmony_ci */ 73017db96d56Sopenharmony_ci 73027db96d56Sopenharmony_ci/*[clinic input] 73037db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.clear 73047db96d56Sopenharmony_ci 73057db96d56Sopenharmony_ciRemove all items from memo. 73067db96d56Sopenharmony_ci[clinic start generated code]*/ 73077db96d56Sopenharmony_ci 73087db96d56Sopenharmony_cistatic PyObject * 73097db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self) 73107db96d56Sopenharmony_ci/*[clinic end generated code: output=d20cd43f4ba1fb1f input=b1df7c52e7afd9bd]*/ 73117db96d56Sopenharmony_ci{ 73127db96d56Sopenharmony_ci _Unpickler_MemoCleanup(self->unpickler); 73137db96d56Sopenharmony_ci self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size); 73147db96d56Sopenharmony_ci if (self->unpickler->memo == NULL) 73157db96d56Sopenharmony_ci return NULL; 73167db96d56Sopenharmony_ci Py_RETURN_NONE; 73177db96d56Sopenharmony_ci} 73187db96d56Sopenharmony_ci 73197db96d56Sopenharmony_ci/*[clinic input] 73207db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.copy 73217db96d56Sopenharmony_ci 73227db96d56Sopenharmony_ciCopy the memo to a new object. 73237db96d56Sopenharmony_ci[clinic start generated code]*/ 73247db96d56Sopenharmony_ci 73257db96d56Sopenharmony_cistatic PyObject * 73267db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self) 73277db96d56Sopenharmony_ci/*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/ 73287db96d56Sopenharmony_ci{ 73297db96d56Sopenharmony_ci size_t i; 73307db96d56Sopenharmony_ci PyObject *new_memo = PyDict_New(); 73317db96d56Sopenharmony_ci if (new_memo == NULL) 73327db96d56Sopenharmony_ci return NULL; 73337db96d56Sopenharmony_ci 73347db96d56Sopenharmony_ci for (i = 0; i < self->unpickler->memo_size; i++) { 73357db96d56Sopenharmony_ci int status; 73367db96d56Sopenharmony_ci PyObject *key, *value; 73377db96d56Sopenharmony_ci 73387db96d56Sopenharmony_ci value = self->unpickler->memo[i]; 73397db96d56Sopenharmony_ci if (value == NULL) 73407db96d56Sopenharmony_ci continue; 73417db96d56Sopenharmony_ci 73427db96d56Sopenharmony_ci key = PyLong_FromSsize_t(i); 73437db96d56Sopenharmony_ci if (key == NULL) 73447db96d56Sopenharmony_ci goto error; 73457db96d56Sopenharmony_ci status = PyDict_SetItem(new_memo, key, value); 73467db96d56Sopenharmony_ci Py_DECREF(key); 73477db96d56Sopenharmony_ci if (status < 0) 73487db96d56Sopenharmony_ci goto error; 73497db96d56Sopenharmony_ci } 73507db96d56Sopenharmony_ci return new_memo; 73517db96d56Sopenharmony_ci 73527db96d56Sopenharmony_cierror: 73537db96d56Sopenharmony_ci Py_DECREF(new_memo); 73547db96d56Sopenharmony_ci return NULL; 73557db96d56Sopenharmony_ci} 73567db96d56Sopenharmony_ci 73577db96d56Sopenharmony_ci/*[clinic input] 73587db96d56Sopenharmony_ci_pickle.UnpicklerMemoProxy.__reduce__ 73597db96d56Sopenharmony_ci 73607db96d56Sopenharmony_ciImplement pickling support. 73617db96d56Sopenharmony_ci[clinic start generated code]*/ 73627db96d56Sopenharmony_ci 73637db96d56Sopenharmony_cistatic PyObject * 73647db96d56Sopenharmony_ci_pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self) 73657db96d56Sopenharmony_ci/*[clinic end generated code: output=6da34ac048d94cca input=6920862413407199]*/ 73667db96d56Sopenharmony_ci{ 73677db96d56Sopenharmony_ci PyObject *reduce_value; 73687db96d56Sopenharmony_ci PyObject *constructor_args; 73697db96d56Sopenharmony_ci PyObject *contents = _pickle_UnpicklerMemoProxy_copy_impl(self); 73707db96d56Sopenharmony_ci if (contents == NULL) 73717db96d56Sopenharmony_ci return NULL; 73727db96d56Sopenharmony_ci 73737db96d56Sopenharmony_ci reduce_value = PyTuple_New(2); 73747db96d56Sopenharmony_ci if (reduce_value == NULL) { 73757db96d56Sopenharmony_ci Py_DECREF(contents); 73767db96d56Sopenharmony_ci return NULL; 73777db96d56Sopenharmony_ci } 73787db96d56Sopenharmony_ci constructor_args = PyTuple_New(1); 73797db96d56Sopenharmony_ci if (constructor_args == NULL) { 73807db96d56Sopenharmony_ci Py_DECREF(contents); 73817db96d56Sopenharmony_ci Py_DECREF(reduce_value); 73827db96d56Sopenharmony_ci return NULL; 73837db96d56Sopenharmony_ci } 73847db96d56Sopenharmony_ci PyTuple_SET_ITEM(constructor_args, 0, contents); 73857db96d56Sopenharmony_ci Py_INCREF((PyObject *)&PyDict_Type); 73867db96d56Sopenharmony_ci PyTuple_SET_ITEM(reduce_value, 0, (PyObject *)&PyDict_Type); 73877db96d56Sopenharmony_ci PyTuple_SET_ITEM(reduce_value, 1, constructor_args); 73887db96d56Sopenharmony_ci return reduce_value; 73897db96d56Sopenharmony_ci} 73907db96d56Sopenharmony_ci 73917db96d56Sopenharmony_cistatic PyMethodDef unpicklerproxy_methods[] = { 73927db96d56Sopenharmony_ci _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF 73937db96d56Sopenharmony_ci _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF 73947db96d56Sopenharmony_ci _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF 73957db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 73967db96d56Sopenharmony_ci}; 73977db96d56Sopenharmony_ci 73987db96d56Sopenharmony_cistatic void 73997db96d56Sopenharmony_ciUnpicklerMemoProxy_dealloc(UnpicklerMemoProxyObject *self) 74007db96d56Sopenharmony_ci{ 74017db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 74027db96d56Sopenharmony_ci Py_XDECREF(self->unpickler); 74037db96d56Sopenharmony_ci PyObject_GC_Del((PyObject *)self); 74047db96d56Sopenharmony_ci} 74057db96d56Sopenharmony_ci 74067db96d56Sopenharmony_cistatic int 74077db96d56Sopenharmony_ciUnpicklerMemoProxy_traverse(UnpicklerMemoProxyObject *self, 74087db96d56Sopenharmony_ci visitproc visit, void *arg) 74097db96d56Sopenharmony_ci{ 74107db96d56Sopenharmony_ci Py_VISIT(self->unpickler); 74117db96d56Sopenharmony_ci return 0; 74127db96d56Sopenharmony_ci} 74137db96d56Sopenharmony_ci 74147db96d56Sopenharmony_cistatic int 74157db96d56Sopenharmony_ciUnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self) 74167db96d56Sopenharmony_ci{ 74177db96d56Sopenharmony_ci Py_CLEAR(self->unpickler); 74187db96d56Sopenharmony_ci return 0; 74197db96d56Sopenharmony_ci} 74207db96d56Sopenharmony_ci 74217db96d56Sopenharmony_cistatic PyTypeObject UnpicklerMemoProxyType = { 74227db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 74237db96d56Sopenharmony_ci "_pickle.UnpicklerMemoProxy", /*tp_name*/ 74247db96d56Sopenharmony_ci sizeof(UnpicklerMemoProxyObject), /*tp_basicsize*/ 74257db96d56Sopenharmony_ci 0, 74267db96d56Sopenharmony_ci (destructor)UnpicklerMemoProxy_dealloc, /* tp_dealloc */ 74277db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 74287db96d56Sopenharmony_ci 0, /* tp_getattr */ 74297db96d56Sopenharmony_ci 0, /* tp_setattr */ 74307db96d56Sopenharmony_ci 0, /* tp_as_async */ 74317db96d56Sopenharmony_ci 0, /* tp_repr */ 74327db96d56Sopenharmony_ci 0, /* tp_as_number */ 74337db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 74347db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 74357db96d56Sopenharmony_ci PyObject_HashNotImplemented, /* tp_hash */ 74367db96d56Sopenharmony_ci 0, /* tp_call */ 74377db96d56Sopenharmony_ci 0, /* tp_str */ 74387db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 74397db96d56Sopenharmony_ci PyObject_GenericSetAttr, /* tp_setattro */ 74407db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 74417db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 74427db96d56Sopenharmony_ci 0, /* tp_doc */ 74437db96d56Sopenharmony_ci (traverseproc)UnpicklerMemoProxy_traverse, /* tp_traverse */ 74447db96d56Sopenharmony_ci (inquiry)UnpicklerMemoProxy_clear, /* tp_clear */ 74457db96d56Sopenharmony_ci 0, /* tp_richcompare */ 74467db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 74477db96d56Sopenharmony_ci 0, /* tp_iter */ 74487db96d56Sopenharmony_ci 0, /* tp_iternext */ 74497db96d56Sopenharmony_ci unpicklerproxy_methods, /* tp_methods */ 74507db96d56Sopenharmony_ci}; 74517db96d56Sopenharmony_ci 74527db96d56Sopenharmony_cistatic PyObject * 74537db96d56Sopenharmony_ciUnpicklerMemoProxy_New(UnpicklerObject *unpickler) 74547db96d56Sopenharmony_ci{ 74557db96d56Sopenharmony_ci UnpicklerMemoProxyObject *self; 74567db96d56Sopenharmony_ci 74577db96d56Sopenharmony_ci self = PyObject_GC_New(UnpicklerMemoProxyObject, 74587db96d56Sopenharmony_ci &UnpicklerMemoProxyType); 74597db96d56Sopenharmony_ci if (self == NULL) 74607db96d56Sopenharmony_ci return NULL; 74617db96d56Sopenharmony_ci Py_INCREF(unpickler); 74627db96d56Sopenharmony_ci self->unpickler = unpickler; 74637db96d56Sopenharmony_ci PyObject_GC_Track(self); 74647db96d56Sopenharmony_ci return (PyObject *)self; 74657db96d56Sopenharmony_ci} 74667db96d56Sopenharmony_ci 74677db96d56Sopenharmony_ci/*****************************************************************************/ 74687db96d56Sopenharmony_ci 74697db96d56Sopenharmony_ci 74707db96d56Sopenharmony_cistatic PyObject * 74717db96d56Sopenharmony_ciUnpickler_get_memo(UnpicklerObject *self, void *Py_UNUSED(ignored)) 74727db96d56Sopenharmony_ci{ 74737db96d56Sopenharmony_ci return UnpicklerMemoProxy_New(self); 74747db96d56Sopenharmony_ci} 74757db96d56Sopenharmony_ci 74767db96d56Sopenharmony_cistatic int 74777db96d56Sopenharmony_ciUnpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored)) 74787db96d56Sopenharmony_ci{ 74797db96d56Sopenharmony_ci PyObject **new_memo; 74807db96d56Sopenharmony_ci size_t new_memo_size = 0; 74817db96d56Sopenharmony_ci 74827db96d56Sopenharmony_ci if (obj == NULL) { 74837db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 74847db96d56Sopenharmony_ci "attribute deletion is not supported"); 74857db96d56Sopenharmony_ci return -1; 74867db96d56Sopenharmony_ci } 74877db96d56Sopenharmony_ci 74887db96d56Sopenharmony_ci if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) { 74897db96d56Sopenharmony_ci UnpicklerObject *unpickler = 74907db96d56Sopenharmony_ci ((UnpicklerMemoProxyObject *)obj)->unpickler; 74917db96d56Sopenharmony_ci 74927db96d56Sopenharmony_ci new_memo_size = unpickler->memo_size; 74937db96d56Sopenharmony_ci new_memo = _Unpickler_NewMemo(new_memo_size); 74947db96d56Sopenharmony_ci if (new_memo == NULL) 74957db96d56Sopenharmony_ci return -1; 74967db96d56Sopenharmony_ci 74977db96d56Sopenharmony_ci for (size_t i = 0; i < new_memo_size; i++) { 74987db96d56Sopenharmony_ci Py_XINCREF(unpickler->memo[i]); 74997db96d56Sopenharmony_ci new_memo[i] = unpickler->memo[i]; 75007db96d56Sopenharmony_ci } 75017db96d56Sopenharmony_ci } 75027db96d56Sopenharmony_ci else if (PyDict_Check(obj)) { 75037db96d56Sopenharmony_ci Py_ssize_t i = 0; 75047db96d56Sopenharmony_ci PyObject *key, *value; 75057db96d56Sopenharmony_ci 75067db96d56Sopenharmony_ci new_memo_size = PyDict_GET_SIZE(obj); 75077db96d56Sopenharmony_ci new_memo = _Unpickler_NewMemo(new_memo_size); 75087db96d56Sopenharmony_ci if (new_memo == NULL) 75097db96d56Sopenharmony_ci return -1; 75107db96d56Sopenharmony_ci 75117db96d56Sopenharmony_ci while (PyDict_Next(obj, &i, &key, &value)) { 75127db96d56Sopenharmony_ci Py_ssize_t idx; 75137db96d56Sopenharmony_ci if (!PyLong_Check(key)) { 75147db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 75157db96d56Sopenharmony_ci "memo key must be integers"); 75167db96d56Sopenharmony_ci goto error; 75177db96d56Sopenharmony_ci } 75187db96d56Sopenharmony_ci idx = PyLong_AsSsize_t(key); 75197db96d56Sopenharmony_ci if (idx == -1 && PyErr_Occurred()) 75207db96d56Sopenharmony_ci goto error; 75217db96d56Sopenharmony_ci if (idx < 0) { 75227db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 75237db96d56Sopenharmony_ci "memo key must be positive integers."); 75247db96d56Sopenharmony_ci goto error; 75257db96d56Sopenharmony_ci } 75267db96d56Sopenharmony_ci if (_Unpickler_MemoPut(self, idx, value) < 0) 75277db96d56Sopenharmony_ci goto error; 75287db96d56Sopenharmony_ci } 75297db96d56Sopenharmony_ci } 75307db96d56Sopenharmony_ci else { 75317db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 75327db96d56Sopenharmony_ci "'memo' attribute must be an UnpicklerMemoProxy object " 75337db96d56Sopenharmony_ci "or dict, not %.200s", Py_TYPE(obj)->tp_name); 75347db96d56Sopenharmony_ci return -1; 75357db96d56Sopenharmony_ci } 75367db96d56Sopenharmony_ci 75377db96d56Sopenharmony_ci _Unpickler_MemoCleanup(self); 75387db96d56Sopenharmony_ci self->memo_size = new_memo_size; 75397db96d56Sopenharmony_ci self->memo = new_memo; 75407db96d56Sopenharmony_ci 75417db96d56Sopenharmony_ci return 0; 75427db96d56Sopenharmony_ci 75437db96d56Sopenharmony_ci error: 75447db96d56Sopenharmony_ci if (new_memo_size) { 75457db96d56Sopenharmony_ci for (size_t i = new_memo_size - 1; i != SIZE_MAX; i--) { 75467db96d56Sopenharmony_ci Py_XDECREF(new_memo[i]); 75477db96d56Sopenharmony_ci } 75487db96d56Sopenharmony_ci PyMem_Free(new_memo); 75497db96d56Sopenharmony_ci } 75507db96d56Sopenharmony_ci return -1; 75517db96d56Sopenharmony_ci} 75527db96d56Sopenharmony_ci 75537db96d56Sopenharmony_cistatic PyObject * 75547db96d56Sopenharmony_ciUnpickler_get_persload(UnpicklerObject *self, void *Py_UNUSED(ignored)) 75557db96d56Sopenharmony_ci{ 75567db96d56Sopenharmony_ci if (self->pers_func == NULL) { 75577db96d56Sopenharmony_ci PyErr_SetString(PyExc_AttributeError, "persistent_load"); 75587db96d56Sopenharmony_ci return NULL; 75597db96d56Sopenharmony_ci } 75607db96d56Sopenharmony_ci return reconstruct_method(self->pers_func, self->pers_func_self); 75617db96d56Sopenharmony_ci} 75627db96d56Sopenharmony_ci 75637db96d56Sopenharmony_cistatic int 75647db96d56Sopenharmony_ciUnpickler_set_persload(UnpicklerObject *self, PyObject *value, void *Py_UNUSED(ignored)) 75657db96d56Sopenharmony_ci{ 75667db96d56Sopenharmony_ci if (value == NULL) { 75677db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 75687db96d56Sopenharmony_ci "attribute deletion is not supported"); 75697db96d56Sopenharmony_ci return -1; 75707db96d56Sopenharmony_ci } 75717db96d56Sopenharmony_ci if (!PyCallable_Check(value)) { 75727db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 75737db96d56Sopenharmony_ci "persistent_load must be a callable taking " 75747db96d56Sopenharmony_ci "one argument"); 75757db96d56Sopenharmony_ci return -1; 75767db96d56Sopenharmony_ci } 75777db96d56Sopenharmony_ci 75787db96d56Sopenharmony_ci self->pers_func_self = NULL; 75797db96d56Sopenharmony_ci Py_INCREF(value); 75807db96d56Sopenharmony_ci Py_XSETREF(self->pers_func, value); 75817db96d56Sopenharmony_ci 75827db96d56Sopenharmony_ci return 0; 75837db96d56Sopenharmony_ci} 75847db96d56Sopenharmony_ci 75857db96d56Sopenharmony_cistatic PyGetSetDef Unpickler_getsets[] = { 75867db96d56Sopenharmony_ci {"memo", (getter)Unpickler_get_memo, (setter)Unpickler_set_memo}, 75877db96d56Sopenharmony_ci {"persistent_load", (getter)Unpickler_get_persload, 75887db96d56Sopenharmony_ci (setter)Unpickler_set_persload}, 75897db96d56Sopenharmony_ci {NULL} 75907db96d56Sopenharmony_ci}; 75917db96d56Sopenharmony_ci 75927db96d56Sopenharmony_cistatic PyTypeObject Unpickler_Type = { 75937db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 75947db96d56Sopenharmony_ci "_pickle.Unpickler", /*tp_name*/ 75957db96d56Sopenharmony_ci sizeof(UnpicklerObject), /*tp_basicsize*/ 75967db96d56Sopenharmony_ci 0, /*tp_itemsize*/ 75977db96d56Sopenharmony_ci (destructor)Unpickler_dealloc, /*tp_dealloc*/ 75987db96d56Sopenharmony_ci 0, /*tp_vectorcall_offset*/ 75997db96d56Sopenharmony_ci 0, /*tp_getattr*/ 76007db96d56Sopenharmony_ci 0, /*tp_setattr*/ 76017db96d56Sopenharmony_ci 0, /*tp_as_async*/ 76027db96d56Sopenharmony_ci 0, /*tp_repr*/ 76037db96d56Sopenharmony_ci 0, /*tp_as_number*/ 76047db96d56Sopenharmony_ci 0, /*tp_as_sequence*/ 76057db96d56Sopenharmony_ci 0, /*tp_as_mapping*/ 76067db96d56Sopenharmony_ci 0, /*tp_hash*/ 76077db96d56Sopenharmony_ci 0, /*tp_call*/ 76087db96d56Sopenharmony_ci 0, /*tp_str*/ 76097db96d56Sopenharmony_ci 0, /*tp_getattro*/ 76107db96d56Sopenharmony_ci 0, /*tp_setattro*/ 76117db96d56Sopenharmony_ci 0, /*tp_as_buffer*/ 76127db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 76137db96d56Sopenharmony_ci _pickle_Unpickler___init____doc__, /*tp_doc*/ 76147db96d56Sopenharmony_ci (traverseproc)Unpickler_traverse, /*tp_traverse*/ 76157db96d56Sopenharmony_ci (inquiry)Unpickler_clear, /*tp_clear*/ 76167db96d56Sopenharmony_ci 0, /*tp_richcompare*/ 76177db96d56Sopenharmony_ci 0, /*tp_weaklistoffset*/ 76187db96d56Sopenharmony_ci 0, /*tp_iter*/ 76197db96d56Sopenharmony_ci 0, /*tp_iternext*/ 76207db96d56Sopenharmony_ci Unpickler_methods, /*tp_methods*/ 76217db96d56Sopenharmony_ci 0, /*tp_members*/ 76227db96d56Sopenharmony_ci Unpickler_getsets, /*tp_getset*/ 76237db96d56Sopenharmony_ci 0, /*tp_base*/ 76247db96d56Sopenharmony_ci 0, /*tp_dict*/ 76257db96d56Sopenharmony_ci 0, /*tp_descr_get*/ 76267db96d56Sopenharmony_ci 0, /*tp_descr_set*/ 76277db96d56Sopenharmony_ci 0, /*tp_dictoffset*/ 76287db96d56Sopenharmony_ci _pickle_Unpickler___init__, /*tp_init*/ 76297db96d56Sopenharmony_ci PyType_GenericAlloc, /*tp_alloc*/ 76307db96d56Sopenharmony_ci PyType_GenericNew, /*tp_new*/ 76317db96d56Sopenharmony_ci PyObject_GC_Del, /*tp_free*/ 76327db96d56Sopenharmony_ci 0, /*tp_is_gc*/ 76337db96d56Sopenharmony_ci}; 76347db96d56Sopenharmony_ci 76357db96d56Sopenharmony_ci/*[clinic input] 76367db96d56Sopenharmony_ci 76377db96d56Sopenharmony_ci_pickle.dump 76387db96d56Sopenharmony_ci 76397db96d56Sopenharmony_ci obj: object 76407db96d56Sopenharmony_ci file: object 76417db96d56Sopenharmony_ci protocol: object = None 76427db96d56Sopenharmony_ci * 76437db96d56Sopenharmony_ci fix_imports: bool = True 76447db96d56Sopenharmony_ci buffer_callback: object = None 76457db96d56Sopenharmony_ci 76467db96d56Sopenharmony_ciWrite a pickled representation of obj to the open file object file. 76477db96d56Sopenharmony_ci 76487db96d56Sopenharmony_ciThis is equivalent to ``Pickler(file, protocol).dump(obj)``, but may 76497db96d56Sopenharmony_cibe more efficient. 76507db96d56Sopenharmony_ci 76517db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given 76527db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5. The default 76537db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible 76547db96d56Sopenharmony_ciwith previous versions. 76557db96d56Sopenharmony_ci 76567db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol 76577db96d56Sopenharmony_civersion supported. The higher the protocol used, the more recent the 76587db96d56Sopenharmony_civersion of Python needed to read the pickle produced. 76597db96d56Sopenharmony_ci 76607db96d56Sopenharmony_ciThe *file* argument must have a write() method that accepts a single 76617db96d56Sopenharmony_cibytes argument. It can thus be a file object opened for binary 76627db96d56Sopenharmony_ciwriting, an io.BytesIO instance, or any other custom object that meets 76637db96d56Sopenharmony_cithis interface. 76647db96d56Sopenharmony_ci 76657db96d56Sopenharmony_ciIf *fix_imports* is True and protocol is less than 3, pickle will try 76667db96d56Sopenharmony_cito map the new Python 3 names to the old module names used in Python 76677db96d56Sopenharmony_ci2, so that the pickle data stream is readable with Python 2. 76687db96d56Sopenharmony_ci 76697db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are serialized 76707db96d56Sopenharmony_ciinto *file* as part of the pickle stream. It is an error if 76717db96d56Sopenharmony_ci*buffer_callback* is not None and *protocol* is None or smaller than 5. 76727db96d56Sopenharmony_ci 76737db96d56Sopenharmony_ci[clinic start generated code]*/ 76747db96d56Sopenharmony_ci 76757db96d56Sopenharmony_cistatic PyObject * 76767db96d56Sopenharmony_ci_pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file, 76777db96d56Sopenharmony_ci PyObject *protocol, int fix_imports, 76787db96d56Sopenharmony_ci PyObject *buffer_callback) 76797db96d56Sopenharmony_ci/*[clinic end generated code: output=706186dba996490c input=5ed6653da99cd97c]*/ 76807db96d56Sopenharmony_ci{ 76817db96d56Sopenharmony_ci PicklerObject *pickler = _Pickler_New(); 76827db96d56Sopenharmony_ci 76837db96d56Sopenharmony_ci if (pickler == NULL) 76847db96d56Sopenharmony_ci return NULL; 76857db96d56Sopenharmony_ci 76867db96d56Sopenharmony_ci if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0) 76877db96d56Sopenharmony_ci goto error; 76887db96d56Sopenharmony_ci 76897db96d56Sopenharmony_ci if (_Pickler_SetOutputStream(pickler, file) < 0) 76907db96d56Sopenharmony_ci goto error; 76917db96d56Sopenharmony_ci 76927db96d56Sopenharmony_ci if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0) 76937db96d56Sopenharmony_ci goto error; 76947db96d56Sopenharmony_ci 76957db96d56Sopenharmony_ci if (dump(pickler, obj) < 0) 76967db96d56Sopenharmony_ci goto error; 76977db96d56Sopenharmony_ci 76987db96d56Sopenharmony_ci if (_Pickler_FlushToFile(pickler) < 0) 76997db96d56Sopenharmony_ci goto error; 77007db96d56Sopenharmony_ci 77017db96d56Sopenharmony_ci Py_DECREF(pickler); 77027db96d56Sopenharmony_ci Py_RETURN_NONE; 77037db96d56Sopenharmony_ci 77047db96d56Sopenharmony_ci error: 77057db96d56Sopenharmony_ci Py_XDECREF(pickler); 77067db96d56Sopenharmony_ci return NULL; 77077db96d56Sopenharmony_ci} 77087db96d56Sopenharmony_ci 77097db96d56Sopenharmony_ci/*[clinic input] 77107db96d56Sopenharmony_ci 77117db96d56Sopenharmony_ci_pickle.dumps 77127db96d56Sopenharmony_ci 77137db96d56Sopenharmony_ci obj: object 77147db96d56Sopenharmony_ci protocol: object = None 77157db96d56Sopenharmony_ci * 77167db96d56Sopenharmony_ci fix_imports: bool = True 77177db96d56Sopenharmony_ci buffer_callback: object = None 77187db96d56Sopenharmony_ci 77197db96d56Sopenharmony_ciReturn the pickled representation of the object as a bytes object. 77207db96d56Sopenharmony_ci 77217db96d56Sopenharmony_ciThe optional *protocol* argument tells the pickler to use the given 77227db96d56Sopenharmony_ciprotocol; supported protocols are 0, 1, 2, 3, 4 and 5. The default 77237db96d56Sopenharmony_ciprotocol is 4. It was introduced in Python 3.4, and is incompatible 77247db96d56Sopenharmony_ciwith previous versions. 77257db96d56Sopenharmony_ci 77267db96d56Sopenharmony_ciSpecifying a negative protocol version selects the highest protocol 77277db96d56Sopenharmony_civersion supported. The higher the protocol used, the more recent the 77287db96d56Sopenharmony_civersion of Python needed to read the pickle produced. 77297db96d56Sopenharmony_ci 77307db96d56Sopenharmony_ciIf *fix_imports* is True and *protocol* is less than 3, pickle will 77317db96d56Sopenharmony_citry to map the new Python 3 names to the old module names used in 77327db96d56Sopenharmony_ciPython 2, so that the pickle data stream is readable with Python 2. 77337db96d56Sopenharmony_ci 77347db96d56Sopenharmony_ciIf *buffer_callback* is None (the default), buffer views are serialized 77357db96d56Sopenharmony_ciinto *file* as part of the pickle stream. It is an error if 77367db96d56Sopenharmony_ci*buffer_callback* is not None and *protocol* is None or smaller than 5. 77377db96d56Sopenharmony_ci 77387db96d56Sopenharmony_ci[clinic start generated code]*/ 77397db96d56Sopenharmony_ci 77407db96d56Sopenharmony_cistatic PyObject * 77417db96d56Sopenharmony_ci_pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol, 77427db96d56Sopenharmony_ci int fix_imports, PyObject *buffer_callback) 77437db96d56Sopenharmony_ci/*[clinic end generated code: output=fbab0093a5580fdf input=e543272436c6f987]*/ 77447db96d56Sopenharmony_ci{ 77457db96d56Sopenharmony_ci PyObject *result; 77467db96d56Sopenharmony_ci PicklerObject *pickler = _Pickler_New(); 77477db96d56Sopenharmony_ci 77487db96d56Sopenharmony_ci if (pickler == NULL) 77497db96d56Sopenharmony_ci return NULL; 77507db96d56Sopenharmony_ci 77517db96d56Sopenharmony_ci if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0) 77527db96d56Sopenharmony_ci goto error; 77537db96d56Sopenharmony_ci 77547db96d56Sopenharmony_ci if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0) 77557db96d56Sopenharmony_ci goto error; 77567db96d56Sopenharmony_ci 77577db96d56Sopenharmony_ci if (dump(pickler, obj) < 0) 77587db96d56Sopenharmony_ci goto error; 77597db96d56Sopenharmony_ci 77607db96d56Sopenharmony_ci result = _Pickler_GetString(pickler); 77617db96d56Sopenharmony_ci Py_DECREF(pickler); 77627db96d56Sopenharmony_ci return result; 77637db96d56Sopenharmony_ci 77647db96d56Sopenharmony_ci error: 77657db96d56Sopenharmony_ci Py_XDECREF(pickler); 77667db96d56Sopenharmony_ci return NULL; 77677db96d56Sopenharmony_ci} 77687db96d56Sopenharmony_ci 77697db96d56Sopenharmony_ci/*[clinic input] 77707db96d56Sopenharmony_ci 77717db96d56Sopenharmony_ci_pickle.load 77727db96d56Sopenharmony_ci 77737db96d56Sopenharmony_ci file: object 77747db96d56Sopenharmony_ci * 77757db96d56Sopenharmony_ci fix_imports: bool = True 77767db96d56Sopenharmony_ci encoding: str = 'ASCII' 77777db96d56Sopenharmony_ci errors: str = 'strict' 77787db96d56Sopenharmony_ci buffers: object(c_default="NULL") = () 77797db96d56Sopenharmony_ci 77807db96d56Sopenharmony_ciRead and return an object from the pickle data stored in a file. 77817db96d56Sopenharmony_ci 77827db96d56Sopenharmony_ciThis is equivalent to ``Unpickler(file).load()``, but may be more 77837db96d56Sopenharmony_ciefficient. 77847db96d56Sopenharmony_ci 77857db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no 77867db96d56Sopenharmony_ciprotocol argument is needed. Bytes past the pickled object's 77877db96d56Sopenharmony_cirepresentation are ignored. 77887db96d56Sopenharmony_ci 77897db96d56Sopenharmony_ciThe argument *file* must have two methods, a read() method that takes 77907db96d56Sopenharmony_cian integer argument, and a readline() method that requires no 77917db96d56Sopenharmony_ciarguments. Both methods should return bytes. Thus *file* can be a 77927db96d56Sopenharmony_cibinary file object opened for reading, an io.BytesIO object, or any 77937db96d56Sopenharmony_ciother custom object that meets this interface. 77947db96d56Sopenharmony_ci 77957db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*, 77967db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream 77977db96d56Sopenharmony_cigenerated by Python 2. If *fix_imports* is True, pickle will try to 77987db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3. The 77997db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string 78007db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict', 78017db96d56Sopenharmony_cirespectively. The *encoding* can be 'bytes' to read these 8-bit 78027db96d56Sopenharmony_cistring instances as bytes objects. 78037db96d56Sopenharmony_ci[clinic start generated code]*/ 78047db96d56Sopenharmony_ci 78057db96d56Sopenharmony_cistatic PyObject * 78067db96d56Sopenharmony_ci_pickle_load_impl(PyObject *module, PyObject *file, int fix_imports, 78077db96d56Sopenharmony_ci const char *encoding, const char *errors, 78087db96d56Sopenharmony_ci PyObject *buffers) 78097db96d56Sopenharmony_ci/*[clinic end generated code: output=250452d141c23e76 input=46c7c31c92f4f371]*/ 78107db96d56Sopenharmony_ci{ 78117db96d56Sopenharmony_ci PyObject *result; 78127db96d56Sopenharmony_ci UnpicklerObject *unpickler = _Unpickler_New(); 78137db96d56Sopenharmony_ci 78147db96d56Sopenharmony_ci if (unpickler == NULL) 78157db96d56Sopenharmony_ci return NULL; 78167db96d56Sopenharmony_ci 78177db96d56Sopenharmony_ci if (_Unpickler_SetInputStream(unpickler, file) < 0) 78187db96d56Sopenharmony_ci goto error; 78197db96d56Sopenharmony_ci 78207db96d56Sopenharmony_ci if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0) 78217db96d56Sopenharmony_ci goto error; 78227db96d56Sopenharmony_ci 78237db96d56Sopenharmony_ci if (_Unpickler_SetBuffers(unpickler, buffers) < 0) 78247db96d56Sopenharmony_ci goto error; 78257db96d56Sopenharmony_ci 78267db96d56Sopenharmony_ci unpickler->fix_imports = fix_imports; 78277db96d56Sopenharmony_ci 78287db96d56Sopenharmony_ci result = load(unpickler); 78297db96d56Sopenharmony_ci Py_DECREF(unpickler); 78307db96d56Sopenharmony_ci return result; 78317db96d56Sopenharmony_ci 78327db96d56Sopenharmony_ci error: 78337db96d56Sopenharmony_ci Py_XDECREF(unpickler); 78347db96d56Sopenharmony_ci return NULL; 78357db96d56Sopenharmony_ci} 78367db96d56Sopenharmony_ci 78377db96d56Sopenharmony_ci/*[clinic input] 78387db96d56Sopenharmony_ci 78397db96d56Sopenharmony_ci_pickle.loads 78407db96d56Sopenharmony_ci 78417db96d56Sopenharmony_ci data: object 78427db96d56Sopenharmony_ci / 78437db96d56Sopenharmony_ci * 78447db96d56Sopenharmony_ci fix_imports: bool = True 78457db96d56Sopenharmony_ci encoding: str = 'ASCII' 78467db96d56Sopenharmony_ci errors: str = 'strict' 78477db96d56Sopenharmony_ci buffers: object(c_default="NULL") = () 78487db96d56Sopenharmony_ci 78497db96d56Sopenharmony_ciRead and return an object from the given pickle data. 78507db96d56Sopenharmony_ci 78517db96d56Sopenharmony_ciThe protocol version of the pickle is detected automatically, so no 78527db96d56Sopenharmony_ciprotocol argument is needed. Bytes past the pickled object's 78537db96d56Sopenharmony_cirepresentation are ignored. 78547db96d56Sopenharmony_ci 78557db96d56Sopenharmony_ciOptional keyword arguments are *fix_imports*, *encoding* and *errors*, 78567db96d56Sopenharmony_ciwhich are used to control compatibility support for pickle stream 78577db96d56Sopenharmony_cigenerated by Python 2. If *fix_imports* is True, pickle will try to 78587db96d56Sopenharmony_cimap the old Python 2 names to the new names used in Python 3. The 78597db96d56Sopenharmony_ci*encoding* and *errors* tell pickle how to decode 8-bit string 78607db96d56Sopenharmony_ciinstances pickled by Python 2; these default to 'ASCII' and 'strict', 78617db96d56Sopenharmony_cirespectively. The *encoding* can be 'bytes' to read these 8-bit 78627db96d56Sopenharmony_cistring instances as bytes objects. 78637db96d56Sopenharmony_ci[clinic start generated code]*/ 78647db96d56Sopenharmony_ci 78657db96d56Sopenharmony_cistatic PyObject * 78667db96d56Sopenharmony_ci_pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports, 78677db96d56Sopenharmony_ci const char *encoding, const char *errors, 78687db96d56Sopenharmony_ci PyObject *buffers) 78697db96d56Sopenharmony_ci/*[clinic end generated code: output=82ac1e6b588e6d02 input=b3615540d0535087]*/ 78707db96d56Sopenharmony_ci{ 78717db96d56Sopenharmony_ci PyObject *result; 78727db96d56Sopenharmony_ci UnpicklerObject *unpickler = _Unpickler_New(); 78737db96d56Sopenharmony_ci 78747db96d56Sopenharmony_ci if (unpickler == NULL) 78757db96d56Sopenharmony_ci return NULL; 78767db96d56Sopenharmony_ci 78777db96d56Sopenharmony_ci if (_Unpickler_SetStringInput(unpickler, data) < 0) 78787db96d56Sopenharmony_ci goto error; 78797db96d56Sopenharmony_ci 78807db96d56Sopenharmony_ci if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0) 78817db96d56Sopenharmony_ci goto error; 78827db96d56Sopenharmony_ci 78837db96d56Sopenharmony_ci if (_Unpickler_SetBuffers(unpickler, buffers) < 0) 78847db96d56Sopenharmony_ci goto error; 78857db96d56Sopenharmony_ci 78867db96d56Sopenharmony_ci unpickler->fix_imports = fix_imports; 78877db96d56Sopenharmony_ci 78887db96d56Sopenharmony_ci result = load(unpickler); 78897db96d56Sopenharmony_ci Py_DECREF(unpickler); 78907db96d56Sopenharmony_ci return result; 78917db96d56Sopenharmony_ci 78927db96d56Sopenharmony_ci error: 78937db96d56Sopenharmony_ci Py_XDECREF(unpickler); 78947db96d56Sopenharmony_ci return NULL; 78957db96d56Sopenharmony_ci} 78967db96d56Sopenharmony_ci 78977db96d56Sopenharmony_cistatic struct PyMethodDef pickle_methods[] = { 78987db96d56Sopenharmony_ci _PICKLE_DUMP_METHODDEF 78997db96d56Sopenharmony_ci _PICKLE_DUMPS_METHODDEF 79007db96d56Sopenharmony_ci _PICKLE_LOAD_METHODDEF 79017db96d56Sopenharmony_ci _PICKLE_LOADS_METHODDEF 79027db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 79037db96d56Sopenharmony_ci}; 79047db96d56Sopenharmony_ci 79057db96d56Sopenharmony_cistatic int 79067db96d56Sopenharmony_cipickle_clear(PyObject *m) 79077db96d56Sopenharmony_ci{ 79087db96d56Sopenharmony_ci _Pickle_ClearState(_Pickle_GetState(m)); 79097db96d56Sopenharmony_ci return 0; 79107db96d56Sopenharmony_ci} 79117db96d56Sopenharmony_ci 79127db96d56Sopenharmony_cistatic void 79137db96d56Sopenharmony_cipickle_free(PyObject *m) 79147db96d56Sopenharmony_ci{ 79157db96d56Sopenharmony_ci _Pickle_ClearState(_Pickle_GetState(m)); 79167db96d56Sopenharmony_ci} 79177db96d56Sopenharmony_ci 79187db96d56Sopenharmony_cistatic int 79197db96d56Sopenharmony_cipickle_traverse(PyObject *m, visitproc visit, void *arg) 79207db96d56Sopenharmony_ci{ 79217db96d56Sopenharmony_ci PickleState *st = _Pickle_GetState(m); 79227db96d56Sopenharmony_ci Py_VISIT(st->PickleError); 79237db96d56Sopenharmony_ci Py_VISIT(st->PicklingError); 79247db96d56Sopenharmony_ci Py_VISIT(st->UnpicklingError); 79257db96d56Sopenharmony_ci Py_VISIT(st->dispatch_table); 79267db96d56Sopenharmony_ci Py_VISIT(st->extension_registry); 79277db96d56Sopenharmony_ci Py_VISIT(st->extension_cache); 79287db96d56Sopenharmony_ci Py_VISIT(st->inverted_registry); 79297db96d56Sopenharmony_ci Py_VISIT(st->name_mapping_2to3); 79307db96d56Sopenharmony_ci Py_VISIT(st->import_mapping_2to3); 79317db96d56Sopenharmony_ci Py_VISIT(st->name_mapping_3to2); 79327db96d56Sopenharmony_ci Py_VISIT(st->import_mapping_3to2); 79337db96d56Sopenharmony_ci Py_VISIT(st->codecs_encode); 79347db96d56Sopenharmony_ci Py_VISIT(st->getattr); 79357db96d56Sopenharmony_ci Py_VISIT(st->partial); 79367db96d56Sopenharmony_ci return 0; 79377db96d56Sopenharmony_ci} 79387db96d56Sopenharmony_ci 79397db96d56Sopenharmony_cistatic struct PyModuleDef _picklemodule = { 79407db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 79417db96d56Sopenharmony_ci "_pickle", /* m_name */ 79427db96d56Sopenharmony_ci pickle_module_doc, /* m_doc */ 79437db96d56Sopenharmony_ci sizeof(PickleState), /* m_size */ 79447db96d56Sopenharmony_ci pickle_methods, /* m_methods */ 79457db96d56Sopenharmony_ci NULL, /* m_reload */ 79467db96d56Sopenharmony_ci pickle_traverse, /* m_traverse */ 79477db96d56Sopenharmony_ci pickle_clear, /* m_clear */ 79487db96d56Sopenharmony_ci (freefunc)pickle_free /* m_free */ 79497db96d56Sopenharmony_ci}; 79507db96d56Sopenharmony_ci 79517db96d56Sopenharmony_ciPyMODINIT_FUNC 79527db96d56Sopenharmony_ciPyInit__pickle(void) 79537db96d56Sopenharmony_ci{ 79547db96d56Sopenharmony_ci PyObject *m; 79557db96d56Sopenharmony_ci PickleState *st; 79567db96d56Sopenharmony_ci 79577db96d56Sopenharmony_ci m = PyState_FindModule(&_picklemodule); 79587db96d56Sopenharmony_ci if (m) { 79597db96d56Sopenharmony_ci Py_INCREF(m); 79607db96d56Sopenharmony_ci return m; 79617db96d56Sopenharmony_ci } 79627db96d56Sopenharmony_ci 79637db96d56Sopenharmony_ci if (PyType_Ready(&Pdata_Type) < 0) 79647db96d56Sopenharmony_ci return NULL; 79657db96d56Sopenharmony_ci if (PyType_Ready(&PicklerMemoProxyType) < 0) 79667db96d56Sopenharmony_ci return NULL; 79677db96d56Sopenharmony_ci if (PyType_Ready(&UnpicklerMemoProxyType) < 0) 79687db96d56Sopenharmony_ci return NULL; 79697db96d56Sopenharmony_ci 79707db96d56Sopenharmony_ci /* Create the module and add the functions. */ 79717db96d56Sopenharmony_ci m = PyModule_Create(&_picklemodule); 79727db96d56Sopenharmony_ci if (m == NULL) 79737db96d56Sopenharmony_ci return NULL; 79747db96d56Sopenharmony_ci 79757db96d56Sopenharmony_ci /* Add types */ 79767db96d56Sopenharmony_ci if (PyModule_AddType(m, &Pickler_Type) < 0) { 79777db96d56Sopenharmony_ci return NULL; 79787db96d56Sopenharmony_ci } 79797db96d56Sopenharmony_ci if (PyModule_AddType(m, &Unpickler_Type) < 0) { 79807db96d56Sopenharmony_ci return NULL; 79817db96d56Sopenharmony_ci } 79827db96d56Sopenharmony_ci if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) { 79837db96d56Sopenharmony_ci return NULL; 79847db96d56Sopenharmony_ci } 79857db96d56Sopenharmony_ci 79867db96d56Sopenharmony_ci st = _Pickle_GetState(m); 79877db96d56Sopenharmony_ci 79887db96d56Sopenharmony_ci /* Initialize the exceptions. */ 79897db96d56Sopenharmony_ci st->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL); 79907db96d56Sopenharmony_ci if (st->PickleError == NULL) 79917db96d56Sopenharmony_ci return NULL; 79927db96d56Sopenharmony_ci st->PicklingError = \ 79937db96d56Sopenharmony_ci PyErr_NewException("_pickle.PicklingError", st->PickleError, NULL); 79947db96d56Sopenharmony_ci if (st->PicklingError == NULL) 79957db96d56Sopenharmony_ci return NULL; 79967db96d56Sopenharmony_ci st->UnpicklingError = \ 79977db96d56Sopenharmony_ci PyErr_NewException("_pickle.UnpicklingError", st->PickleError, NULL); 79987db96d56Sopenharmony_ci if (st->UnpicklingError == NULL) 79997db96d56Sopenharmony_ci return NULL; 80007db96d56Sopenharmony_ci 80017db96d56Sopenharmony_ci if (PyModule_AddObjectRef(m, "PickleError", st->PickleError) < 0) { 80027db96d56Sopenharmony_ci return NULL; 80037db96d56Sopenharmony_ci } 80047db96d56Sopenharmony_ci if (PyModule_AddObjectRef(m, "PicklingError", st->PicklingError) < 0) { 80057db96d56Sopenharmony_ci return NULL; 80067db96d56Sopenharmony_ci } 80077db96d56Sopenharmony_ci if (PyModule_AddObjectRef(m, "UnpicklingError", st->UnpicklingError) < 0) { 80087db96d56Sopenharmony_ci return NULL; 80097db96d56Sopenharmony_ci } 80107db96d56Sopenharmony_ci if (_Pickle_InitState(st) < 0) 80117db96d56Sopenharmony_ci return NULL; 80127db96d56Sopenharmony_ci 80137db96d56Sopenharmony_ci return m; 80147db96d56Sopenharmony_ci} 8015