LCOV - code coverage report
Current view: | top level - Modules - _pickle.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 110 | 3757 | 2.9 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 6 | 203 | 3.0 %
|  |  | Branches: | 81 | 2671 | 3.0 %

               Branch data     Line data    Source code
           1                 :            : /* pickle accelerator C extensor: _pickle module.
           2                 :            :  *
           3                 :            :  * It is built as a built-in module (Py_BUILD_CORE_BUILTIN define) on Windows
           4                 :            :  * and as an extension module (Py_BUILD_CORE_MODULE define) on other
           5                 :            :  * platforms. */
           6                 :            :
           7                 :            : #ifndef Py_BUILD_CORE_BUILTIN
           8                 :            : #  define Py_BUILD_CORE_MODULE 1
           9                 :            : #endif
          10                 :            :
          11                 :            : #include "Python.h"
          12                 :            : #include "pycore_ceval.h"         // _Py_EnterRecursiveCall()
          13                 :            : #include "pycore_moduleobject.h"  // _PyModule_GetState()
          14                 :            : #include "pycore_runtime.h"       // _Py_ID()
          15                 :            : #include "pycore_pystate.h"       // _PyThreadState_GET()
          16                 :            : #include "structmember.h"         // PyMemberDef
          17                 :            :
          18                 :            : #include <stdlib.h>               // strtol()
          19                 :            :
          20                 :            : PyDoc_STRVAR(pickle_module_doc,
          21                 :            : "Optimized C implementation for the Python pickle module.");
          22                 :            :
          23                 :            : /*[clinic input]
          24                 :            : module _pickle
          25                 :            : class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
          26                 :            : class _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" "&PicklerMemoProxyType"
          27                 :            : class _pickle.Unpickler "UnpicklerObject *" "&Unpickler_Type"
          28                 :            : class _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" "&UnpicklerMemoProxyType"
          29                 :            : [clinic start generated code]*/
          30                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b3e113468a58e6c]*/
          31                 :            :
          32                 :            : /* Bump HIGHEST_PROTOCOL when new opcodes are added to the pickle protocol.
          33                 :            :    Bump DEFAULT_PROTOCOL only when the oldest still supported version of Python
          34                 :            :    already includes it. */
          35                 :            : enum {
          36                 :            :     HIGHEST_PROTOCOL = 5,
          37                 :            :     DEFAULT_PROTOCOL = 4
          38                 :            : };
          39                 :            :
          40                 :            : #ifdef MS_WINDOWS
          41                 :            : // These are already typedefs from windows.h, pulled in via pycore_runtime.h.
          42                 :            : #define FLOAT FLOAT_
          43                 :            : #define INT INT_
          44                 :            : #define LONG LONG_
          45                 :            :
          46                 :            : /* This can already be defined on Windows to set the character set
          47                 :            :    the Windows header files treat as default */
          48                 :            : #ifdef UNICODE
          49                 :            : #undef UNICODE
          50                 :            : #endif
          51                 :            : #endif
          52                 :            :
          53                 :            : /* Pickle opcodes. These must be kept updated with pickle.py.
          54                 :            :    Extensive docs are in pickletools.py. */
          55                 :            : enum opcode {
          56                 :            :     MARK            = '(',
          57                 :            :     STOP            = '.',
          58                 :            :     POP             = '0',
          59                 :            :     POP_MARK        = '1',
          60                 :            :     DUP             = '2',
          61                 :            :     FLOAT           = 'F',
          62                 :            :     INT             = 'I',
          63                 :            :     BININT          = 'J',
          64                 :            :     BININT1         = 'K',
          65                 :            :     LONG            = 'L',
          66                 :            :     BININT2         = 'M',
          67                 :            :     NONE            = 'N',
          68                 :            :     PERSID          = 'P',
          69                 :            :     BINPERSID       = 'Q',
          70                 :            :     REDUCE          = 'R',
          71                 :            :     STRING          = 'S',
          72                 :            :     BINSTRING       = 'T',
          73                 :            :     SHORT_BINSTRING = 'U',
          74                 :            :     UNICODE         = 'V',
          75                 :            :     BINUNICODE      = 'X',
          76                 :            :     APPEND          = 'a',
          77                 :            :     BUILD           = 'b',
          78                 :            :     GLOBAL          = 'c',
          79                 :            :     DICT            = 'd',
          80                 :            :     EMPTY_DICT      = '}',
          81                 :            :     APPENDS         = 'e',
          82                 :            :     GET             = 'g',
          83                 :            :     BINGET          = 'h',
          84                 :            :     INST            = 'i',
          85                 :            :     LONG_BINGET     = 'j',
          86                 :            :     LIST            = 'l',
          87                 :            :     EMPTY_LIST      = ']',
          88                 :            :     OBJ             = 'o',
          89                 :            :     PUT             = 'p',
          90                 :            :     BINPUT          = 'q',
          91                 :            :     LONG_BINPUT     = 'r',
          92                 :            :     SETITEM         = 's',
          93                 :            :     TUPLE           = 't',
          94                 :            :     EMPTY_TUPLE     = ')',
          95                 :            :     SETITEMS        = 'u',
          96                 :            :     BINFLOAT        = 'G',
          97                 :            :
          98                 :            :     /* Protocol 2. */
          99                 :            :     PROTO       = '\x80',
         100                 :            :     NEWOBJ      = '\x81',
         101                 :            :     EXT1        = '\x82',
         102                 :            :     EXT2        = '\x83',
         103                 :            :     EXT4        = '\x84',
         104                 :            :     TUPLE1      = '\x85',
         105                 :            :     TUPLE2      = '\x86',
         106                 :            :     TUPLE3      = '\x87',
         107                 :            :     NEWTRUE     = '\x88',
         108                 :            :     NEWFALSE    = '\x89',
         109                 :            :     LONG1       = '\x8a',
         110                 :            :     LONG4       = '\x8b',
         111                 :            :
         112                 :            :     /* Protocol 3 (Python 3.x) */
         113                 :            :     BINBYTES       = 'B',
         114                 :            :     SHORT_BINBYTES = 'C',
         115                 :            :
         116                 :            :     /* Protocol 4 */
         117                 :            :     SHORT_BINUNICODE = '\x8c',
         118                 :            :     BINUNICODE8      = '\x8d',
         119                 :            :     BINBYTES8        = '\x8e',
         120                 :            :     EMPTY_SET        = '\x8f',
         121                 :            :     ADDITEMS         = '\x90',
         122                 :            :     FROZENSET        = '\x91',
         123                 :            :     NEWOBJ_EX        = '\x92',
         124                 :            :     STACK_GLOBAL     = '\x93',
         125                 :            :     MEMOIZE          = '\x94',
         126                 :            :     FRAME            = '\x95',
         127                 :            :
         128                 :            :     /* Protocol 5 */
         129                 :            :     BYTEARRAY8       = '\x96',
         130                 :            :     NEXT_BUFFER      = '\x97',
         131                 :            :     READONLY_BUFFER  = '\x98'
         132                 :            : };
         133                 :            :
         134                 :            : enum {
         135                 :            :    /* Keep in synch with pickle.Pickler._BATCHSIZE.  This is how many elements
         136                 :            :       batch_list/dict() pumps out before doing APPENDS/SETITEMS.  Nothing will
         137                 :            :       break if this gets out of synch with pickle.py, but it's unclear that would
         138                 :            :       help anything either. */
         139                 :            :     BATCHSIZE = 1000,
         140                 :            :
         141                 :            :     /* Nesting limit until Pickler, when running in "fast mode", starts
         142                 :            :        checking for self-referential data-structures. */
         143                 :            :     FAST_NESTING_LIMIT = 50,
         144                 :            :
         145                 :            :     /* Initial size of the write buffer of Pickler. */
         146                 :            :     WRITE_BUF_SIZE = 4096,
         147                 :            :
         148                 :            :     /* Prefetch size when unpickling (disabled on unpeekable streams) */
         149                 :            :     PREFETCH = 8192 * 16,
         150                 :            :
         151                 :            :     FRAME_SIZE_MIN = 4,
         152                 :            :     FRAME_SIZE_TARGET = 64 * 1024,
         153                 :            :     FRAME_HEADER_SIZE = 9
         154                 :            : };
         155                 :            :
         156                 :            : /*************************************************************************/
         157                 :            :
         158                 :            : /* State of the pickle module, per PEP 3121. */
         159                 :            : typedef struct {
         160                 :            :     /* Exception classes for pickle. */
         161                 :            :     PyObject *PickleError;
         162                 :            :     PyObject *PicklingError;
         163                 :            :     PyObject *UnpicklingError;
         164                 :            :
         165                 :            :     /* copyreg.dispatch_table, {type_object: pickling_function} */
         166                 :            :     PyObject *dispatch_table;
         167                 :            :
         168                 :            :     /* For the extension opcodes EXT1, EXT2 and EXT4. */
         169                 :            :
         170                 :            :     /* copyreg._extension_registry, {(module_name, function_name): code} */
         171                 :            :     PyObject *extension_registry;
         172                 :            :     /* copyreg._extension_cache, {code: object} */
         173                 :            :     PyObject *extension_cache;
         174                 :            :     /* copyreg._inverted_registry, {code: (module_name, function_name)} */
         175                 :            :     PyObject *inverted_registry;
         176                 :            :
         177                 :            :     /* Import mappings for compatibility with Python 2.x */
         178                 :            :
         179                 :            :     /* _compat_pickle.NAME_MAPPING,
         180                 :            :        {(oldmodule, oldname): (newmodule, newname)} */
         181                 :            :     PyObject *name_mapping_2to3;
         182                 :            :     /* _compat_pickle.IMPORT_MAPPING, {oldmodule: newmodule} */
         183                 :            :     PyObject *import_mapping_2to3;
         184                 :            :     /* Same, but with REVERSE_NAME_MAPPING / REVERSE_IMPORT_MAPPING */
         185                 :            :     PyObject *name_mapping_3to2;
         186                 :            :     PyObject *import_mapping_3to2;
         187                 :            :
         188                 :            :     /* codecs.encode, used for saving bytes in older protocols */
         189                 :            :     PyObject *codecs_encode;
         190                 :            :     /* builtins.getattr, used for saving nested names with protocol < 4 */
         191                 :            :     PyObject *getattr;
         192                 :            :     /* functools.partial, used for implementing __newobj_ex__ with protocols
         193                 :            :        2 and 3 */
         194                 :            :     PyObject *partial;
         195                 :            : } PickleState;
         196                 :            :
         197                 :            : /* Forward declaration of the _pickle module definition. */
         198                 :            : static struct PyModuleDef _picklemodule;
         199                 :            :
         200                 :            : /* Given a module object, get its per-module state. */
         201                 :            : static PickleState *
         202                 :         10 : _Pickle_GetState(PyObject *module)
         203                 :            : {
         204                 :         10 :     return (PickleState *)_PyModule_GetState(module);
         205                 :            : }
         206                 :            :
         207                 :            : /* Find the module instance imported in the currently running sub-interpreter
         208                 :            :    and get its state. */
         209                 :            : static PickleState *
         210                 :          0 : _Pickle_GetGlobalState(void)
         211                 :            : {
         212                 :          0 :     return _Pickle_GetState(PyState_FindModule(&_picklemodule));
         213                 :            : }
         214                 :            :
         215                 :            : /* Clear the given pickle module state. */
         216                 :            : static void
         217                 :          1 : _Pickle_ClearState(PickleState *st)
         218                 :            : {
         219         [ +  - ]:          1 :     Py_CLEAR(st->PickleError);
         220         [ +  - ]:          1 :     Py_CLEAR(st->PicklingError);
         221         [ +  - ]:          1 :     Py_CLEAR(st->UnpicklingError);
         222         [ +  - ]:          1 :     Py_CLEAR(st->dispatch_table);
         223         [ +  - ]:          1 :     Py_CLEAR(st->extension_registry);
         224         [ +  - ]:          1 :     Py_CLEAR(st->extension_cache);
         225         [ +  - ]:          1 :     Py_CLEAR(st->inverted_registry);
         226         [ +  - ]:          1 :     Py_CLEAR(st->name_mapping_2to3);
         227         [ +  - ]:          1 :     Py_CLEAR(st->import_mapping_2to3);
         228         [ +  - ]:          1 :     Py_CLEAR(st->name_mapping_3to2);
         229         [ +  - ]:          1 :     Py_CLEAR(st->import_mapping_3to2);
         230         [ +  - ]:          1 :     Py_CLEAR(st->codecs_encode);
         231         [ +  - ]:          1 :     Py_CLEAR(st->getattr);
         232         [ +  - ]:          1 :     Py_CLEAR(st->partial);
         233                 :          1 : }
         234                 :            :
         235                 :            : /* Initialize the given pickle module state. */
         236                 :            : static int
         237                 :          1 : _Pickle_InitState(PickleState *st)
         238                 :            : {
         239                 :          1 :     PyObject *copyreg = NULL;
         240                 :          1 :     PyObject *compat_pickle = NULL;
         241                 :            :
         242                 :          1 :     st->getattr = _PyEval_GetBuiltin(&_Py_ID(getattr));
         243         [ -  + ]:          1 :     if (st->getattr == NULL)
         244                 :          0 :         goto error;
         245                 :            :
         246                 :          1 :     copyreg = PyImport_ImportModule("copyreg");
         247         [ -  + ]:          1 :     if (!copyreg)
         248                 :          0 :         goto error;
         249                 :          1 :     st->dispatch_table = PyObject_GetAttrString(copyreg, "dispatch_table");
         250         [ -  + ]:          1 :     if (!st->dispatch_table)
         251                 :          0 :         goto error;
         252         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->dispatch_table)) {
         253                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         254                 :            :                      "copyreg.dispatch_table should be a dict, not %.200s",
         255                 :          0 :                      Py_TYPE(st->dispatch_table)->tp_name);
         256                 :          0 :         goto error;
         257                 :            :     }
         258                 :          1 :     st->extension_registry = \
         259                 :          1 :         PyObject_GetAttrString(copyreg, "_extension_registry");
         260         [ -  + ]:          1 :     if (!st->extension_registry)
         261                 :          0 :         goto error;
         262         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->extension_registry)) {
         263                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         264                 :            :                      "copyreg._extension_registry should be a dict, "
         265                 :          0 :                      "not %.200s", Py_TYPE(st->extension_registry)->tp_name);
         266                 :          0 :         goto error;
         267                 :            :     }
         268                 :          1 :     st->inverted_registry = \
         269                 :          1 :         PyObject_GetAttrString(copyreg, "_inverted_registry");
         270         [ -  + ]:          1 :     if (!st->inverted_registry)
         271                 :          0 :         goto error;
         272         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->inverted_registry)) {
         273                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         274                 :            :                      "copyreg._inverted_registry should be a dict, "
         275                 :          0 :                      "not %.200s", Py_TYPE(st->inverted_registry)->tp_name);
         276                 :          0 :         goto error;
         277                 :            :     }
         278                 :          1 :     st->extension_cache = PyObject_GetAttrString(copyreg, "_extension_cache");
         279         [ -  + ]:          1 :     if (!st->extension_cache)
         280                 :          0 :         goto error;
         281         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->extension_cache)) {
         282                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         283                 :            :                      "copyreg._extension_cache should be a dict, "
         284                 :          0 :                      "not %.200s", Py_TYPE(st->extension_cache)->tp_name);
         285                 :          0 :         goto error;
         286                 :            :     }
         287         [ +  - ]:          1 :     Py_CLEAR(copyreg);
         288                 :            :
         289                 :            :     /* Load the 2.x -> 3.x stdlib module mapping tables */
         290                 :          1 :     compat_pickle = PyImport_ImportModule("_compat_pickle");
         291         [ -  + ]:          1 :     if (!compat_pickle)
         292                 :          0 :         goto error;
         293                 :          1 :     st->name_mapping_2to3 = \
         294                 :          1 :         PyObject_GetAttrString(compat_pickle, "NAME_MAPPING");
         295         [ -  + ]:          1 :     if (!st->name_mapping_2to3)
         296                 :          0 :         goto error;
         297         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->name_mapping_2to3)) {
         298                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         299                 :            :                      "_compat_pickle.NAME_MAPPING should be a dict, not %.200s",
         300                 :          0 :                      Py_TYPE(st->name_mapping_2to3)->tp_name);
         301                 :          0 :         goto error;
         302                 :            :     }
         303                 :          1 :     st->import_mapping_2to3 = \
         304                 :          1 :         PyObject_GetAttrString(compat_pickle, "IMPORT_MAPPING");
         305         [ -  + ]:          1 :     if (!st->import_mapping_2to3)
         306                 :          0 :         goto error;
         307         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->import_mapping_2to3)) {
         308                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         309                 :            :                      "_compat_pickle.IMPORT_MAPPING should be a dict, "
         310                 :          0 :                      "not %.200s", Py_TYPE(st->import_mapping_2to3)->tp_name);
         311                 :          0 :         goto error;
         312                 :            :     }
         313                 :            :     /* ... and the 3.x -> 2.x mapping tables */
         314                 :          1 :     st->name_mapping_3to2 = \
         315                 :          1 :         PyObject_GetAttrString(compat_pickle, "REVERSE_NAME_MAPPING");
         316         [ -  + ]:          1 :     if (!st->name_mapping_3to2)
         317                 :          0 :         goto error;
         318         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->name_mapping_3to2)) {
         319                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         320                 :            :                      "_compat_pickle.REVERSE_NAME_MAPPING should be a dict, "
         321                 :          0 :                      "not %.200s", Py_TYPE(st->name_mapping_3to2)->tp_name);
         322                 :          0 :         goto error;
         323                 :            :     }
         324                 :          1 :     st->import_mapping_3to2 = \
         325                 :          1 :         PyObject_GetAttrString(compat_pickle, "REVERSE_IMPORT_MAPPING");
         326         [ -  + ]:          1 :     if (!st->import_mapping_3to2)
         327                 :          0 :         goto error;
         328         [ -  + ]:          1 :     if (!PyDict_CheckExact(st->import_mapping_3to2)) {
         329                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         330                 :            :                      "_compat_pickle.REVERSE_IMPORT_MAPPING should be a dict, "
         331                 :          0 :                      "not %.200s", Py_TYPE(st->import_mapping_3to2)->tp_name);
         332                 :          0 :         goto error;
         333                 :            :     }
         334         [ +  - ]:          1 :     Py_CLEAR(compat_pickle);
         335                 :            :
         336                 :          1 :     st->codecs_encode = _PyImport_GetModuleAttrString("codecs", "encode");
         337         [ -  + ]:          1 :     if (st->codecs_encode == NULL) {
         338                 :          0 :         goto error;
         339                 :            :     }
         340         [ -  + ]:          1 :     if (!PyCallable_Check(st->codecs_encode)) {
         341                 :          0 :         PyErr_Format(PyExc_RuntimeError,
         342                 :            :                      "codecs.encode should be a callable, not %.200s",
         343                 :          0 :                      Py_TYPE(st->codecs_encode)->tp_name);
         344                 :          0 :         goto error;
         345                 :            :     }
         346                 :            :
         347                 :          1 :     st->partial = _PyImport_GetModuleAttrString("functools", "partial");
         348         [ -  + ]:          1 :     if (!st->partial)
         349                 :          0 :         goto error;
         350                 :            :
         351                 :          1 :     return 0;
         352                 :            :
         353                 :          0 :   error:
         354         [ #  # ]:          0 :     Py_CLEAR(copyreg);
         355         [ #  # ]:          0 :     Py_CLEAR(compat_pickle);
         356                 :          0 :     _Pickle_ClearState(st);
         357                 :          0 :     return -1;
         358                 :            : }
         359                 :            :
         360                 :            : /* Helper for calling a function with a single argument quickly.
         361                 :            :
         362                 :            :    This function steals the reference of the given argument. */
         363                 :            : static PyObject *
         364                 :          0 : _Pickle_FastCall(PyObject *func, PyObject *obj)
         365                 :            : {
         366                 :            :     PyObject *result;
         367                 :            :
         368                 :          0 :     result = PyObject_CallOneArg(func, obj);
         369                 :          0 :     Py_DECREF(obj);
         370                 :          0 :     return result;
         371                 :            : }
         372                 :            :
         373                 :            : /*************************************************************************/
         374                 :            :
         375                 :            : /* Retrieve and deconstruct a method for avoiding a reference cycle
         376                 :            :    (pickler -> bound method of pickler -> pickler) */
         377                 :            : static int
         378                 :          0 : init_method_ref(PyObject *self, PyObject *name,
         379                 :            :                 PyObject **method_func, PyObject **method_self)
         380                 :            : {
         381                 :            :     PyObject *func, *func2;
         382                 :            :     int ret;
         383                 :            :
         384                 :            :     /* *method_func and *method_self should be consistent.  All refcount decrements
         385                 :            :        should be occurred after setting *method_self and *method_func. */
         386                 :          0 :     ret = _PyObject_LookupAttr(self, name, &func);
         387         [ #  # ]:          0 :     if (func == NULL) {
         388                 :          0 :         *method_self = NULL;
         389         [ #  # ]:          0 :         Py_CLEAR(*method_func);
         390                 :          0 :         return ret;
         391                 :            :     }
         392                 :            :
         393   [ #  #  #  # ]:          0 :     if (PyMethod_Check(func) && PyMethod_GET_SELF(func) == self) {
         394                 :            :         /* Deconstruct a bound Python method */
         395                 :          0 :         *method_self = self; /* borrowed */
         396                 :          0 :         func2 = PyMethod_GET_FUNCTION(func);
         397                 :          0 :         Py_XSETREF(*method_func, Py_NewRef(func2));
         398                 :          0 :         Py_DECREF(func);
         399                 :          0 :         return 0;
         400                 :            :     }
         401                 :            :     else {
         402                 :          0 :         *method_self = NULL;
         403                 :          0 :         Py_XSETREF(*method_func, func);
         404                 :          0 :         return 0;
         405                 :            :     }
         406                 :            : }
         407                 :            :
         408                 :            : /* Bind a method if it was deconstructed */
         409                 :            : static PyObject *
         410                 :          0 : reconstruct_method(PyObject *func, PyObject *self)
         411                 :            : {
         412         [ #  # ]:          0 :     if (self) {
         413                 :          0 :         return PyMethod_New(func, self);
         414                 :            :     }
         415                 :            :     else {
         416                 :          0 :         return Py_NewRef(func);
         417                 :            :     }
         418                 :            : }
         419                 :            :
         420                 :            : static PyObject *
         421                 :          0 : call_method(PyObject *func, PyObject *self, PyObject *obj)
         422                 :            : {
         423         [ #  # ]:          0 :     if (self) {
         424                 :          0 :         return PyObject_CallFunctionObjArgs(func, self, obj, NULL);
         425                 :            :     }
         426                 :            :     else {
         427                 :          0 :         return PyObject_CallOneArg(func, obj);
         428                 :            :     }
         429                 :            : }
         430                 :            :
         431                 :            : /*************************************************************************/
         432                 :            :
         433                 :            : /* Internal data type used as the unpickling stack. */
         434                 :            : typedef struct {
         435                 :            :     PyObject_VAR_HEAD
         436                 :            :     PyObject **data;
         437                 :            :     int mark_set;          /* is MARK set? */
         438                 :            :     Py_ssize_t fence;      /* position of top MARK or 0 */
         439                 :            :     Py_ssize_t allocated;  /* number of slots in data allocated */
         440                 :            : } Pdata;
         441                 :            :
         442                 :            : static void
         443                 :          0 : Pdata_dealloc(Pdata *self)
         444                 :            : {
         445                 :          0 :     Py_ssize_t i = Py_SIZE(self);
         446         [ #  # ]:          0 :     while (--i >= 0) {
         447                 :          0 :         Py_DECREF(self->data[i]);
         448                 :            :     }
         449                 :          0 :     PyMem_Free(self->data);
         450                 :          0 :     PyObject_Free(self);
         451                 :          0 : }
         452                 :            :
         453                 :            : static PyTypeObject Pdata_Type = {
         454                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         455                 :            :     "_pickle.Pdata",              /*tp_name*/
         456                 :            :     sizeof(Pdata),                /*tp_basicsize*/
         457                 :            :     sizeof(PyObject *),           /*tp_itemsize*/
         458                 :            :     (destructor)Pdata_dealloc,    /*tp_dealloc*/
         459                 :            : };
         460                 :            :
         461                 :            : static PyObject *
         462                 :          0 : Pdata_New(void)
         463                 :            : {
         464                 :            :     Pdata *self;
         465                 :            :
         466         [ #  # ]:          0 :     if (!(self = PyObject_New(Pdata, &Pdata_Type)))
         467                 :          0 :         return NULL;
         468                 :          0 :     Py_SET_SIZE(self, 0);
         469                 :          0 :     self->mark_set = 0;
         470                 :          0 :     self->fence = 0;
         471                 :          0 :     self->allocated = 8;
         472                 :          0 :     self->data = PyMem_Malloc(self->allocated * sizeof(PyObject *));
         473         [ #  # ]:          0 :     if (self->data)
         474                 :          0 :         return (PyObject *)self;
         475                 :          0 :     Py_DECREF(self);
         476                 :          0 :     return PyErr_NoMemory();
         477                 :            : }
         478                 :            :
         479                 :            :
         480                 :            : /* Retain only the initial clearto items.  If clearto >= the current
         481                 :            :  * number of items, this is a (non-erroneous) NOP.
         482                 :            :  */
         483                 :            : static int
         484                 :          0 : Pdata_clear(Pdata *self, Py_ssize_t clearto)
         485                 :            : {
         486                 :          0 :     Py_ssize_t i = Py_SIZE(self);
         487                 :            :
         488                 :            :     assert(clearto >= self->fence);
         489         [ #  # ]:          0 :     if (clearto >= i)
         490                 :          0 :         return 0;
         491                 :            :
         492         [ #  # ]:          0 :     while (--i >= clearto) {
         493         [ #  # ]:          0 :         Py_CLEAR(self->data[i]);
         494                 :            :     }
         495                 :          0 :     Py_SET_SIZE(self, clearto);
         496                 :          0 :     return 0;
         497                 :            : }
         498                 :            :
         499                 :            : static int
         500                 :          0 : Pdata_grow(Pdata *self)
         501                 :            : {
         502                 :          0 :     PyObject **data = self->data;
         503                 :          0 :     size_t allocated = (size_t)self->allocated;
         504                 :            :     size_t new_allocated;
         505                 :            :
         506                 :          0 :     new_allocated = (allocated >> 3) + 6;
         507                 :            :     /* check for integer overflow */
         508         [ #  # ]:          0 :     if (new_allocated > (size_t)PY_SSIZE_T_MAX - allocated)
         509                 :          0 :         goto nomemory;
         510                 :          0 :     new_allocated += allocated;
         511         [ #  # ]:          0 :     PyMem_RESIZE(data, PyObject *, new_allocated);
         512         [ #  # ]:          0 :     if (data == NULL)
         513                 :          0 :         goto nomemory;
         514                 :            :
         515                 :          0 :     self->data = data;
         516                 :          0 :     self->allocated = (Py_ssize_t)new_allocated;
         517                 :          0 :     return 0;
         518                 :            :
         519                 :          0 :   nomemory:
         520                 :          0 :     PyErr_NoMemory();
         521                 :          0 :     return -1;
         522                 :            : }
         523                 :            :
         524                 :            : static int
         525                 :          0 : Pdata_stack_underflow(Pdata *self)
         526                 :            : {
         527                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
         528                 :          0 :     PyErr_SetString(st->UnpicklingError,
         529         [ #  # ]:          0 :                     self->mark_set ?
         530                 :            :                     "unexpected MARK found" :
         531                 :            :                     "unpickling stack underflow");
         532                 :          0 :     return -1;
         533                 :            : }
         534                 :            :
         535                 :            : /* D is a Pdata*.  Pop the topmost element and store it into V, which
         536                 :            :  * must be an lvalue holding PyObject*.  On stack underflow, UnpicklingError
         537                 :            :  * is raised and V is set to NULL.
         538                 :            :  */
         539                 :            : static PyObject *
         540                 :          0 : Pdata_pop(Pdata *self)
         541                 :            : {
         542         [ #  # ]:          0 :     if (Py_SIZE(self) <= self->fence) {
         543                 :          0 :         Pdata_stack_underflow(self);
         544                 :          0 :         return NULL;
         545                 :            :     }
         546                 :          0 :     Py_SET_SIZE(self, Py_SIZE(self) - 1);
         547                 :          0 :     return self->data[Py_SIZE(self)];
         548                 :            : }
         549                 :            : #define PDATA_POP(D, V) do { (V) = Pdata_pop((D)); } while (0)
         550                 :            :
         551                 :            : static int
         552                 :          0 : Pdata_push(Pdata *self, PyObject *obj)
         553                 :            : {
         554   [ #  #  #  # ]:          0 :     if (Py_SIZE(self) == self->allocated && Pdata_grow(self) < 0) {
         555                 :          0 :         return -1;
         556                 :            :     }
         557                 :          0 :     self->data[Py_SIZE(self)] = obj;
         558                 :          0 :     Py_SET_SIZE(self, Py_SIZE(self) + 1);
         559                 :          0 :     return 0;
         560                 :            : }
         561                 :            :
         562                 :            : /* Push an object on stack, transferring its ownership to the stack. */
         563                 :            : #define PDATA_PUSH(D, O, ER) do {                               \
         564                 :            :         if (Pdata_push((D), (O)) < 0) return (ER); } while(0)
         565                 :            :
         566                 :            : /* Push an object on stack, adding a new reference to the object. */
         567                 :            : #define PDATA_APPEND(D, O, ER) do {                             \
         568                 :            :         Py_INCREF((O));                                         \
         569                 :            :         if (Pdata_push((D), (O)) < 0) return (ER); } while(0)
         570                 :            :
         571                 :            : static PyObject *
         572                 :          0 : Pdata_poptuple(Pdata *self, Py_ssize_t start)
         573                 :            : {
         574                 :            :     PyObject *tuple;
         575                 :            :     Py_ssize_t len, i, j;
         576                 :            :
         577         [ #  # ]:          0 :     if (start < self->fence) {
         578                 :          0 :         Pdata_stack_underflow(self);
         579                 :          0 :         return NULL;
         580                 :            :     }
         581                 :          0 :     len = Py_SIZE(self) - start;
         582                 :          0 :     tuple = PyTuple_New(len);
         583         [ #  # ]:          0 :     if (tuple == NULL)
         584                 :          0 :         return NULL;
         585         [ #  # ]:          0 :     for (i = start, j = 0; j < len; i++, j++)
         586                 :          0 :         PyTuple_SET_ITEM(tuple, j, self->data[i]);
         587                 :            :
         588                 :          0 :     Py_SET_SIZE(self, start);
         589                 :          0 :     return tuple;
         590                 :            : }
         591                 :            :
         592                 :            : static PyObject *
         593                 :          0 : Pdata_poplist(Pdata *self, Py_ssize_t start)
         594                 :            : {
         595                 :            :     PyObject *list;
         596                 :            :     Py_ssize_t len, i, j;
         597                 :            :
         598                 :          0 :     len = Py_SIZE(self) - start;
         599                 :          0 :     list = PyList_New(len);
         600         [ #  # ]:          0 :     if (list == NULL)
         601                 :          0 :         return NULL;
         602         [ #  # ]:          0 :     for (i = start, j = 0; j < len; i++, j++)
         603                 :          0 :         PyList_SET_ITEM(list, j, self->data[i]);
         604                 :            :
         605                 :          0 :     Py_SET_SIZE(self, start);
         606                 :          0 :     return list;
         607                 :            : }
         608                 :            :
         609                 :            : typedef struct {
         610                 :            :     PyObject *me_key;
         611                 :            :     Py_ssize_t me_value;
         612                 :            : } PyMemoEntry;
         613                 :            :
         614                 :            : typedef struct {
         615                 :            :     size_t mt_mask;
         616                 :            :     size_t mt_used;
         617                 :            :     size_t mt_allocated;
         618                 :            :     PyMemoEntry *mt_table;
         619                 :            : } PyMemoTable;
         620                 :            :
         621                 :            : typedef struct PicklerObject {
         622                 :            :     PyObject_HEAD
         623                 :            :     PyMemoTable *memo;          /* Memo table, keep track of the seen
         624                 :            :                                    objects to support self-referential objects
         625                 :            :                                    pickling. */
         626                 :            :     PyObject *pers_func;        /* persistent_id() method, can be NULL */
         627                 :            :     PyObject *pers_func_self;   /* borrowed reference to self if pers_func
         628                 :            :                                    is an unbound method, NULL otherwise */
         629                 :            :     PyObject *dispatch_table;   /* private dispatch_table, can be NULL */
         630                 :            :     PyObject *reducer_override; /* hook for invoking user-defined callbacks
         631                 :            :                                    instead of save_global when pickling
         632                 :            :                                    functions and classes*/
         633                 :            :
         634                 :            :     PyObject *write;            /* write() method of the output stream. */
         635                 :            :     PyObject *output_buffer;    /* Write into a local bytearray buffer before
         636                 :            :                                    flushing to the stream. */
         637                 :            :     Py_ssize_t output_len;      /* Length of output_buffer. */
         638                 :            :     Py_ssize_t max_output_len;  /* Allocation size of output_buffer. */
         639                 :            :     int proto;                  /* Pickle protocol number, >= 0 */
         640                 :            :     int bin;                    /* Boolean, true if proto > 0 */
         641                 :            :     int framing;                /* True when framing is enabled, proto >= 4 */
         642                 :            :     Py_ssize_t frame_start;     /* Position in output_buffer where the
         643                 :            :                                    current frame begins. -1 if there
         644                 :            :                                    is no frame currently open. */
         645                 :            :
         646                 :            :     Py_ssize_t buf_size;        /* Size of the current buffered pickle data */
         647                 :            :     int fast;                   /* Enable fast mode if set to a true value.
         648                 :            :                                    The fast mode disable the usage of memo,
         649                 :            :                                    therefore speeding the pickling process by
         650                 :            :                                    not generating superfluous PUT opcodes. It
         651                 :            :                                    should not be used if with self-referential
         652                 :            :                                    objects. */
         653                 :            :     int fast_nesting;
         654                 :            :     int fix_imports;            /* Indicate whether Pickler should fix
         655                 :            :                                    the name of globals for Python 2.x. */
         656                 :            :     PyObject *fast_memo;
         657                 :            :     PyObject *buffer_callback;  /* Callback for out-of-band buffers, or NULL */
         658                 :            : } PicklerObject;
         659                 :            :
         660                 :            : typedef struct UnpicklerObject {
         661                 :            :     PyObject_HEAD
         662                 :            :     Pdata *stack;               /* Pickle data stack, store unpickled objects. */
         663                 :            :
         664                 :            :     /* The unpickler memo is just an array of PyObject *s. Using a dict
         665                 :            :        is unnecessary, since the keys are contiguous ints. */
         666                 :            :     PyObject **memo;
         667                 :            :     size_t memo_size;       /* Capacity of the memo array */
         668                 :            :     size_t memo_len;        /* Number of objects in the memo */
         669                 :            :
         670                 :            :     PyObject *pers_func;        /* persistent_load() method, can be NULL. */
         671                 :            :     PyObject *pers_func_self;   /* borrowed reference to self if pers_func
         672                 :            :                                    is an unbound method, NULL otherwise */
         673                 :            :
         674                 :            :     Py_buffer buffer;
         675                 :            :     char *input_buffer;
         676                 :            :     char *input_line;
         677                 :            :     Py_ssize_t input_len;
         678                 :            :     Py_ssize_t next_read_idx;
         679                 :            :     Py_ssize_t prefetched_idx;  /* index of first prefetched byte */
         680                 :            :
         681                 :            :     PyObject *read;             /* read() method of the input stream. */
         682                 :            :     PyObject *readinto;         /* readinto() method of the input stream. */
         683                 :            :     PyObject *readline;         /* readline() method of the input stream. */
         684                 :            :     PyObject *peek;             /* peek() method of the input stream, or NULL */
         685                 :            :     PyObject *buffers;          /* iterable of out-of-band buffers, or NULL */
         686                 :            :
         687                 :            :     char *encoding;             /* Name of the encoding to be used for
         688                 :            :                                    decoding strings pickled using Python
         689                 :            :                                    2.x. The default value is "ASCII" */
         690                 :            :     char *errors;               /* Name of errors handling scheme to used when
         691                 :            :                                    decoding strings. The default value is
         692                 :            :                                    "strict". */
         693                 :            :     Py_ssize_t *marks;          /* Mark stack, used for unpickling container
         694                 :            :                                    objects. */
         695                 :            :     Py_ssize_t num_marks;       /* Number of marks in the mark stack. */
         696                 :            :     Py_ssize_t marks_size;      /* Current allocated size of the mark stack. */
         697                 :            :     int proto;                  /* Protocol of the pickle loaded. */
         698                 :            :     int fix_imports;            /* Indicate whether Unpickler should fix
         699                 :            :                                    the name of globals pickled by Python 2.x. */
         700                 :            : } UnpicklerObject;
         701                 :            :
         702                 :            : typedef struct {
         703                 :            :     PyObject_HEAD
         704                 :            :     PicklerObject *pickler; /* Pickler whose memo table we're proxying. */
         705                 :            : }  PicklerMemoProxyObject;
         706                 :            :
         707                 :            : typedef struct {
         708                 :            :     PyObject_HEAD
         709                 :            :     UnpicklerObject *unpickler;
         710                 :            : } UnpicklerMemoProxyObject;
         711                 :            :
         712                 :            : /* Forward declarations */
         713                 :            : static int save(PicklerObject *, PyObject *, int);
         714                 :            : static int save_reduce(PicklerObject *, PyObject *, PyObject *);
         715                 :            : static PyTypeObject Pickler_Type;
         716                 :            : static PyTypeObject Unpickler_Type;
         717                 :            :
         718                 :            : #include "clinic/_pickle.c.h"
         719                 :            :
         720                 :            : /*************************************************************************
         721                 :            :  A custom hashtable mapping void* to Python ints. This is used by the pickler
         722                 :            :  for memoization. Using a custom hashtable rather than PyDict allows us to skip
         723                 :            :  a bunch of unnecessary object creation. This makes a huge performance
         724                 :            :  difference. */
         725                 :            :
         726                 :            : #define MT_MINSIZE 8
         727                 :            : #define PERTURB_SHIFT 5
         728                 :            :
         729                 :            :
         730                 :            : static PyMemoTable *
         731                 :          0 : PyMemoTable_New(void)
         732                 :            : {
         733                 :          0 :     PyMemoTable *memo = PyMem_Malloc(sizeof(PyMemoTable));
         734         [ #  # ]:          0 :     if (memo == NULL) {
         735                 :          0 :         PyErr_NoMemory();
         736                 :          0 :         return NULL;
         737                 :            :     }
         738                 :            :
         739                 :          0 :     memo->mt_used = 0;
         740                 :          0 :     memo->mt_allocated = MT_MINSIZE;
         741                 :          0 :     memo->mt_mask = MT_MINSIZE - 1;
         742                 :          0 :     memo->mt_table = PyMem_Malloc(MT_MINSIZE * sizeof(PyMemoEntry));
         743         [ #  # ]:          0 :     if (memo->mt_table == NULL) {
         744                 :          0 :         PyMem_Free(memo);
         745                 :          0 :         PyErr_NoMemory();
         746                 :          0 :         return NULL;
         747                 :            :     }
         748                 :          0 :     memset(memo->mt_table, 0, MT_MINSIZE * sizeof(PyMemoEntry));
         749                 :            :
         750                 :          0 :     return memo;
         751                 :            : }
         752                 :            :
         753                 :            : static PyMemoTable *
         754                 :          0 : PyMemoTable_Copy(PyMemoTable *self)
         755                 :            : {
         756                 :          0 :     PyMemoTable *new = PyMemoTable_New();
         757         [ #  # ]:          0 :     if (new == NULL)
         758                 :          0 :         return NULL;
         759                 :            :
         760                 :          0 :     new->mt_used = self->mt_used;
         761                 :          0 :     new->mt_allocated = self->mt_allocated;
         762                 :          0 :     new->mt_mask = self->mt_mask;
         763                 :            :     /* The table we get from _New() is probably smaller than we wanted.
         764                 :            :        Free it and allocate one that's the right size. */
         765                 :          0 :     PyMem_Free(new->mt_table);
         766         [ #  # ]:          0 :     new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated);
         767         [ #  # ]:          0 :     if (new->mt_table == NULL) {
         768                 :          0 :         PyMem_Free(new);
         769                 :          0 :         PyErr_NoMemory();
         770                 :          0 :         return NULL;
         771                 :            :     }
         772         [ #  # ]:          0 :     for (size_t i = 0; i < self->mt_allocated; i++) {
         773                 :          0 :         Py_XINCREF(self->mt_table[i].me_key);
         774                 :            :     }
         775                 :          0 :     memcpy(new->mt_table, self->mt_table,
         776                 :          0 :            sizeof(PyMemoEntry) * self->mt_allocated);
         777                 :            :
         778                 :          0 :     return new;
         779                 :            : }
         780                 :            :
         781                 :            : static Py_ssize_t
         782                 :          0 : PyMemoTable_Size(PyMemoTable *self)
         783                 :            : {
         784                 :          0 :     return self->mt_used;
         785                 :            : }
         786                 :            :
         787                 :            : static int
         788                 :          0 : PyMemoTable_Clear(PyMemoTable *self)
         789                 :            : {
         790                 :          0 :     Py_ssize_t i = self->mt_allocated;
         791                 :            :
         792         [ #  # ]:          0 :     while (--i >= 0) {
         793                 :          0 :         Py_XDECREF(self->mt_table[i].me_key);
         794                 :            :     }
         795                 :          0 :     self->mt_used = 0;
         796                 :          0 :     memset(self->mt_table, 0, self->mt_allocated * sizeof(PyMemoEntry));
         797                 :          0 :     return 0;
         798                 :            : }
         799                 :            :
         800                 :            : static void
         801                 :          0 : PyMemoTable_Del(PyMemoTable *self)
         802                 :            : {
         803         [ #  # ]:          0 :     if (self == NULL)
         804                 :          0 :         return;
         805                 :          0 :     PyMemoTable_Clear(self);
         806                 :            :
         807                 :          0 :     PyMem_Free(self->mt_table);
         808                 :          0 :     PyMem_Free(self);
         809                 :            : }
         810                 :            :
         811                 :            : /* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup()
         812                 :            :    can be considerably simpler than dictobject.c's lookdict(). */
         813                 :            : static PyMemoEntry *
         814                 :          0 : _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
         815                 :            : {
         816                 :            :     size_t i;
         817                 :            :     size_t perturb;
         818                 :          0 :     size_t mask = self->mt_mask;
         819                 :          0 :     PyMemoEntry *table = self->mt_table;
         820                 :            :     PyMemoEntry *entry;
         821                 :          0 :     Py_hash_t hash = (Py_hash_t)key >> 3;
         822                 :            :
         823                 :          0 :     i = hash & mask;
         824                 :          0 :     entry = &table[i];
         825   [ #  #  #  # ]:          0 :     if (entry->me_key == NULL || entry->me_key == key)
         826                 :          0 :         return entry;
         827                 :            :
         828                 :          0 :     for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
         829                 :          0 :         i = (i << 2) + i + perturb + 1;
         830                 :          0 :         entry = &table[i & mask];
         831   [ #  #  #  # ]:          0 :         if (entry->me_key == NULL || entry->me_key == key)
         832                 :          0 :             return entry;
         833                 :            :     }
         834                 :            :     Py_UNREACHABLE();
         835                 :            : }
         836                 :            :
         837                 :            : /* Returns -1 on failure, 0 on success. */
         838                 :            : static int
         839                 :          0 : _PyMemoTable_ResizeTable(PyMemoTable *self, size_t min_size)
         840                 :            : {
         841                 :          0 :     PyMemoEntry *oldtable = NULL;
         842                 :            :     PyMemoEntry *oldentry, *newentry;
         843                 :          0 :     size_t new_size = MT_MINSIZE;
         844                 :            :     size_t to_process;
         845                 :            :
         846                 :            :     assert(min_size > 0);
         847                 :            :
         848         [ #  # ]:          0 :     if (min_size > PY_SSIZE_T_MAX) {
         849                 :          0 :         PyErr_NoMemory();
         850                 :          0 :         return -1;
         851                 :            :     }
         852                 :            :
         853                 :            :     /* Find the smallest valid table size >= min_size. */
         854         [ #  # ]:          0 :     while (new_size < min_size) {
         855                 :          0 :         new_size <<= 1;
         856                 :            :     }
         857                 :            :     /* new_size needs to be a power of two. */
         858                 :            :     assert((new_size & (new_size - 1)) == 0);
         859                 :            :
         860                 :            :     /* Allocate new table. */
         861                 :          0 :     oldtable = self->mt_table;
         862         [ #  # ]:          0 :     self->mt_table = PyMem_NEW(PyMemoEntry, new_size);
         863         [ #  # ]:          0 :     if (self->mt_table == NULL) {
         864                 :          0 :         self->mt_table = oldtable;
         865                 :          0 :         PyErr_NoMemory();
         866                 :          0 :         return -1;
         867                 :            :     }
         868                 :          0 :     self->mt_allocated = new_size;
         869                 :          0 :     self->mt_mask = new_size - 1;
         870                 :          0 :     memset(self->mt_table, 0, sizeof(PyMemoEntry) * new_size);
         871                 :            :
         872                 :            :     /* Copy entries from the old table. */
         873                 :          0 :     to_process = self->mt_used;
         874         [ #  # ]:          0 :     for (oldentry = oldtable; to_process > 0; oldentry++) {
         875         [ #  # ]:          0 :         if (oldentry->me_key != NULL) {
         876                 :          0 :             to_process--;
         877                 :            :             /* newentry is a pointer to a chunk of the new
         878                 :            :                mt_table, so we're setting the key:value pair
         879                 :            :                in-place. */
         880                 :          0 :             newentry = _PyMemoTable_Lookup(self, oldentry->me_key);
         881                 :          0 :             newentry->me_key = oldentry->me_key;
         882                 :          0 :             newentry->me_value = oldentry->me_value;
         883                 :            :         }
         884                 :            :     }
         885                 :            :
         886                 :            :     /* Deallocate the old table. */
         887                 :          0 :     PyMem_Free(oldtable);
         888                 :          0 :     return 0;
         889                 :            : }
         890                 :            :
         891                 :            : /* Returns NULL on failure, a pointer to the value otherwise. */
         892                 :            : static Py_ssize_t *
         893                 :          0 : PyMemoTable_Get(PyMemoTable *self, PyObject *key)
         894                 :            : {
         895                 :          0 :     PyMemoEntry *entry = _PyMemoTable_Lookup(self, key);
         896         [ #  # ]:          0 :     if (entry->me_key == NULL)
         897                 :          0 :         return NULL;
         898                 :          0 :     return &entry->me_value;
         899                 :            : }
         900                 :            :
         901                 :            : /* Returns -1 on failure, 0 on success. */
         902                 :            : static int
         903                 :          0 : PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
         904                 :            : {
         905                 :            :     PyMemoEntry *entry;
         906                 :            :
         907                 :            :     assert(key != NULL);
         908                 :            :
         909                 :          0 :     entry = _PyMemoTable_Lookup(self, key);
         910         [ #  # ]:          0 :     if (entry->me_key != NULL) {
         911                 :          0 :         entry->me_value = value;
         912                 :          0 :         return 0;
         913                 :            :     }
         914                 :          0 :     entry->me_key = Py_NewRef(key);
         915                 :          0 :     entry->me_value = value;
         916                 :          0 :     self->mt_used++;
         917                 :            :
         918                 :            :     /* If we added a key, we can safely resize. Otherwise just return!
         919                 :            :      * If used >= 2/3 size, adjust size. Normally, this quaduples the size.
         920                 :            :      *
         921                 :            :      * Quadrupling the size improves average table sparseness
         922                 :            :      * (reducing collisions) at the cost of some memory. It also halves
         923                 :            :      * the number of expensive resize operations in a growing memo table.
         924                 :            :      *
         925                 :            :      * Very large memo tables (over 50K items) use doubling instead.
         926                 :            :      * This may help applications with severe memory constraints.
         927                 :            :      */
         928   [ #  #  #  # ]:          0 :     if (SIZE_MAX / 3 >= self->mt_used && self->mt_used * 3 < self->mt_allocated * 2) {
         929                 :          0 :         return 0;
         930                 :            :     }
         931                 :            :     // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
         932         [ #  # ]:          0 :     size_t desired_size = (self->mt_used > 50000 ? 2 : 4) * self->mt_used;
         933                 :          0 :     return _PyMemoTable_ResizeTable(self, desired_size);
         934                 :            : }
         935                 :            :
         936                 :            : #undef MT_MINSIZE
         937                 :            : #undef PERTURB_SHIFT
         938                 :            :
         939                 :            : /*************************************************************************/
         940                 :            :
         941                 :            :
         942                 :            : static int
         943                 :          0 : _Pickler_ClearBuffer(PicklerObject *self)
         944                 :            : {
         945                 :          0 :     Py_XSETREF(self->output_buffer,
         946                 :            :               PyBytes_FromStringAndSize(NULL, self->max_output_len));
         947         [ #  # ]:          0 :     if (self->output_buffer == NULL)
         948                 :          0 :         return -1;
         949                 :          0 :     self->output_len = 0;
         950                 :          0 :     self->frame_start = -1;
         951                 :          0 :     return 0;
         952                 :            : }
         953                 :            :
         954                 :            : static void
         955                 :          0 : _write_size64(char *out, size_t value)
         956                 :            : {
         957                 :            :     size_t i;
         958                 :            :
         959                 :            :     static_assert(sizeof(size_t) <= 8, "size_t is larger than 64-bit");
         960                 :            :
         961         [ #  # ]:          0 :     for (i = 0; i < sizeof(size_t); i++) {
         962                 :          0 :         out[i] = (unsigned char)((value >> (8 * i)) & 0xff);
         963                 :            :     }
         964         [ #  # ]:          0 :     for (i = sizeof(size_t); i < 8; i++) {
         965                 :          0 :         out[i] = 0;
         966                 :            :     }
         967                 :          0 : }
         968                 :            :
         969                 :            : static int
         970                 :          0 : _Pickler_CommitFrame(PicklerObject *self)
         971                 :            : {
         972                 :            :     size_t frame_len;
         973                 :            :     char *qdata;
         974                 :            :
         975   [ #  #  #  # ]:          0 :     if (!self->framing || self->frame_start == -1)
         976                 :          0 :         return 0;
         977                 :          0 :     frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE;
         978                 :          0 :     qdata = PyBytes_AS_STRING(self->output_buffer) + self->frame_start;
         979         [ #  # ]:          0 :     if (frame_len >= FRAME_SIZE_MIN) {
         980                 :          0 :         qdata[0] = FRAME;
         981                 :          0 :         _write_size64(qdata + 1, frame_len);
         982                 :            :     }
         983                 :            :     else {
         984                 :          0 :         memmove(qdata, qdata + FRAME_HEADER_SIZE, frame_len);
         985                 :          0 :         self->output_len -= FRAME_HEADER_SIZE;
         986                 :            :     }
         987                 :          0 :     self->frame_start = -1;
         988                 :          0 :     return 0;
         989                 :            : }
         990                 :            :
         991                 :            : static PyObject *
         992                 :          0 : _Pickler_GetString(PicklerObject *self)
         993                 :            : {
         994                 :          0 :     PyObject *output_buffer = self->output_buffer;
         995                 :            :
         996                 :            :     assert(self->output_buffer != NULL);
         997                 :            :
         998         [ #  # ]:          0 :     if (_Pickler_CommitFrame(self))
         999                 :          0 :         return NULL;
        1000                 :            :
        1001                 :          0 :     self->output_buffer = NULL;
        1002                 :            :     /* Resize down to exact size */
        1003         [ #  # ]:          0 :     if (_PyBytes_Resize(&output_buffer, self->output_len) < 0)
        1004                 :          0 :         return NULL;
        1005                 :          0 :     return output_buffer;
        1006                 :            : }
        1007                 :            :
        1008                 :            : static int
        1009                 :          0 : _Pickler_FlushToFile(PicklerObject *self)
        1010                 :            : {
        1011                 :            :     PyObject *output, *result;
        1012                 :            :
        1013                 :            :     assert(self->write != NULL);
        1014                 :            :
        1015                 :            :     /* This will commit the frame first */
        1016                 :          0 :     output = _Pickler_GetString(self);
        1017         [ #  # ]:          0 :     if (output == NULL)
        1018                 :          0 :         return -1;
        1019                 :            :
        1020                 :          0 :     result = _Pickle_FastCall(self->write, output);
        1021                 :          0 :     Py_XDECREF(result);
        1022         [ #  # ]:          0 :     return (result == NULL) ? -1 : 0;
        1023                 :            : }
        1024                 :            :
        1025                 :            : static int
        1026                 :          0 : _Pickler_OpcodeBoundary(PicklerObject *self)
        1027                 :            : {
        1028                 :            :     Py_ssize_t frame_len;
        1029                 :            :
        1030   [ #  #  #  # ]:          0 :     if (!self->framing || self->frame_start == -1) {
        1031                 :          0 :         return 0;
        1032                 :            :     }
        1033                 :          0 :     frame_len = self->output_len - self->frame_start - FRAME_HEADER_SIZE;
        1034         [ #  # ]:          0 :     if (frame_len >= FRAME_SIZE_TARGET) {
        1035         [ #  # ]:          0 :         if(_Pickler_CommitFrame(self)) {
        1036                 :          0 :             return -1;
        1037                 :            :         }
        1038                 :            :         /* Flush the content of the committed frame to the underlying
        1039                 :            :          * file and reuse the pickler buffer for the next frame so as
        1040                 :            :          * to limit memory usage when dumping large complex objects to
        1041                 :            :          * a file.
        1042                 :            :          *
        1043                 :            :          * self->write is NULL when called via dumps.
        1044                 :            :          */
        1045         [ #  # ]:          0 :         if (self->write != NULL) {
        1046         [ #  # ]:          0 :             if (_Pickler_FlushToFile(self) < 0) {
        1047                 :          0 :                 return -1;
        1048                 :            :             }
        1049         [ #  # ]:          0 :             if (_Pickler_ClearBuffer(self) < 0) {
        1050                 :          0 :                 return -1;
        1051                 :            :             }
        1052                 :            :         }
        1053                 :            :     }
        1054                 :          0 :     return 0;
        1055                 :            : }
        1056                 :            :
        1057                 :            : static Py_ssize_t
        1058                 :          0 : _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
        1059                 :            : {
        1060                 :            :     Py_ssize_t i, n, required;
        1061                 :            :     char *buffer;
        1062                 :            :     int need_new_frame;
        1063                 :            :
        1064                 :            :     assert(s != NULL);
        1065   [ #  #  #  # ]:          0 :     need_new_frame = (self->framing && self->frame_start == -1);
        1066                 :            :
        1067         [ #  # ]:          0 :     if (need_new_frame)
        1068                 :          0 :         n = data_len + FRAME_HEADER_SIZE;
        1069                 :            :     else
        1070                 :          0 :         n = data_len;
        1071                 :            :
        1072                 :          0 :     required = self->output_len + n;
        1073         [ #  # ]:          0 :     if (required > self->max_output_len) {
        1074                 :            :         /* Make place in buffer for the pickle chunk */
        1075         [ #  # ]:          0 :         if (self->output_len >= PY_SSIZE_T_MAX / 2 - n) {
        1076                 :          0 :             PyErr_NoMemory();
        1077                 :          0 :             return -1;
        1078                 :            :         }
        1079                 :          0 :         self->max_output_len = (self->output_len + n) / 2 * 3;
        1080         [ #  # ]:          0 :         if (_PyBytes_Resize(&self->output_buffer, self->max_output_len) < 0)
        1081                 :          0 :             return -1;
        1082                 :            :     }
        1083                 :          0 :     buffer = PyBytes_AS_STRING(self->output_buffer);
        1084         [ #  # ]:          0 :     if (need_new_frame) {
        1085                 :            :         /* Setup new frame */
        1086                 :          0 :         Py_ssize_t frame_start = self->output_len;
        1087                 :          0 :         self->frame_start = frame_start;
        1088         [ #  # ]:          0 :         for (i = 0; i < FRAME_HEADER_SIZE; i++) {
        1089                 :            :             /* Write an invalid value, for debugging */
        1090                 :          0 :             buffer[frame_start + i] = 0xFE;
        1091                 :            :         }
        1092                 :          0 :         self->output_len += FRAME_HEADER_SIZE;
        1093                 :            :     }
        1094         [ #  # ]:          0 :     if (data_len < 8) {
        1095                 :            :         /* This is faster than memcpy when the string is short. */
        1096         [ #  # ]:          0 :         for (i = 0; i < data_len; i++) {
        1097                 :          0 :             buffer[self->output_len + i] = s[i];
        1098                 :            :         }
        1099                 :            :     }
        1100                 :            :     else {
        1101                 :          0 :         memcpy(buffer + self->output_len, s, data_len);
        1102                 :            :     }
        1103                 :          0 :     self->output_len += data_len;
        1104                 :          0 :     return data_len;
        1105                 :            : }
        1106                 :            :
        1107                 :            : static PicklerObject *
        1108                 :          0 : _Pickler_New(void)
        1109                 :            : {
        1110                 :            :     PicklerObject *self;
        1111                 :            :
        1112                 :          0 :     self = PyObject_GC_New(PicklerObject, &Pickler_Type);
        1113         [ #  # ]:          0 :     if (self == NULL)
        1114                 :          0 :         return NULL;
        1115                 :            :
        1116                 :          0 :     self->pers_func = NULL;
        1117                 :          0 :     self->dispatch_table = NULL;
        1118                 :          0 :     self->buffer_callback = NULL;
        1119                 :          0 :     self->write = NULL;
        1120                 :          0 :     self->proto = 0;
        1121                 :          0 :     self->bin = 0;
        1122                 :          0 :     self->framing = 0;
        1123                 :          0 :     self->frame_start = -1;
        1124                 :          0 :     self->fast = 0;
        1125                 :          0 :     self->fast_nesting = 0;
        1126                 :          0 :     self->fix_imports = 0;
        1127                 :          0 :     self->fast_memo = NULL;
        1128                 :          0 :     self->max_output_len = WRITE_BUF_SIZE;
        1129                 :          0 :     self->output_len = 0;
        1130                 :          0 :     self->reducer_override = NULL;
        1131                 :            :
        1132                 :          0 :     self->memo = PyMemoTable_New();
        1133                 :          0 :     self->output_buffer = PyBytes_FromStringAndSize(NULL,
        1134                 :            :                                                     self->max_output_len);
        1135                 :            :
        1136   [ #  #  #  # ]:          0 :     if (self->memo == NULL || self->output_buffer == NULL) {
        1137                 :          0 :         Py_DECREF(self);
        1138                 :          0 :         return NULL;
        1139                 :            :     }
        1140                 :            :
        1141                 :          0 :     PyObject_GC_Track(self);
        1142                 :          0 :     return self;
        1143                 :            : }
        1144                 :            :
        1145                 :            : static int
        1146                 :          0 : _Pickler_SetProtocol(PicklerObject *self, PyObject *protocol, int fix_imports)
        1147                 :            : {
        1148                 :            :     long proto;
        1149                 :            :
        1150         [ #  # ]:          0 :     if (protocol == Py_None) {
        1151                 :          0 :         proto = DEFAULT_PROTOCOL;
        1152                 :            :     }
        1153                 :            :     else {
        1154                 :          0 :         proto = PyLong_AsLong(protocol);
        1155         [ #  # ]:          0 :         if (proto < 0) {
        1156   [ #  #  #  # ]:          0 :             if (proto == -1 && PyErr_Occurred())
        1157                 :          0 :                 return -1;
        1158                 :          0 :             proto = HIGHEST_PROTOCOL;
        1159                 :            :         }
        1160         [ #  # ]:          0 :         else if (proto > HIGHEST_PROTOCOL) {
        1161                 :          0 :             PyErr_Format(PyExc_ValueError, "pickle protocol must be <= %d",
        1162                 :            :                          HIGHEST_PROTOCOL);
        1163                 :          0 :             return -1;
        1164                 :            :         }
        1165                 :            :     }
        1166                 :          0 :     self->proto = (int)proto;
        1167                 :          0 :     self->bin = proto > 0;
        1168   [ #  #  #  # ]:          0 :     self->fix_imports = fix_imports && proto < 3;
        1169                 :          0 :     return 0;
        1170                 :            : }
        1171                 :            :
        1172                 :            : /* Returns -1 (with an exception set) on failure, 0 on success. This may
        1173                 :            :    be called once on a freshly created Pickler. */
        1174                 :            : static int
        1175                 :          0 : _Pickler_SetOutputStream(PicklerObject *self, PyObject *file)
        1176                 :            : {
        1177                 :            :     assert(file != NULL);
        1178         [ #  # ]:          0 :     if (_PyObject_LookupAttr(file, &_Py_ID(write), &self->write) < 0) {
        1179                 :          0 :         return -1;
        1180                 :            :     }
        1181         [ #  # ]:          0 :     if (self->write == NULL) {
        1182                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1183                 :            :                         "file must have a 'write' attribute");
        1184                 :          0 :         return -1;
        1185                 :            :     }
        1186                 :            :
        1187                 :          0 :     return 0;
        1188                 :            : }
        1189                 :            :
        1190                 :            : static int
        1191                 :          0 : _Pickler_SetBufferCallback(PicklerObject *self, PyObject *buffer_callback)
        1192                 :            : {
        1193         [ #  # ]:          0 :     if (buffer_callback == Py_None) {
        1194                 :          0 :         buffer_callback = NULL;
        1195                 :            :     }
        1196   [ #  #  #  # ]:          0 :     if (buffer_callback != NULL && self->proto < 5) {
        1197                 :          0 :         PyErr_SetString(PyExc_ValueError,
        1198                 :            :                         "buffer_callback needs protocol >= 5");
        1199                 :          0 :         return -1;
        1200                 :            :     }
        1201                 :            :
        1202                 :          0 :     self->buffer_callback = Py_XNewRef(buffer_callback);
        1203                 :          0 :     return 0;
        1204                 :            : }
        1205                 :            :
        1206                 :            : /* Returns the size of the input on success, -1 on failure. This takes its
        1207                 :            :    own reference to `input`. */
        1208                 :            : static Py_ssize_t
        1209                 :          0 : _Unpickler_SetStringInput(UnpicklerObject *self, PyObject *input)
        1210                 :            : {
        1211         [ #  # ]:          0 :     if (self->buffer.buf != NULL)
        1212                 :          0 :         PyBuffer_Release(&self->buffer);
        1213         [ #  # ]:          0 :     if (PyObject_GetBuffer(input, &self->buffer, PyBUF_CONTIG_RO) < 0)
        1214                 :          0 :         return -1;
        1215                 :          0 :     self->input_buffer = self->buffer.buf;
        1216                 :          0 :     self->input_len = self->buffer.len;
        1217                 :          0 :     self->next_read_idx = 0;
        1218                 :          0 :     self->prefetched_idx = self->input_len;
        1219                 :          0 :     return self->input_len;
        1220                 :            : }
        1221                 :            :
        1222                 :            : static int
        1223                 :          0 : bad_readline(void)
        1224                 :            : {
        1225                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        1226                 :          0 :     PyErr_SetString(st->UnpicklingError, "pickle data was truncated");
        1227                 :          0 :     return -1;
        1228                 :            : }
        1229                 :            :
        1230                 :            : /* Skip any consumed data that was only prefetched using peek() */
        1231                 :            : static int
        1232                 :          0 : _Unpickler_SkipConsumed(UnpicklerObject *self)
        1233                 :            : {
        1234                 :            :     Py_ssize_t consumed;
        1235                 :            :     PyObject *r;
        1236                 :            :
        1237                 :          0 :     consumed = self->next_read_idx - self->prefetched_idx;
        1238         [ #  # ]:          0 :     if (consumed <= 0)
        1239                 :          0 :         return 0;
        1240                 :            :
        1241                 :            :     assert(self->peek);  /* otherwise we did something wrong */
        1242                 :            :     /* This makes a useless copy... */
        1243                 :          0 :     r = PyObject_CallFunction(self->read, "n", consumed);
        1244         [ #  # ]:          0 :     if (r == NULL)
        1245                 :          0 :         return -1;
        1246                 :          0 :     Py_DECREF(r);
        1247                 :            :
        1248                 :          0 :     self->prefetched_idx = self->next_read_idx;
        1249                 :          0 :     return 0;
        1250                 :            : }
        1251                 :            :
        1252                 :            : static const Py_ssize_t READ_WHOLE_LINE = -1;
        1253                 :            :
        1254                 :            : /* If reading from a file, we need to only pull the bytes we need, since there
        1255                 :            :    may be multiple pickle objects arranged contiguously in the same input
        1256                 :            :    buffer.
        1257                 :            :
        1258                 :            :    If `n` is READ_WHOLE_LINE, read a whole line. Otherwise, read up to `n`
        1259                 :            :    bytes from the input stream/buffer.
        1260                 :            :
        1261                 :            :    Update the unpickler's input buffer with the newly-read data. Returns -1 on
        1262                 :            :    failure; on success, returns the number of bytes read from the file.
        1263                 :            :
        1264                 :            :    On success, self->input_len will be 0; this is intentional so that when
        1265                 :            :    unpickling from a file, the "we've run out of data" code paths will trigger,
        1266                 :            :    causing the Unpickler to go back to the file for more data. Use the returned
        1267                 :            :    size to tell you how much data you can process. */
        1268                 :            : static Py_ssize_t
        1269                 :          0 : _Unpickler_ReadFromFile(UnpicklerObject *self, Py_ssize_t n)
        1270                 :            : {
        1271                 :            :     PyObject *data;
        1272                 :            :     Py_ssize_t read_size;
        1273                 :            :
        1274                 :            :     assert(self->read != NULL);
        1275                 :            :
        1276         [ #  # ]:          0 :     if (_Unpickler_SkipConsumed(self) < 0)
        1277                 :          0 :         return -1;
        1278                 :            :
        1279         [ #  # ]:          0 :     if (n == READ_WHOLE_LINE) {
        1280                 :          0 :         data = PyObject_CallNoArgs(self->readline);
        1281                 :            :     }
        1282                 :            :     else {
        1283                 :            :         PyObject *len;
        1284                 :            :         /* Prefetch some data without advancing the file pointer, if possible */
        1285   [ #  #  #  # ]:          0 :         if (self->peek && n < PREFETCH) {
        1286                 :          0 :             len = PyLong_FromSsize_t(PREFETCH);
        1287         [ #  # ]:          0 :             if (len == NULL)
        1288                 :          0 :                 return -1;
        1289                 :          0 :             data = _Pickle_FastCall(self->peek, len);
        1290         [ #  # ]:          0 :             if (data == NULL) {
        1291         [ #  # ]:          0 :                 if (!PyErr_ExceptionMatches(PyExc_NotImplementedError))
        1292                 :          0 :                     return -1;
        1293                 :            :                 /* peek() is probably not supported by the given file object */
        1294                 :          0 :                 PyErr_Clear();
        1295         [ #  # ]:          0 :                 Py_CLEAR(self->peek);
        1296                 :            :             }
        1297                 :            :             else {
        1298                 :          0 :                 read_size = _Unpickler_SetStringInput(self, data);
        1299                 :          0 :                 Py_DECREF(data);
        1300                 :          0 :                 self->prefetched_idx = 0;
        1301         [ #  # ]:          0 :                 if (n <= read_size)
        1302                 :          0 :                     return n;
        1303                 :            :             }
        1304                 :            :         }
        1305                 :          0 :         len = PyLong_FromSsize_t(n);
        1306         [ #  # ]:          0 :         if (len == NULL)
        1307                 :          0 :             return -1;
        1308                 :          0 :         data = _Pickle_FastCall(self->read, len);
        1309                 :            :     }
        1310         [ #  # ]:          0 :     if (data == NULL)
        1311                 :          0 :         return -1;
        1312                 :            :
        1313                 :          0 :     read_size = _Unpickler_SetStringInput(self, data);
        1314                 :          0 :     Py_DECREF(data);
        1315                 :          0 :     return read_size;
        1316                 :            : }
        1317                 :            :
        1318                 :            : /* Don't call it directly: use _Unpickler_Read() */
        1319                 :            : static Py_ssize_t
        1320                 :          0 : _Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n)
        1321                 :            : {
        1322                 :            :     Py_ssize_t num_read;
        1323                 :            :
        1324                 :          0 :     *s = NULL;
        1325         [ #  # ]:          0 :     if (self->next_read_idx > PY_SSIZE_T_MAX - n) {
        1326                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        1327                 :          0 :         PyErr_SetString(st->UnpicklingError,
        1328                 :            :                         "read would overflow (invalid bytecode)");
        1329                 :          0 :         return -1;
        1330                 :            :     }
        1331                 :            :
        1332                 :            :     /* This case is handled by the _Unpickler_Read() macro for efficiency */
        1333                 :            :     assert(self->next_read_idx + n > self->input_len);
        1334                 :            :
        1335         [ #  # ]:          0 :     if (!self->read)
        1336                 :          0 :         return bad_readline();
        1337                 :            :
        1338                 :            :     /* Extend the buffer to satisfy desired size */
        1339                 :          0 :     num_read = _Unpickler_ReadFromFile(self, n);
        1340         [ #  # ]:          0 :     if (num_read < 0)
        1341                 :          0 :         return -1;
        1342         [ #  # ]:          0 :     if (num_read < n)
        1343                 :          0 :         return bad_readline();
        1344                 :          0 :     *s = self->input_buffer;
        1345                 :          0 :     self->next_read_idx = n;
        1346                 :          0 :     return n;
        1347                 :            : }
        1348                 :            :
        1349                 :            : /* Read `n` bytes from the unpickler's data source, storing the result in `buf`.
        1350                 :            :  *
        1351                 :            :  * This should only be used for non-small data reads where potentially
        1352                 :            :  * avoiding a copy is beneficial.  This method does not try to prefetch
        1353                 :            :  * more data into the input buffer.
        1354                 :            :  *
        1355                 :            :  * _Unpickler_Read() is recommended in most cases.
        1356                 :            :  */
        1357                 :            : static Py_ssize_t
        1358                 :          0 : _Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
        1359                 :            : {
        1360                 :            :     assert(n != READ_WHOLE_LINE);
        1361                 :            :
        1362                 :            :     /* Read from available buffer data, if any */
        1363                 :          0 :     Py_ssize_t in_buffer = self->input_len - self->next_read_idx;
        1364         [ #  # ]:          0 :     if (in_buffer > 0) {
        1365                 :          0 :         Py_ssize_t to_read = Py_MIN(in_buffer, n);
        1366                 :          0 :         memcpy(buf, self->input_buffer + self->next_read_idx, to_read);
        1367                 :          0 :         self->next_read_idx += to_read;
        1368                 :          0 :         buf += to_read;
        1369                 :          0 :         n -= to_read;
        1370         [ #  # ]:          0 :         if (n == 0) {
        1371                 :            :             /* Entire read was satisfied from buffer */
        1372                 :          0 :             return n;
        1373                 :            :         }
        1374                 :            :     }
        1375                 :            :
        1376                 :            :     /* Read from file */
        1377         [ #  # ]:          0 :     if (!self->read) {
        1378                 :            :         /* We're unpickling memory, this means the input is truncated */
        1379                 :          0 :         return bad_readline();
        1380                 :            :     }
        1381         [ #  # ]:          0 :     if (_Unpickler_SkipConsumed(self) < 0) {
        1382                 :          0 :         return -1;
        1383                 :            :     }
        1384                 :            :
        1385         [ #  # ]:          0 :     if (!self->readinto) {
        1386                 :            :         /* readinto() not supported on file-like object, fall back to read()
        1387                 :            :          * and copy into destination buffer (bpo-39681) */
        1388                 :          0 :         PyObject* len = PyLong_FromSsize_t(n);
        1389         [ #  # ]:          0 :         if (len == NULL) {
        1390                 :          0 :             return -1;
        1391                 :            :         }
        1392                 :          0 :         PyObject* data = _Pickle_FastCall(self->read, len);
        1393         [ #  # ]:          0 :         if (data == NULL) {
        1394                 :          0 :             return -1;
        1395                 :            :         }
        1396         [ #  # ]:          0 :         if (!PyBytes_Check(data)) {
        1397                 :          0 :             PyErr_Format(PyExc_ValueError,
        1398                 :            :                          "read() returned non-bytes object (%R)",
        1399                 :            :                          Py_TYPE(data));
        1400                 :          0 :             Py_DECREF(data);
        1401                 :          0 :             return -1;
        1402                 :            :         }
        1403                 :          0 :         Py_ssize_t read_size = PyBytes_GET_SIZE(data);
        1404         [ #  # ]:          0 :         if (read_size < n) {
        1405                 :          0 :             Py_DECREF(data);
        1406                 :          0 :             return bad_readline();
        1407                 :            :         }
        1408                 :          0 :         memcpy(buf, PyBytes_AS_STRING(data), n);
        1409                 :          0 :         Py_DECREF(data);
        1410                 :          0 :         return n;
        1411                 :            :     }
        1412                 :            :
        1413                 :            :     /* Call readinto() into user buffer */
        1414                 :          0 :     PyObject *buf_obj = PyMemoryView_FromMemory(buf, n, PyBUF_WRITE);
        1415         [ #  # ]:          0 :     if (buf_obj == NULL) {
        1416                 :          0 :         return -1;
        1417                 :            :     }
        1418                 :          0 :     PyObject *read_size_obj = _Pickle_FastCall(self->readinto, buf_obj);
        1419         [ #  # ]:          0 :     if (read_size_obj == NULL) {
        1420                 :          0 :         return -1;
        1421                 :            :     }
        1422                 :          0 :     Py_ssize_t read_size = PyLong_AsSsize_t(read_size_obj);
        1423                 :          0 :     Py_DECREF(read_size_obj);
        1424                 :            :
        1425         [ #  # ]:          0 :     if (read_size < 0) {
        1426         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        1427                 :          0 :             PyErr_SetString(PyExc_ValueError,
        1428                 :            :                             "readinto() returned negative size");
        1429                 :            :         }
        1430                 :          0 :         return -1;
        1431                 :            :     }
        1432         [ #  # ]:          0 :     if (read_size < n) {
        1433                 :          0 :         return bad_readline();
        1434                 :            :     }
        1435                 :          0 :     return n;
        1436                 :            : }
        1437                 :            :
        1438                 :            : /* Read `n` bytes from the unpickler's data source, storing the result in `*s`.
        1439                 :            :
        1440                 :            :    This should be used for all data reads, rather than accessing the unpickler's
        1441                 :            :    input buffer directly. This method deals correctly with reading from input
        1442                 :            :    streams, which the input buffer doesn't deal with.
        1443                 :            :
        1444                 :            :    Note that when reading from a file-like object, self->next_read_idx won't
        1445                 :            :    be updated (it should remain at 0 for the entire unpickling process). You
        1446                 :            :    should use this function's return value to know how many bytes you can
        1447                 :            :    consume.
        1448                 :            :
        1449                 :            :    Returns -1 (with an exception set) on failure. On success, return the
        1450                 :            :    number of chars read. */
        1451                 :            : #define _Unpickler_Read(self, s, n) \
        1452                 :            :     (((n) <= (self)->input_len - (self)->next_read_idx)      \
        1453                 :            :      ? (*(s) = (self)->input_buffer + (self)->next_read_idx, \
        1454                 :            :         (self)->next_read_idx += (n),                        \
        1455                 :            :         (n))                                                 \
        1456                 :            :      : _Unpickler_ReadImpl(self, (s), (n)))
        1457                 :            :
        1458                 :            : static Py_ssize_t
        1459                 :          0 : _Unpickler_CopyLine(UnpicklerObject *self, char *line, Py_ssize_t len,
        1460                 :            :                     char **result)
        1461                 :            : {
        1462                 :          0 :     char *input_line = PyMem_Realloc(self->input_line, len + 1);
        1463         [ #  # ]:          0 :     if (input_line == NULL) {
        1464                 :          0 :         PyErr_NoMemory();
        1465                 :          0 :         return -1;
        1466                 :            :     }
        1467                 :            :
        1468                 :          0 :     memcpy(input_line, line, len);
        1469                 :          0 :     input_line[len] = '\0';
        1470                 :          0 :     self->input_line = input_line;
        1471                 :          0 :     *result = self->input_line;
        1472                 :          0 :     return len;
        1473                 :            : }
        1474                 :            :
        1475                 :            : /* Read a line from the input stream/buffer. If we run off the end of the input
        1476                 :            :    before hitting \n, raise an error.
        1477                 :            :
        1478                 :            :    Returns the number of chars read, or -1 on failure. */
        1479                 :            : static Py_ssize_t
        1480                 :          0 : _Unpickler_Readline(UnpicklerObject *self, char **result)
        1481                 :            : {
        1482                 :            :     Py_ssize_t i, num_read;
        1483                 :            :
        1484         [ #  # ]:          0 :     for (i = self->next_read_idx; i < self->input_len; i++) {
        1485         [ #  # ]:          0 :         if (self->input_buffer[i] == '\n') {
        1486                 :          0 :             char *line_start = self->input_buffer + self->next_read_idx;
        1487                 :          0 :             num_read = i - self->next_read_idx + 1;
        1488                 :          0 :             self->next_read_idx = i + 1;
        1489                 :          0 :             return _Unpickler_CopyLine(self, line_start, num_read, result);
        1490                 :            :         }
        1491                 :            :     }
        1492         [ #  # ]:          0 :     if (!self->read)
        1493                 :          0 :         return bad_readline();
        1494                 :            :
        1495                 :          0 :     num_read = _Unpickler_ReadFromFile(self, READ_WHOLE_LINE);
        1496         [ #  # ]:          0 :     if (num_read < 0)
        1497                 :          0 :         return -1;
        1498   [ #  #  #  # ]:          0 :     if (num_read == 0 || self->input_buffer[num_read - 1] != '\n')
        1499                 :          0 :         return bad_readline();
        1500                 :          0 :     self->next_read_idx = num_read;
        1501                 :          0 :     return _Unpickler_CopyLine(self, self->input_buffer, num_read, result);
        1502                 :            : }
        1503                 :            :
        1504                 :            : /* Returns -1 (with an exception set) on failure, 0 on success. The memo array
        1505                 :            :    will be modified in place. */
        1506                 :            : static int
        1507                 :          0 : _Unpickler_ResizeMemoList(UnpicklerObject *self, size_t new_size)
        1508                 :            : {
        1509                 :            :     size_t i;
        1510                 :            :
        1511                 :            :     assert(new_size > self->memo_size);
        1512                 :            :
        1513                 :          0 :     PyObject **memo_new = self->memo;
        1514         [ #  # ]:          0 :     PyMem_RESIZE(memo_new, PyObject *, new_size);
        1515         [ #  # ]:          0 :     if (memo_new == NULL) {
        1516                 :          0 :         PyErr_NoMemory();
        1517                 :          0 :         return -1;
        1518                 :            :     }
        1519                 :          0 :     self->memo = memo_new;
        1520         [ #  # ]:          0 :     for (i = self->memo_size; i < new_size; i++)
        1521                 :          0 :         self->memo[i] = NULL;
        1522                 :          0 :     self->memo_size = new_size;
        1523                 :          0 :     return 0;
        1524                 :            : }
        1525                 :            :
        1526                 :            : /* Returns NULL if idx is out of bounds. */
        1527                 :            : static PyObject *
        1528                 :          0 : _Unpickler_MemoGet(UnpicklerObject *self, size_t idx)
        1529                 :            : {
        1530         [ #  # ]:          0 :     if (idx >= self->memo_size)
        1531                 :          0 :         return NULL;
        1532                 :            :
        1533                 :          0 :     return self->memo[idx];
        1534                 :            : }
        1535                 :            :
        1536                 :            : /* Returns -1 (with an exception set) on failure, 0 on success.
        1537                 :            :    This takes its own reference to `value`. */
        1538                 :            : static int
        1539                 :          0 : _Unpickler_MemoPut(UnpicklerObject *self, size_t idx, PyObject *value)
        1540                 :            : {
        1541                 :            :     PyObject *old_item;
        1542                 :            :
        1543         [ #  # ]:          0 :     if (idx >= self->memo_size) {
        1544         [ #  # ]:          0 :         if (_Unpickler_ResizeMemoList(self, idx * 2) < 0)
        1545                 :          0 :             return -1;
        1546                 :            :         assert(idx < self->memo_size);
        1547                 :            :     }
        1548                 :          0 :     old_item = self->memo[idx];
        1549                 :          0 :     self->memo[idx] = Py_NewRef(value);
        1550         [ #  # ]:          0 :     if (old_item != NULL) {
        1551                 :          0 :         Py_DECREF(old_item);
        1552                 :            :     }
        1553                 :            :     else {
        1554                 :          0 :         self->memo_len++;
        1555                 :            :     }
        1556                 :          0 :     return 0;
        1557                 :            : }
        1558                 :            :
        1559                 :            : static PyObject **
        1560                 :          0 : _Unpickler_NewMemo(Py_ssize_t new_size)
        1561                 :            : {
        1562         [ #  # ]:          0 :     PyObject **memo = PyMem_NEW(PyObject *, new_size);
        1563         [ #  # ]:          0 :     if (memo == NULL) {
        1564                 :          0 :         PyErr_NoMemory();
        1565                 :          0 :         return NULL;
        1566                 :            :     }
        1567                 :          0 :     memset(memo, 0, new_size * sizeof(PyObject *));
        1568                 :          0 :     return memo;
        1569                 :            : }
        1570                 :            :
        1571                 :            : /* Free the unpickler's memo, taking care to decref any items left in it. */
        1572                 :            : static void
        1573                 :          0 : _Unpickler_MemoCleanup(UnpicklerObject *self)
        1574                 :            : {
        1575                 :            :     Py_ssize_t i;
        1576                 :          0 :     PyObject **memo = self->memo;
        1577                 :            :
        1578         [ #  # ]:          0 :     if (self->memo == NULL)
        1579                 :          0 :         return;
        1580                 :          0 :     self->memo = NULL;
        1581                 :          0 :     i = self->memo_size;
        1582         [ #  # ]:          0 :     while (--i >= 0) {
        1583                 :          0 :         Py_XDECREF(memo[i]);
        1584                 :            :     }
        1585                 :          0 :     PyMem_Free(memo);
        1586                 :            : }
        1587                 :            :
        1588                 :            : static UnpicklerObject *
        1589                 :          0 : _Unpickler_New(void)
        1590                 :            : {
        1591                 :            :     UnpicklerObject *self;
        1592                 :            :
        1593                 :          0 :     self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type);
        1594         [ #  # ]:          0 :     if (self == NULL)
        1595                 :          0 :         return NULL;
        1596                 :            :
        1597                 :          0 :     self->pers_func = NULL;
        1598                 :          0 :     self->input_buffer = NULL;
        1599                 :          0 :     self->input_line = NULL;
        1600                 :          0 :     self->input_len = 0;
        1601                 :          0 :     self->next_read_idx = 0;
        1602                 :          0 :     self->prefetched_idx = 0;
        1603                 :          0 :     self->read = NULL;
        1604                 :          0 :     self->readinto = NULL;
        1605                 :          0 :     self->readline = NULL;
        1606                 :          0 :     self->peek = NULL;
        1607                 :          0 :     self->buffers = NULL;
        1608                 :          0 :     self->encoding = NULL;
        1609                 :          0 :     self->errors = NULL;
        1610                 :          0 :     self->marks = NULL;
        1611                 :          0 :     self->num_marks = 0;
        1612                 :          0 :     self->marks_size = 0;
        1613                 :          0 :     self->proto = 0;
        1614                 :          0 :     self->fix_imports = 0;
        1615                 :          0 :     memset(&self->buffer, 0, sizeof(Py_buffer));
        1616                 :          0 :     self->memo_size = 32;
        1617                 :          0 :     self->memo_len = 0;
        1618                 :          0 :     self->memo = _Unpickler_NewMemo(self->memo_size);
        1619                 :          0 :     self->stack = (Pdata *)Pdata_New();
        1620                 :            :
        1621   [ #  #  #  # ]:          0 :     if (self->memo == NULL || self->stack == NULL) {
        1622                 :          0 :         Py_DECREF(self);
        1623                 :          0 :         return NULL;
        1624                 :            :     }
        1625                 :            :
        1626                 :          0 :     PyObject_GC_Track(self);
        1627                 :          0 :     return self;
        1628                 :            : }
        1629                 :            :
        1630                 :            : /* Returns -1 (with an exception set) on failure, 0 on success. This may
        1631                 :            :    be called once on a freshly created Unpickler. */
        1632                 :            : static int
        1633                 :          0 : _Unpickler_SetInputStream(UnpicklerObject *self, PyObject *file)
        1634                 :            : {
        1635                 :            :     /* Optional file methods */
        1636         [ #  # ]:          0 :     if (_PyObject_LookupAttr(file, &_Py_ID(peek), &self->peek) < 0) {
        1637                 :          0 :         return -1;
        1638                 :            :     }
        1639         [ #  # ]:          0 :     if (_PyObject_LookupAttr(file, &_Py_ID(readinto), &self->readinto) < 0) {
        1640                 :          0 :         return -1;
        1641                 :            :     }
        1642                 :          0 :     (void)_PyObject_LookupAttr(file, &_Py_ID(read), &self->read);
        1643                 :          0 :     (void)_PyObject_LookupAttr(file, &_Py_ID(readline), &self->readline);
        1644   [ #  #  #  # ]:          0 :     if (!self->readline || !self->read) {
        1645         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        1646                 :          0 :             PyErr_SetString(PyExc_TypeError,
        1647                 :            :                             "file must have 'read' and 'readline' attributes");
        1648                 :            :         }
        1649         [ #  # ]:          0 :         Py_CLEAR(self->read);
        1650         [ #  # ]:          0 :         Py_CLEAR(self->readinto);
        1651         [ #  # ]:          0 :         Py_CLEAR(self->readline);
        1652         [ #  # ]:          0 :         Py_CLEAR(self->peek);
        1653                 :          0 :         return -1;
        1654                 :            :     }
        1655                 :          0 :     return 0;
        1656                 :            : }
        1657                 :            :
        1658                 :            : /* Returns -1 (with an exception set) on failure, 0 on success. This may
        1659                 :            :    be called once on a freshly created Unpickler. */
        1660                 :            : static int
        1661                 :          0 : _Unpickler_SetInputEncoding(UnpicklerObject *self,
        1662                 :            :                             const char *encoding,
        1663                 :            :                             const char *errors)
        1664                 :            : {
        1665         [ #  # ]:          0 :     if (encoding == NULL)
        1666                 :          0 :         encoding = "ASCII";
        1667         [ #  # ]:          0 :     if (errors == NULL)
        1668                 :          0 :         errors = "strict";
        1669                 :            :
        1670                 :          0 :     self->encoding = _PyMem_Strdup(encoding);
        1671                 :          0 :     self->errors = _PyMem_Strdup(errors);
        1672   [ #  #  #  # ]:          0 :     if (self->encoding == NULL || self->errors == NULL) {
        1673                 :          0 :         PyErr_NoMemory();
        1674                 :          0 :         return -1;
        1675                 :            :     }
        1676                 :          0 :     return 0;
        1677                 :            : }
        1678                 :            :
        1679                 :            : /* Returns -1 (with an exception set) on failure, 0 on success. This may
        1680                 :            :    be called once on a freshly created Unpickler. */
        1681                 :            : static int
        1682                 :          0 : _Unpickler_SetBuffers(UnpicklerObject *self, PyObject *buffers)
        1683                 :            : {
        1684   [ #  #  #  # ]:          0 :     if (buffers == NULL || buffers == Py_None) {
        1685                 :          0 :         self->buffers = NULL;
        1686                 :            :     }
        1687                 :            :     else {
        1688                 :          0 :         self->buffers = PyObject_GetIter(buffers);
        1689         [ #  # ]:          0 :         if (self->buffers == NULL) {
        1690                 :          0 :             return -1;
        1691                 :            :         }
        1692                 :            :     }
        1693                 :          0 :     return 0;
        1694                 :            : }
        1695                 :            :
        1696                 :            : /* Generate a GET opcode for an object stored in the memo. */
        1697                 :            : static int
        1698                 :          0 : memo_get(PicklerObject *self, PyObject *key)
        1699                 :            : {
        1700                 :            :     Py_ssize_t *value;
        1701                 :            :     char pdata[30];
        1702                 :            :     Py_ssize_t len;
        1703                 :            :
        1704                 :          0 :     value = PyMemoTable_Get(self->memo, key);
        1705         [ #  # ]:          0 :     if (value == NULL)  {
        1706                 :          0 :         PyErr_SetObject(PyExc_KeyError, key);
        1707                 :          0 :         return -1;
        1708                 :            :     }
        1709                 :            :
        1710         [ #  # ]:          0 :     if (!self->bin) {
        1711                 :          0 :         pdata[0] = GET;
        1712                 :          0 :         PyOS_snprintf(pdata + 1, sizeof(pdata) - 1,
        1713                 :            :                       "%zd\n", *value);
        1714                 :          0 :         len = strlen(pdata);
        1715                 :            :     }
        1716                 :            :     else {
        1717         [ #  # ]:          0 :         if (*value < 256) {
        1718                 :          0 :             pdata[0] = BINGET;
        1719                 :          0 :             pdata[1] = (unsigned char)(*value & 0xff);
        1720                 :          0 :             len = 2;
        1721                 :            :         }
        1722         [ #  # ]:          0 :         else if ((size_t)*value <= 0xffffffffUL) {
        1723                 :          0 :             pdata[0] = LONG_BINGET;
        1724                 :          0 :             pdata[1] = (unsigned char)(*value & 0xff);
        1725                 :          0 :             pdata[2] = (unsigned char)((*value >> 8) & 0xff);
        1726                 :          0 :             pdata[3] = (unsigned char)((*value >> 16) & 0xff);
        1727                 :          0 :             pdata[4] = (unsigned char)((*value >> 24) & 0xff);
        1728                 :          0 :             len = 5;
        1729                 :            :         }
        1730                 :            :         else { /* unlikely */
        1731                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        1732                 :          0 :             PyErr_SetString(st->PicklingError,
        1733                 :            :                             "memo id too large for LONG_BINGET");
        1734                 :          0 :             return -1;
        1735                 :            :         }
        1736                 :            :     }
        1737                 :            :
        1738         [ #  # ]:          0 :     if (_Pickler_Write(self, pdata, len) < 0)
        1739                 :          0 :         return -1;
        1740                 :            :
        1741                 :          0 :     return 0;
        1742                 :            : }
        1743                 :            :
        1744                 :            : /* Store an object in the memo, assign it a new unique ID based on the number
        1745                 :            :    of objects currently stored in the memo and generate a PUT opcode. */
        1746                 :            : static int
        1747                 :          0 : memo_put(PicklerObject *self, PyObject *obj)
        1748                 :            : {
        1749                 :            :     char pdata[30];
        1750                 :            :     Py_ssize_t len;
        1751                 :            :     Py_ssize_t idx;
        1752                 :            :
        1753                 :          0 :     const char memoize_op = MEMOIZE;
        1754                 :            :
        1755         [ #  # ]:          0 :     if (self->fast)
        1756                 :          0 :         return 0;
        1757                 :            :
        1758                 :          0 :     idx = PyMemoTable_Size(self->memo);
        1759         [ #  # ]:          0 :     if (PyMemoTable_Set(self->memo, obj, idx) < 0)
        1760                 :          0 :         return -1;
        1761                 :            :
        1762         [ #  # ]:          0 :     if (self->proto >= 4) {
        1763         [ #  # ]:          0 :         if (_Pickler_Write(self, &memoize_op, 1) < 0)
        1764                 :          0 :             return -1;
        1765                 :          0 :         return 0;
        1766                 :            :     }
        1767         [ #  # ]:          0 :     else if (!self->bin) {
        1768                 :          0 :         pdata[0] = PUT;
        1769                 :          0 :         PyOS_snprintf(pdata + 1, sizeof(pdata) - 1,
        1770                 :            :                       "%zd\n", idx);
        1771                 :          0 :         len = strlen(pdata);
        1772                 :            :     }
        1773                 :            :     else {
        1774         [ #  # ]:          0 :         if (idx < 256) {
        1775                 :          0 :             pdata[0] = BINPUT;
        1776                 :          0 :             pdata[1] = (unsigned char)idx;
        1777                 :          0 :             len = 2;
        1778                 :            :         }
        1779         [ #  # ]:          0 :         else if ((size_t)idx <= 0xffffffffUL) {
        1780                 :          0 :             pdata[0] = LONG_BINPUT;
        1781                 :          0 :             pdata[1] = (unsigned char)(idx & 0xff);
        1782                 :          0 :             pdata[2] = (unsigned char)((idx >> 8) & 0xff);
        1783                 :          0 :             pdata[3] = (unsigned char)((idx >> 16) & 0xff);
        1784                 :          0 :             pdata[4] = (unsigned char)((idx >> 24) & 0xff);
        1785                 :          0 :             len = 5;
        1786                 :            :         }
        1787                 :            :         else { /* unlikely */
        1788                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        1789                 :          0 :             PyErr_SetString(st->PicklingError,
        1790                 :            :                             "memo id too large for LONG_BINPUT");
        1791                 :          0 :             return -1;
        1792                 :            :         }
        1793                 :            :     }
        1794         [ #  # ]:          0 :     if (_Pickler_Write(self, pdata, len) < 0)
        1795                 :          0 :         return -1;
        1796                 :            :
        1797                 :          0 :     return 0;
        1798                 :            : }
        1799                 :            :
        1800                 :            : static PyObject *
        1801                 :          0 : get_dotted_path(PyObject *obj, PyObject *name)
        1802                 :            : {
        1803                 :            :     PyObject *dotted_path;
        1804                 :            :     Py_ssize_t i, n;
        1805                 :            :     _Py_DECLARE_STR(dot, ".");
        1806                 :          0 :     dotted_path = PyUnicode_Split(name, &_Py_STR(dot), -1);
        1807         [ #  # ]:          0 :     if (dotted_path == NULL)
        1808                 :          0 :         return NULL;
        1809                 :          0 :     n = PyList_GET_SIZE(dotted_path);
        1810                 :            :     assert(n >= 1);
        1811         [ #  # ]:          0 :     for (i = 0; i < n; i++) {
        1812                 :          0 :         PyObject *subpath = PyList_GET_ITEM(dotted_path, i);
        1813         [ #  # ]:          0 :         if (_PyUnicode_EqualToASCIIString(subpath, "<locals>")) {
        1814         [ #  # ]:          0 :             if (obj == NULL)
        1815                 :          0 :                 PyErr_Format(PyExc_AttributeError,
        1816                 :            :                              "Can't pickle local object %R", name);
        1817                 :            :             else
        1818                 :          0 :                 PyErr_Format(PyExc_AttributeError,
        1819                 :            :                              "Can't pickle local attribute %R on %R", name, obj);
        1820                 :          0 :             Py_DECREF(dotted_path);
        1821                 :          0 :             return NULL;
        1822                 :            :         }
        1823                 :            :     }
        1824                 :          0 :     return dotted_path;
        1825                 :            : }
        1826                 :            :
        1827                 :            : static PyObject *
        1828                 :          0 : get_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
        1829                 :            : {
        1830                 :            :     Py_ssize_t i, n;
        1831                 :          0 :     PyObject *parent = NULL;
        1832                 :            :
        1833                 :            :     assert(PyList_CheckExact(names));
        1834                 :          0 :     Py_INCREF(obj);
        1835                 :          0 :     n = PyList_GET_SIZE(names);
        1836         [ #  # ]:          0 :     for (i = 0; i < n; i++) {
        1837                 :          0 :         PyObject *name = PyList_GET_ITEM(names, i);
        1838                 :          0 :         Py_XSETREF(parent, obj);
        1839                 :          0 :         (void)_PyObject_LookupAttr(parent, name, &obj);
        1840         [ #  # ]:          0 :         if (obj == NULL) {
        1841                 :          0 :             Py_DECREF(parent);
        1842                 :          0 :             return NULL;
        1843                 :            :         }
        1844                 :            :     }
        1845         [ #  # ]:          0 :     if (pparent != NULL)
        1846                 :          0 :         *pparent = parent;
        1847                 :            :     else
        1848                 :          0 :         Py_XDECREF(parent);
        1849                 :          0 :     return obj;
        1850                 :            : }
        1851                 :            :
        1852                 :            :
        1853                 :            : static PyObject *
        1854                 :          0 : getattribute(PyObject *obj, PyObject *name, int allow_qualname)
        1855                 :            : {
        1856                 :            :     PyObject *dotted_path, *attr;
        1857                 :            :
        1858         [ #  # ]:          0 :     if (allow_qualname) {
        1859                 :          0 :         dotted_path = get_dotted_path(obj, name);
        1860         [ #  # ]:          0 :         if (dotted_path == NULL)
        1861                 :          0 :             return NULL;
        1862                 :          0 :         attr = get_deep_attribute(obj, dotted_path, NULL);
        1863                 :          0 :         Py_DECREF(dotted_path);
        1864                 :            :     }
        1865                 :            :     else {
        1866                 :          0 :         (void)_PyObject_LookupAttr(obj, name, &attr);
        1867                 :            :     }
        1868   [ #  #  #  # ]:          0 :     if (attr == NULL && !PyErr_Occurred()) {
        1869                 :          0 :         PyErr_Format(PyExc_AttributeError,
        1870                 :            :                      "Can't get attribute %R on %R", name, obj);
        1871                 :            :     }
        1872                 :          0 :     return attr;
        1873                 :            : }
        1874                 :            :
        1875                 :            : static int
        1876                 :          0 : _checkmodule(PyObject *module_name, PyObject *module,
        1877                 :            :              PyObject *global, PyObject *dotted_path)
        1878                 :            : {
        1879         [ #  # ]:          0 :     if (module == Py_None) {
        1880                 :          0 :         return -1;
        1881                 :            :     }
        1882   [ #  #  #  # ]:          0 :     if (PyUnicode_Check(module_name) &&
        1883                 :          0 :             _PyUnicode_EqualToASCIIString(module_name, "__main__")) {
        1884                 :          0 :         return -1;
        1885                 :            :     }
        1886                 :            :
        1887                 :          0 :     PyObject *candidate = get_deep_attribute(module, dotted_path, NULL);
        1888         [ #  # ]:          0 :     if (candidate == NULL) {
        1889                 :          0 :         return -1;
        1890                 :            :     }
        1891         [ #  # ]:          0 :     if (candidate != global) {
        1892                 :          0 :         Py_DECREF(candidate);
        1893                 :          0 :         return -1;
        1894                 :            :     }
        1895                 :          0 :     Py_DECREF(candidate);
        1896                 :          0 :     return 0;
        1897                 :            : }
        1898                 :            :
        1899                 :            : static PyObject *
        1900                 :          0 : whichmodule(PyObject *global, PyObject *dotted_path)
        1901                 :            : {
        1902                 :            :     PyObject *module_name;
        1903                 :          0 :     PyObject *module = NULL;
        1904                 :            :     Py_ssize_t i;
        1905                 :            :     PyObject *modules;
        1906                 :            :
        1907         [ #  # ]:          0 :     if (_PyObject_LookupAttr(global, &_Py_ID(__module__), &module_name) < 0) {
        1908                 :          0 :         return NULL;
        1909                 :            :     }
        1910         [ #  # ]:          0 :     if (module_name) {
        1911                 :            :         /* In some rare cases (e.g., bound methods of extension types),
        1912                 :            :            __module__ can be None. If it is so, then search sys.modules for
        1913                 :            :            the module of global. */
        1914         [ #  # ]:          0 :         if (module_name != Py_None)
        1915                 :          0 :             return module_name;
        1916         [ #  # ]:          0 :         Py_CLEAR(module_name);
        1917                 :            :     }
        1918                 :            :     assert(module_name == NULL);
        1919                 :            :
        1920                 :            :     /* Fallback on walking sys.modules */
        1921                 :          0 :     PyThreadState *tstate = _PyThreadState_GET();
        1922                 :          0 :     modules = _PySys_GetAttr(tstate, &_Py_ID(modules));
        1923         [ #  # ]:          0 :     if (modules == NULL) {
        1924                 :          0 :         PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
        1925                 :          0 :         return NULL;
        1926                 :            :     }
        1927         [ #  # ]:          0 :     if (PyDict_CheckExact(modules)) {
        1928                 :          0 :         i = 0;
        1929         [ #  # ]:          0 :         while (PyDict_Next(modules, &i, &module_name, &module)) {
        1930         [ #  # ]:          0 :             if (_checkmodule(module_name, module, global, dotted_path) == 0) {
        1931                 :          0 :                 return Py_NewRef(module_name);
        1932                 :            :             }
        1933         [ #  # ]:          0 :             if (PyErr_Occurred()) {
        1934                 :          0 :                 return NULL;
        1935                 :            :             }
        1936                 :            :         }
        1937                 :            :     }
        1938                 :            :     else {
        1939                 :          0 :         PyObject *iterator = PyObject_GetIter(modules);
        1940         [ #  # ]:          0 :         if (iterator == NULL) {
        1941                 :          0 :             return NULL;
        1942                 :            :         }
        1943         [ #  # ]:          0 :         while ((module_name = PyIter_Next(iterator))) {
        1944                 :          0 :             module = PyObject_GetItem(modules, module_name);
        1945         [ #  # ]:          0 :             if (module == NULL) {
        1946                 :          0 :                 Py_DECREF(module_name);
        1947                 :          0 :                 Py_DECREF(iterator);
        1948                 :          0 :                 return NULL;
        1949                 :            :             }
        1950         [ #  # ]:          0 :             if (_checkmodule(module_name, module, global, dotted_path) == 0) {
        1951                 :          0 :                 Py_DECREF(module);
        1952                 :          0 :                 Py_DECREF(iterator);
        1953                 :          0 :                 return module_name;
        1954                 :            :             }
        1955                 :          0 :             Py_DECREF(module);
        1956                 :          0 :             Py_DECREF(module_name);
        1957         [ #  # ]:          0 :             if (PyErr_Occurred()) {
        1958                 :          0 :                 Py_DECREF(iterator);
        1959                 :          0 :                 return NULL;
        1960                 :            :             }
        1961                 :            :         }
        1962                 :          0 :         Py_DECREF(iterator);
        1963                 :            :     }
        1964                 :            :
        1965                 :            :     /* If no module is found, use __main__. */
        1966                 :          0 :     module_name = &_Py_ID(__main__);
        1967                 :          0 :     return Py_NewRef(module_name);
        1968                 :            : }
        1969                 :            :
        1970                 :            : /* fast_save_enter() and fast_save_leave() are guards against recursive
        1971                 :            :    objects when Pickler is used with the "fast mode" (i.e., with object
        1972                 :            :    memoization disabled). If the nesting of a list or dict object exceed
        1973                 :            :    FAST_NESTING_LIMIT, these guards will start keeping an internal
        1974                 :            :    reference to the seen list or dict objects and check whether these objects
        1975                 :            :    are recursive. These are not strictly necessary, since save() has a
        1976                 :            :    hard-coded recursion limit, but they give a nicer error message than the
        1977                 :            :    typical RuntimeError. */
        1978                 :            : static int
        1979                 :          0 : fast_save_enter(PicklerObject *self, PyObject *obj)
        1980                 :            : {
        1981                 :            :     /* if fast_nesting < 0, we're doing an error exit. */
        1982         [ #  # ]:          0 :     if (++self->fast_nesting >= FAST_NESTING_LIMIT) {
        1983                 :          0 :         PyObject *key = NULL;
        1984         [ #  # ]:          0 :         if (self->fast_memo == NULL) {
        1985                 :          0 :             self->fast_memo = PyDict_New();
        1986         [ #  # ]:          0 :             if (self->fast_memo == NULL) {
        1987                 :          0 :                 self->fast_nesting = -1;
        1988                 :          0 :                 return 0;
        1989                 :            :             }
        1990                 :            :         }
        1991                 :          0 :         key = PyLong_FromVoidPtr(obj);
        1992         [ #  # ]:          0 :         if (key == NULL) {
        1993                 :          0 :             self->fast_nesting = -1;
        1994                 :          0 :             return 0;
        1995                 :            :         }
        1996                 :          0 :         int r = PyDict_Contains(self->fast_memo, key);
        1997         [ #  # ]:          0 :         if (r > 0) {
        1998                 :          0 :             PyErr_Format(PyExc_ValueError,
        1999                 :            :                          "fast mode: can't pickle cyclic objects "
        2000                 :            :                          "including object type %.200s at %p",
        2001                 :          0 :                          Py_TYPE(obj)->tp_name, obj);
        2002                 :            :         }
        2003         [ #  # ]:          0 :         else if (r == 0) {
        2004                 :          0 :             r = PyDict_SetItem(self->fast_memo, key, Py_None);
        2005                 :            :         }
        2006                 :          0 :         Py_DECREF(key);
        2007         [ #  # ]:          0 :         if (r != 0) {
        2008                 :          0 :             self->fast_nesting = -1;
        2009                 :          0 :             return 0;
        2010                 :            :         }
        2011                 :            :     }
        2012                 :          0 :     return 1;
        2013                 :            : }
        2014                 :            :
        2015                 :            : static int
        2016                 :          0 : fast_save_leave(PicklerObject *self, PyObject *obj)
        2017                 :            : {
        2018         [ #  # ]:          0 :     if (self->fast_nesting-- >= FAST_NESTING_LIMIT) {
        2019                 :          0 :         PyObject *key = PyLong_FromVoidPtr(obj);
        2020         [ #  # ]:          0 :         if (key == NULL)
        2021                 :          0 :             return 0;
        2022         [ #  # ]:          0 :         if (PyDict_DelItem(self->fast_memo, key) < 0) {
        2023                 :          0 :             Py_DECREF(key);
        2024                 :          0 :             return 0;
        2025                 :            :         }
        2026                 :          0 :         Py_DECREF(key);
        2027                 :            :     }
        2028                 :          0 :     return 1;
        2029                 :            : }
        2030                 :            :
        2031                 :            : static int
        2032                 :          0 : save_none(PicklerObject *self, PyObject *obj)
        2033                 :            : {
        2034                 :          0 :     const char none_op = NONE;
        2035         [ #  # ]:          0 :     if (_Pickler_Write(self, &none_op, 1) < 0)
        2036                 :          0 :         return -1;
        2037                 :            :
        2038                 :          0 :     return 0;
        2039                 :            : }
        2040                 :            :
        2041                 :            : static int
        2042                 :          0 : save_bool(PicklerObject *self, PyObject *obj)
        2043                 :            : {
        2044         [ #  # ]:          0 :     if (self->proto >= 2) {
        2045         [ #  # ]:          0 :         const char bool_op = (obj == Py_True) ? NEWTRUE : NEWFALSE;
        2046         [ #  # ]:          0 :         if (_Pickler_Write(self, &bool_op, 1) < 0)
        2047                 :          0 :             return -1;
        2048                 :            :     }
        2049                 :            :     else {
        2050                 :            :         /* These aren't opcodes -- they're ways to pickle bools before protocol 2
        2051                 :            :          * so that unpicklers written before bools were introduced unpickle them
        2052                 :            :          * as ints, but unpicklers after can recognize that bools were intended.
        2053                 :            :          * Note that protocol 2 added direct ways to pickle bools.
        2054                 :            :          */
        2055         [ #  # ]:          0 :         const char *bool_str = (obj == Py_True) ? "I01\n" : "I00\n";
        2056         [ #  # ]:          0 :         if (_Pickler_Write(self, bool_str, strlen(bool_str)) < 0)
        2057                 :          0 :             return -1;
        2058                 :            :     }
        2059                 :          0 :     return 0;
        2060                 :            : }
        2061                 :            :
        2062                 :            : static int
        2063                 :          0 : save_long(PicklerObject *self, PyObject *obj)
        2064                 :            : {
        2065                 :          0 :     PyObject *repr = NULL;
        2066                 :            :     Py_ssize_t size;
        2067                 :            :     long val;
        2068                 :            :     int overflow;
        2069                 :          0 :     int status = 0;
        2070                 :            :
        2071                 :          0 :     val= PyLong_AsLongAndOverflow(obj, &overflow);
        2072   [ #  #  #  #  :          0 :     if (!overflow && (sizeof(long) <= 4 ||
                       #  # ]
        2073                 :            :             (val <= 0x7fffffffL && val >= (-0x7fffffffL - 1))))
        2074                 :            :     {
        2075                 :            :         /* result fits in a signed 4-byte integer.
        2076                 :            :
        2077                 :            :            Note: we can't use -0x80000000L in the above condition because some
        2078                 :            :            compilers (e.g., MSVC) will promote 0x80000000L to an unsigned type
        2079                 :            :            before applying the unary minus when sizeof(long) <= 4. The
        2080                 :            :            resulting value stays unsigned which is commonly not what we want,
        2081                 :            :            so MSVC happily warns us about it.  However, that result would have
        2082                 :            :            been fine because we guard for sizeof(long) <= 4 which turns the
        2083                 :            :            condition true in that particular case. */
        2084                 :            :         char pdata[32];
        2085                 :          0 :         Py_ssize_t len = 0;
        2086                 :            :
        2087         [ #  # ]:          0 :         if (self->bin) {
        2088                 :          0 :             pdata[1] = (unsigned char)(val & 0xff);
        2089                 :          0 :             pdata[2] = (unsigned char)((val >> 8) & 0xff);
        2090                 :          0 :             pdata[3] = (unsigned char)((val >> 16) & 0xff);
        2091                 :          0 :             pdata[4] = (unsigned char)((val >> 24) & 0xff);
        2092                 :            :
        2093   [ #  #  #  # ]:          0 :             if ((pdata[4] != 0) || (pdata[3] != 0)) {
        2094                 :          0 :                 pdata[0] = BININT;
        2095                 :          0 :                 len = 5;
        2096                 :            :             }
        2097         [ #  # ]:          0 :             else if (pdata[2] != 0) {
        2098                 :          0 :                 pdata[0] = BININT2;
        2099                 :          0 :                 len = 3;
        2100                 :            :             }
        2101                 :            :             else {
        2102                 :          0 :                 pdata[0] = BININT1;
        2103                 :          0 :                 len = 2;
        2104                 :            :             }
        2105                 :            :         }
        2106                 :            :         else {
        2107                 :          0 :             sprintf(pdata, "%c%ld\n", INT,  val);
        2108                 :          0 :             len = strlen(pdata);
        2109                 :            :         }
        2110         [ #  # ]:          0 :         if (_Pickler_Write(self, pdata, len) < 0)
        2111                 :          0 :             return -1;
        2112                 :            :
        2113                 :          0 :         return 0;
        2114                 :            :     }
        2115                 :            :     assert(!PyErr_Occurred());
        2116                 :            :
        2117         [ #  # ]:          0 :     if (self->proto >= 2) {
        2118                 :            :         /* Linear-time pickling. */
        2119                 :            :         size_t nbits;
        2120                 :            :         size_t nbytes;
        2121                 :            :         unsigned char *pdata;
        2122                 :            :         char header[5];
        2123                 :            :         int i;
        2124                 :          0 :         int sign = _PyLong_Sign(obj);
        2125                 :            :
        2126         [ #  # ]:          0 :         if (sign == 0) {
        2127                 :          0 :             header[0] = LONG1;
        2128                 :          0 :             header[1] = 0;      /* It's 0 -- an empty bytestring. */
        2129         [ #  # ]:          0 :             if (_Pickler_Write(self, header, 2) < 0)
        2130                 :          0 :                 goto error;
        2131                 :          0 :             return 0;
        2132                 :            :         }
        2133                 :          0 :         nbits = _PyLong_NumBits(obj);
        2134   [ #  #  #  # ]:          0 :         if (nbits == (size_t)-1 && PyErr_Occurred())
        2135                 :          0 :             goto error;
        2136                 :            :         /* How many bytes do we need?  There are nbits >> 3 full
        2137                 :            :          * bytes of data, and nbits & 7 leftover bits.  If there
        2138                 :            :          * are any leftover bits, then we clearly need another
        2139                 :            :          * byte.  What's not so obvious is that we *probably*
        2140                 :            :          * need another byte even if there aren't any leftovers:
        2141                 :            :          * the most-significant bit of the most-significant byte
        2142                 :            :          * acts like a sign bit, and it's usually got a sense
        2143                 :            :          * opposite of the one we need.  The exception is ints
        2144                 :            :          * of the form -(2**(8*j-1)) for j > 0.  Such an int is
        2145                 :            :          * its own 256's-complement, so has the right sign bit
        2146                 :            :          * even without the extra byte.  That's a pain to check
        2147                 :            :          * for in advance, though, so we always grab an extra
        2148                 :            :          * byte at the start, and cut it back later if possible.
        2149                 :            :          */
        2150                 :          0 :         nbytes = (nbits >> 3) + 1;
        2151         [ #  # ]:          0 :         if (nbytes > 0x7fffffffL) {
        2152                 :          0 :             PyErr_SetString(PyExc_OverflowError,
        2153                 :            :                             "int too large to pickle");
        2154                 :          0 :             goto error;
        2155                 :            :         }
        2156                 :          0 :         repr = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)nbytes);
        2157         [ #  # ]:          0 :         if (repr == NULL)
        2158                 :          0 :             goto error;
        2159                 :          0 :         pdata = (unsigned char *)PyBytes_AS_STRING(repr);
        2160                 :          0 :         i = _PyLong_AsByteArray((PyLongObject *)obj,
        2161                 :            :                                 pdata, nbytes,
        2162                 :            :                                 1 /* little endian */ , 1 /* signed */ );
        2163         [ #  # ]:          0 :         if (i < 0)
        2164                 :          0 :             goto error;
        2165                 :            :         /* If the int is negative, this may be a byte more than
        2166                 :            :          * needed.  This is so iff the MSB is all redundant sign
        2167                 :            :          * bits.
        2168                 :            :          */
        2169   [ #  #  #  # ]:          0 :         if (sign < 0 &&
        2170                 :          0 :             nbytes > 1 &&
        2171         [ #  # ]:          0 :             pdata[nbytes - 1] == 0xff &&
        2172         [ #  # ]:          0 :             (pdata[nbytes - 2] & 0x80) != 0) {
        2173                 :          0 :             nbytes--;
        2174                 :            :         }
        2175                 :            :
        2176         [ #  # ]:          0 :         if (nbytes < 256) {
        2177                 :          0 :             header[0] = LONG1;
        2178                 :          0 :             header[1] = (unsigned char)nbytes;
        2179                 :          0 :             size = 2;
        2180                 :            :         }
        2181                 :            :         else {
        2182                 :          0 :             header[0] = LONG4;
        2183                 :          0 :             size = (Py_ssize_t) nbytes;
        2184         [ #  # ]:          0 :             for (i = 1; i < 5; i++) {
        2185                 :          0 :                 header[i] = (unsigned char)(size & 0xff);
        2186                 :          0 :                 size >>= 8;
        2187                 :            :             }
        2188                 :          0 :             size = 5;
        2189                 :            :         }
        2190   [ #  #  #  # ]:          0 :         if (_Pickler_Write(self, header, size) < 0 ||
        2191                 :          0 :             _Pickler_Write(self, (char *)pdata, (int)nbytes) < 0)
        2192                 :          0 :             goto error;
        2193                 :            :     }
        2194                 :            :     else {
        2195                 :          0 :         const char long_op = LONG;
        2196                 :            :         const char *string;
        2197                 :            :
        2198                 :            :         /* proto < 2: write the repr and newline.  This is quadratic-time (in
        2199                 :            :            the number of digits), in both directions.  We add a trailing 'L'
        2200                 :            :            to the repr, for compatibility with Python 2.x. */
        2201                 :            :
        2202                 :          0 :         repr = PyObject_Repr(obj);
        2203         [ #  # ]:          0 :         if (repr == NULL)
        2204                 :          0 :             goto error;
        2205                 :            :
        2206                 :          0 :         string = PyUnicode_AsUTF8AndSize(repr, &size);
        2207         [ #  # ]:          0 :         if (string == NULL)
        2208                 :          0 :             goto error;
        2209                 :            :
        2210   [ #  #  #  # ]:          0 :         if (_Pickler_Write(self, &long_op, 1) < 0 ||
        2211         [ #  # ]:          0 :             _Pickler_Write(self, string, size) < 0 ||
        2212                 :          0 :             _Pickler_Write(self, "L\n", 2) < 0)
        2213                 :          0 :             goto error;
        2214                 :            :     }
        2215                 :            :
        2216                 :            :     if (0) {
        2217                 :          0 :   error:
        2218                 :          0 :       status = -1;
        2219                 :            :     }
        2220                 :          0 :     Py_XDECREF(repr);
        2221                 :            :
        2222                 :          0 :     return status;
        2223                 :            : }
        2224                 :            :
        2225                 :            : static int
        2226                 :          0 : save_float(PicklerObject *self, PyObject *obj)
        2227                 :            : {
        2228                 :          0 :     double x = PyFloat_AS_DOUBLE((PyFloatObject *)obj);
        2229                 :            :
        2230         [ #  # ]:          0 :     if (self->bin) {
        2231                 :            :         char pdata[9];
        2232                 :          0 :         pdata[0] = BINFLOAT;
        2233         [ #  # ]:          0 :         if (PyFloat_Pack8(x, &pdata[1], 0) < 0)
        2234                 :          0 :             return -1;
        2235         [ #  # ]:          0 :         if (_Pickler_Write(self, pdata, 9) < 0)
        2236                 :          0 :             return -1;
        2237                 :            :    }
        2238                 :            :     else {
        2239                 :          0 :         int result = -1;
        2240                 :          0 :         char *buf = NULL;
        2241                 :          0 :         char op = FLOAT;
        2242                 :            :
        2243         [ #  # ]:          0 :         if (_Pickler_Write(self, &op, 1) < 0)
        2244                 :          0 :             goto done;
        2245                 :            :
        2246                 :          0 :         buf = PyOS_double_to_string(x, 'r', 0, Py_DTSF_ADD_DOT_0, NULL);
        2247         [ #  # ]:          0 :         if (!buf) {
        2248                 :          0 :             PyErr_NoMemory();
        2249                 :          0 :             goto done;
        2250                 :            :         }
        2251                 :            :
        2252         [ #  # ]:          0 :         if (_Pickler_Write(self, buf, strlen(buf)) < 0)
        2253                 :          0 :             goto done;
        2254                 :            :
        2255         [ #  # ]:          0 :         if (_Pickler_Write(self, "\n", 1) < 0)
        2256                 :          0 :             goto done;
        2257                 :            :
        2258                 :          0 :         result = 0;
        2259                 :          0 : done:
        2260                 :          0 :         PyMem_Free(buf);
        2261                 :          0 :         return result;
        2262                 :            :     }
        2263                 :            :
        2264                 :          0 :     return 0;
        2265                 :            : }
        2266                 :            :
        2267                 :            : /* Perform direct write of the header and payload of the binary object.
        2268                 :            :
        2269                 :            :    The large contiguous data is written directly into the underlying file
        2270                 :            :    object, bypassing the output_buffer of the Pickler.  We intentionally
        2271                 :            :    do not insert a protocol 4 frame opcode to make it possible to optimize
        2272                 :            :    file.read calls in the loader.
        2273                 :            :  */
        2274                 :            : static int
        2275                 :          0 : _Pickler_write_bytes(PicklerObject *self,
        2276                 :            :                      const char *header, Py_ssize_t header_size,
        2277                 :            :                      const char *data, Py_ssize_t data_size,
        2278                 :            :                      PyObject *payload)
        2279                 :            : {
        2280                 :          0 :     int bypass_buffer = (data_size >= FRAME_SIZE_TARGET);
        2281                 :          0 :     int framing = self->framing;
        2282                 :            :
        2283         [ #  # ]:          0 :     if (bypass_buffer) {
        2284                 :            :         assert(self->output_buffer != NULL);
        2285                 :            :         /* Commit the previous frame. */
        2286         [ #  # ]:          0 :         if (_Pickler_CommitFrame(self)) {
        2287                 :          0 :             return -1;
        2288                 :            :         }
        2289                 :            :         /* Disable framing temporarily */
        2290                 :          0 :         self->framing = 0;
        2291                 :            :     }
        2292                 :            :
        2293         [ #  # ]:          0 :     if (_Pickler_Write(self, header, header_size) < 0) {
        2294                 :          0 :         return -1;
        2295                 :            :     }
        2296                 :            :
        2297   [ #  #  #  # ]:          0 :     if (bypass_buffer && self->write != NULL) {
        2298                 :            :         /* Bypass the in-memory buffer to directly stream large data
        2299                 :            :            into the underlying file object. */
        2300                 :          0 :         PyObject *result, *mem = NULL;
        2301                 :            :         /* Dump the output buffer to the file. */
        2302         [ #  # ]:          0 :         if (_Pickler_FlushToFile(self) < 0) {
        2303                 :          0 :             return -1;
        2304                 :            :         }
        2305                 :            :
        2306                 :            :         /* Stream write the payload into the file without going through the
        2307                 :            :            output buffer. */
        2308         [ #  # ]:          0 :         if (payload == NULL) {
        2309                 :            :             /* TODO: It would be better to use a memoryview with a linked
        2310                 :            :                original string if this is possible. */
        2311                 :          0 :             payload = mem = PyBytes_FromStringAndSize(data, data_size);
        2312         [ #  # ]:          0 :             if (payload == NULL) {
        2313                 :          0 :                 return -1;
        2314                 :            :             }
        2315                 :            :         }
        2316                 :          0 :         result = PyObject_CallOneArg(self->write, payload);
        2317                 :          0 :         Py_XDECREF(mem);
        2318         [ #  # ]:          0 :         if (result == NULL) {
        2319                 :          0 :             return -1;
        2320                 :            :         }
        2321                 :          0 :         Py_DECREF(result);
        2322                 :            :
        2323                 :            :         /* Reinitialize the buffer for subsequent calls to _Pickler_Write. */
        2324         [ #  # ]:          0 :         if (_Pickler_ClearBuffer(self) < 0) {
        2325                 :          0 :             return -1;
        2326                 :            :         }
        2327                 :            :     }
        2328                 :            :     else {
        2329         [ #  # ]:          0 :         if (_Pickler_Write(self, data, data_size) < 0) {
        2330                 :          0 :             return -1;
        2331                 :            :         }
        2332                 :            :     }
        2333                 :            :
        2334                 :            :     /* Re-enable framing for subsequent calls to _Pickler_Write. */
        2335                 :          0 :     self->framing = framing;
        2336                 :            :
        2337                 :          0 :     return 0;
        2338                 :            : }
        2339                 :            :
        2340                 :            : static int
        2341                 :          0 : _save_bytes_data(PicklerObject *self, PyObject *obj, const char *data,
        2342                 :            :                  Py_ssize_t size)
        2343                 :            : {
        2344                 :            :     assert(self->proto >= 3);
        2345                 :            :
        2346                 :            :     char header[9];
        2347                 :            :     Py_ssize_t len;
        2348                 :            :
        2349         [ #  # ]:          0 :     if (size < 0)
        2350                 :          0 :         return -1;
        2351                 :            :
        2352         [ #  # ]:          0 :     if (size <= 0xff) {
        2353                 :          0 :         header[0] = SHORT_BINBYTES;
        2354                 :          0 :         header[1] = (unsigned char)size;
        2355                 :          0 :         len = 2;
        2356                 :            :     }
        2357         [ #  # ]:          0 :     else if ((size_t)size <= 0xffffffffUL) {
        2358                 :          0 :         header[0] = BINBYTES;
        2359                 :          0 :         header[1] = (unsigned char)(size & 0xff);
        2360                 :          0 :         header[2] = (unsigned char)((size >> 8) & 0xff);
        2361                 :          0 :         header[3] = (unsigned char)((size >> 16) & 0xff);
        2362                 :          0 :         header[4] = (unsigned char)((size >> 24) & 0xff);
        2363                 :          0 :         len = 5;
        2364                 :            :     }
        2365         [ #  # ]:          0 :     else if (self->proto >= 4) {
        2366                 :          0 :         header[0] = BINBYTES8;
        2367                 :          0 :         _write_size64(header + 1, size);
        2368                 :          0 :         len = 9;
        2369                 :            :     }
        2370                 :            :     else {
        2371                 :          0 :         PyErr_SetString(PyExc_OverflowError,
        2372                 :            :                         "serializing a bytes object larger than 4 GiB "
        2373                 :            :                         "requires pickle protocol 4 or higher");
        2374                 :          0 :         return -1;
        2375                 :            :     }
        2376                 :            :
        2377         [ #  # ]:          0 :     if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) {
        2378                 :          0 :         return -1;
        2379                 :            :     }
        2380                 :            :
        2381         [ #  # ]:          0 :     if (memo_put(self, obj) < 0) {
        2382                 :          0 :         return -1;
        2383                 :            :     }
        2384                 :            :
        2385                 :          0 :     return 0;
        2386                 :            : }
        2387                 :            :
        2388                 :            : static int
        2389                 :          0 : save_bytes(PicklerObject *self, PyObject *obj)
        2390                 :            : {
        2391         [ #  # ]:          0 :     if (self->proto < 3) {
        2392                 :            :         /* Older pickle protocols do not have an opcode for pickling bytes
        2393                 :            :            objects. Therefore, we need to fake the copy protocol (i.e.,
        2394                 :            :            the __reduce__ method) to permit bytes object unpickling.
        2395                 :            :
        2396                 :            :            Here we use a hack to be compatible with Python 2. Since in Python
        2397                 :            :            2 'bytes' is just an alias for 'str' (which has different
        2398                 :            :            parameters than the actual bytes object), we use codecs.encode
        2399                 :            :            to create the appropriate 'str' object when unpickled using
        2400                 :            :            Python 2 *and* the appropriate 'bytes' object when unpickled
        2401                 :            :            using Python 3. Again this is a hack and we don't need to do this
        2402                 :            :            with newer protocols. */
        2403                 :            :         PyObject *reduce_value;
        2404                 :            :         int status;
        2405                 :            :
        2406         [ #  # ]:          0 :         if (PyBytes_GET_SIZE(obj) == 0) {
        2407                 :          0 :             reduce_value = Py_BuildValue("(O())", (PyObject*)&PyBytes_Type);
        2408                 :            :         }
        2409                 :            :         else {
        2410                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        2411                 :            :             PyObject *unicode_str =
        2412                 :          0 :                 PyUnicode_DecodeLatin1(PyBytes_AS_STRING(obj),
        2413                 :            :                                        PyBytes_GET_SIZE(obj),
        2414                 :            :                                        "strict");
        2415                 :            :
        2416         [ #  # ]:          0 :             if (unicode_str == NULL)
        2417                 :          0 :                 return -1;
        2418                 :          0 :             reduce_value = Py_BuildValue("(O(OO))",
        2419                 :            :                                          st->codecs_encode, unicode_str,
        2420                 :            :                                          &_Py_ID(latin1));
        2421                 :          0 :             Py_DECREF(unicode_str);
        2422                 :            :         }
        2423                 :            :
        2424         [ #  # ]:          0 :         if (reduce_value == NULL)
        2425                 :          0 :             return -1;
        2426                 :            :
        2427                 :            :         /* save_reduce() will memoize the object automatically. */
        2428                 :          0 :         status = save_reduce(self, reduce_value, obj);
        2429                 :          0 :         Py_DECREF(reduce_value);
        2430                 :          0 :         return status;
        2431                 :            :     }
        2432                 :            :     else {
        2433                 :          0 :         return _save_bytes_data(self, obj, PyBytes_AS_STRING(obj),
        2434                 :            :                                 PyBytes_GET_SIZE(obj));
        2435                 :            :     }
        2436                 :            : }
        2437                 :            :
        2438                 :            : static int
        2439                 :          0 : _save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data,
        2440                 :            :                      Py_ssize_t size)
        2441                 :            : {
        2442                 :            :     assert(self->proto >= 5);
        2443                 :            :
        2444                 :            :     char header[9];
        2445                 :            :     Py_ssize_t len;
        2446                 :            :
        2447         [ #  # ]:          0 :     if (size < 0)
        2448                 :          0 :         return -1;
        2449                 :            :
        2450                 :          0 :     header[0] = BYTEARRAY8;
        2451                 :          0 :     _write_size64(header + 1, size);
        2452                 :          0 :     len = 9;
        2453                 :            :
        2454         [ #  # ]:          0 :     if (_Pickler_write_bytes(self, header, len, data, size, obj) < 0) {
        2455                 :          0 :         return -1;
        2456                 :            :     }
        2457                 :            :
        2458         [ #  # ]:          0 :     if (memo_put(self, obj) < 0) {
        2459                 :          0 :         return -1;
        2460                 :            :     }
        2461                 :            :
        2462                 :          0 :     return 0;
        2463                 :            : }
        2464                 :            :
        2465                 :            : static int
        2466                 :          0 : save_bytearray(PicklerObject *self, PyObject *obj)
        2467                 :            : {
        2468         [ #  # ]:          0 :     if (self->proto < 5) {
        2469                 :            :         /* Older pickle protocols do not have an opcode for pickling
        2470                 :            :          * bytearrays. */
        2471                 :          0 :         PyObject *reduce_value = NULL;
        2472                 :            :         int status;
        2473                 :            :
        2474         [ #  # ]:          0 :         if (PyByteArray_GET_SIZE(obj) == 0) {
        2475                 :          0 :             reduce_value = Py_BuildValue("(O())",
        2476                 :            :                                          (PyObject *) &PyByteArray_Type);
        2477                 :            :         }
        2478                 :            :         else {
        2479                 :          0 :             PyObject *bytes_obj = PyBytes_FromObject(obj);
        2480         [ #  # ]:          0 :             if (bytes_obj != NULL) {
        2481                 :          0 :                 reduce_value = Py_BuildValue("(O(O))",
        2482                 :            :                                              (PyObject *) &PyByteArray_Type,
        2483                 :            :                                              bytes_obj);
        2484                 :          0 :                 Py_DECREF(bytes_obj);
        2485                 :            :             }
        2486                 :            :         }
        2487         [ #  # ]:          0 :         if (reduce_value == NULL)
        2488                 :          0 :             return -1;
        2489                 :            :
        2490                 :            :         /* save_reduce() will memoize the object automatically. */
        2491                 :          0 :         status = save_reduce(self, reduce_value, obj);
        2492                 :          0 :         Py_DECREF(reduce_value);
        2493                 :          0 :         return status;
        2494                 :            :     }
        2495                 :            :     else {
        2496                 :          0 :         return _save_bytearray_data(self, obj, PyByteArray_AS_STRING(obj),
        2497                 :            :                                     PyByteArray_GET_SIZE(obj));
        2498                 :            :     }
        2499                 :            : }
        2500                 :            :
        2501                 :            : static int
        2502                 :          0 : save_picklebuffer(PicklerObject *self, PyObject *obj)
        2503                 :            : {
        2504         [ #  # ]:          0 :     if (self->proto < 5) {
        2505                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        2506                 :          0 :         PyErr_SetString(st->PicklingError,
        2507                 :            :                         "PickleBuffer can only pickled with protocol >= 5");
        2508                 :          0 :         return -1;
        2509                 :            :     }
        2510                 :          0 :     const Py_buffer* view = PyPickleBuffer_GetBuffer(obj);
        2511         [ #  # ]:          0 :     if (view == NULL) {
        2512                 :          0 :         return -1;
        2513                 :            :     }
        2514   [ #  #  #  # ]:          0 :     if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) {
        2515                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        2516                 :          0 :         PyErr_SetString(st->PicklingError,
        2517                 :            :                         "PickleBuffer can not be pickled when "
        2518                 :            :                         "pointing to a non-contiguous buffer");
        2519                 :          0 :         return -1;
        2520                 :            :     }
        2521                 :          0 :     int in_band = 1;
        2522         [ #  # ]:          0 :     if (self->buffer_callback != NULL) {
        2523                 :          0 :         PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj);
        2524         [ #  # ]:          0 :         if (ret == NULL) {
        2525                 :          0 :             return -1;
        2526                 :            :         }
        2527                 :          0 :         in_band = PyObject_IsTrue(ret);
        2528                 :          0 :         Py_DECREF(ret);
        2529         [ #  # ]:          0 :         if (in_band == -1) {
        2530                 :          0 :             return -1;
        2531                 :            :         }
        2532                 :            :     }
        2533         [ #  # ]:          0 :     if (in_band) {
        2534                 :            :         /* Write data in-band */
        2535         [ #  # ]:          0 :         if (view->readonly) {
        2536                 :          0 :             return _save_bytes_data(self, obj, (const char*) view->buf,
        2537                 :            :                                     view->len);
        2538                 :            :         }
        2539                 :            :         else {
        2540                 :          0 :             return _save_bytearray_data(self, obj, (const char*) view->buf,
        2541                 :            :                                         view->len);
        2542                 :            :         }
        2543                 :            :     }
        2544                 :            :     else {
        2545                 :            :         /* Write data out-of-band */
        2546                 :          0 :         const char next_buffer_op = NEXT_BUFFER;
        2547         [ #  # ]:          0 :         if (_Pickler_Write(self, &next_buffer_op, 1) < 0) {
        2548                 :          0 :             return -1;
        2549                 :            :         }
        2550         [ #  # ]:          0 :         if (view->readonly) {
        2551                 :          0 :             const char readonly_buffer_op = READONLY_BUFFER;
        2552         [ #  # ]:          0 :             if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) {
        2553                 :          0 :                 return -1;
        2554                 :            :             }
        2555                 :            :         }
        2556                 :            :     }
        2557                 :          0 :     return 0;
        2558                 :            : }
        2559                 :            :
        2560                 :            : /* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates
        2561                 :            :    backslash and newline characters to \uXXXX escapes. */
        2562                 :            : static PyObject *
        2563                 :          0 : raw_unicode_escape(PyObject *obj)
        2564                 :            : {
        2565                 :            :     char *p;
        2566                 :            :     Py_ssize_t i, size;
        2567                 :            :     const void *data;
        2568                 :            :     int kind;
        2569                 :            :     _PyBytesWriter writer;
        2570                 :            :
        2571         [ #  # ]:          0 :     if (PyUnicode_READY(obj))
        2572                 :          0 :         return NULL;
        2573                 :            :
        2574                 :          0 :     _PyBytesWriter_Init(&writer);
        2575                 :            :
        2576                 :          0 :     size = PyUnicode_GET_LENGTH(obj);
        2577                 :          0 :     data = PyUnicode_DATA(obj);
        2578                 :          0 :     kind = PyUnicode_KIND(obj);
        2579                 :            :
        2580                 :          0 :     p = _PyBytesWriter_Alloc(&writer, size);
        2581         [ #  # ]:          0 :     if (p == NULL)
        2582                 :          0 :         goto error;
        2583                 :          0 :     writer.overallocate = 1;
        2584                 :            :
        2585         [ #  # ]:          0 :     for (i=0; i < size; i++) {
        2586                 :          0 :         Py_UCS4 ch = PyUnicode_READ(kind, data, i);
        2587                 :            :         /* Map 32-bit characters to '\Uxxxxxxxx' */
        2588         [ #  # ]:          0 :         if (ch >= 0x10000) {
        2589                 :            :             /* -1: subtract 1 preallocated byte */
        2590                 :          0 :             p = _PyBytesWriter_Prepare(&writer, p, 10-1);
        2591         [ #  # ]:          0 :             if (p == NULL)
        2592                 :          0 :                 goto error;
        2593                 :            :
        2594                 :          0 :             *p++ = '\\';
        2595                 :          0 :             *p++ = 'U';
        2596                 :          0 :             *p++ = Py_hexdigits[(ch >> 28) & 0xf];
        2597                 :          0 :             *p++ = Py_hexdigits[(ch >> 24) & 0xf];
        2598                 :          0 :             *p++ = Py_hexdigits[(ch >> 20) & 0xf];
        2599                 :          0 :             *p++ = Py_hexdigits[(ch >> 16) & 0xf];
        2600                 :          0 :             *p++ = Py_hexdigits[(ch >> 12) & 0xf];
        2601                 :          0 :             *p++ = Py_hexdigits[(ch >> 8) & 0xf];
        2602                 :          0 :             *p++ = Py_hexdigits[(ch >> 4) & 0xf];
        2603                 :          0 :             *p++ = Py_hexdigits[ch & 15];
        2604                 :            :         }
        2605                 :            :         /* Map 16-bit characters, '\\' and '\n' to '\uxxxx' */
        2606   [ #  #  #  # ]:          0 :         else if (ch >= 256 ||
        2607   [ #  #  #  #  :          0 :                  ch == '\\' || ch == 0 || ch == '\n' || ch == '\r' ||
                 #  #  #  # ]
        2608                 :            :                  ch == 0x1a)
        2609                 :            :         {
        2610                 :            :             /* -1: subtract 1 preallocated byte */
        2611                 :          0 :             p = _PyBytesWriter_Prepare(&writer, p, 6-1);
        2612         [ #  # ]:          0 :             if (p == NULL)
        2613                 :          0 :                 goto error;
        2614                 :            :
        2615                 :          0 :             *p++ = '\\';
        2616                 :          0 :             *p++ = 'u';
        2617                 :          0 :             *p++ = Py_hexdigits[(ch >> 12) & 0xf];
        2618                 :          0 :             *p++ = Py_hexdigits[(ch >> 8) & 0xf];
        2619                 :          0 :             *p++ = Py_hexdigits[(ch >> 4) & 0xf];
        2620                 :          0 :             *p++ = Py_hexdigits[ch & 15];
        2621                 :            :         }
        2622                 :            :         /* Copy everything else as-is */
        2623                 :            :         else
        2624                 :          0 :             *p++ = (char) ch;
        2625                 :            :     }
        2626                 :            :
        2627                 :          0 :     return _PyBytesWriter_Finish(&writer, p);
        2628                 :            :
        2629                 :          0 : error:
        2630                 :          0 :     _PyBytesWriter_Dealloc(&writer);
        2631                 :          0 :     return NULL;
        2632                 :            : }
        2633                 :            :
        2634                 :            : static int
        2635                 :          0 : write_unicode_binary(PicklerObject *self, PyObject *obj)
        2636                 :            : {
        2637                 :            :     char header[9];
        2638                 :            :     Py_ssize_t len;
        2639                 :          0 :     PyObject *encoded = NULL;
        2640                 :            :     Py_ssize_t size;
        2641                 :            :     const char *data;
        2642                 :            :
        2643         [ #  # ]:          0 :     if (PyUnicode_READY(obj))
        2644                 :          0 :         return -1;
        2645                 :            :
        2646                 :          0 :     data = PyUnicode_AsUTF8AndSize(obj, &size);
        2647         [ #  # ]:          0 :     if (data == NULL) {
        2648                 :            :         /* Issue #8383: for strings with lone surrogates, fallback on the
        2649                 :            :            "surrogatepass" error handler. */
        2650                 :          0 :         PyErr_Clear();
        2651                 :          0 :         encoded = PyUnicode_AsEncodedString(obj, "utf-8", "surrogatepass");
        2652         [ #  # ]:          0 :         if (encoded == NULL)
        2653                 :          0 :             return -1;
        2654                 :            :
        2655                 :          0 :         data = PyBytes_AS_STRING(encoded);
        2656                 :          0 :         size = PyBytes_GET_SIZE(encoded);
        2657                 :            :     }
        2658                 :            :
        2659                 :            :     assert(size >= 0);
        2660   [ #  #  #  # ]:          0 :     if (size <= 0xff && self->proto >= 4) {
        2661                 :          0 :         header[0] = SHORT_BINUNICODE;
        2662                 :          0 :         header[1] = (unsigned char)(size & 0xff);
        2663                 :          0 :         len = 2;
        2664                 :            :     }
        2665         [ #  # ]:          0 :     else if ((size_t)size <= 0xffffffffUL) {
        2666                 :          0 :         header[0] = BINUNICODE;
        2667                 :          0 :         header[1] = (unsigned char)(size & 0xff);
        2668                 :          0 :         header[2] = (unsigned char)((size >> 8) & 0xff);
        2669                 :          0 :         header[3] = (unsigned char)((size >> 16) & 0xff);
        2670                 :          0 :         header[4] = (unsigned char)((size >> 24) & 0xff);
        2671                 :          0 :         len = 5;
        2672                 :            :     }
        2673         [ #  # ]:          0 :     else if (self->proto >= 4) {
        2674                 :          0 :         header[0] = BINUNICODE8;
        2675                 :          0 :         _write_size64(header + 1, size);
        2676                 :          0 :         len = 9;
        2677                 :            :     }
        2678                 :            :     else {
        2679                 :          0 :         PyErr_SetString(PyExc_OverflowError,
        2680                 :            :                         "serializing a string larger than 4 GiB "
        2681                 :            :                         "requires pickle protocol 4 or higher");
        2682                 :          0 :         Py_XDECREF(encoded);
        2683                 :          0 :         return -1;
        2684                 :            :     }
        2685                 :            :
        2686         [ #  # ]:          0 :     if (_Pickler_write_bytes(self, header, len, data, size, encoded) < 0) {
        2687                 :          0 :         Py_XDECREF(encoded);
        2688                 :          0 :         return -1;
        2689                 :            :     }
        2690                 :          0 :     Py_XDECREF(encoded);
        2691                 :          0 :     return 0;
        2692                 :            : }
        2693                 :            :
        2694                 :            : static int
        2695                 :          0 : save_unicode(PicklerObject *self, PyObject *obj)
        2696                 :            : {
        2697         [ #  # ]:          0 :     if (self->bin) {
        2698         [ #  # ]:          0 :         if (write_unicode_binary(self, obj) < 0)
        2699                 :          0 :             return -1;
        2700                 :            :     }
        2701                 :            :     else {
        2702                 :            :         PyObject *encoded;
        2703                 :            :         Py_ssize_t size;
        2704                 :          0 :         const char unicode_op = UNICODE;
        2705                 :            :
        2706                 :          0 :         encoded = raw_unicode_escape(obj);
        2707         [ #  # ]:          0 :         if (encoded == NULL)
        2708                 :          0 :             return -1;
        2709                 :            :
        2710         [ #  # ]:          0 :         if (_Pickler_Write(self, &unicode_op, 1) < 0) {
        2711                 :          0 :             Py_DECREF(encoded);
        2712                 :          0 :             return -1;
        2713                 :            :         }
        2714                 :            :
        2715                 :          0 :         size = PyBytes_GET_SIZE(encoded);
        2716         [ #  # ]:          0 :         if (_Pickler_Write(self, PyBytes_AS_STRING(encoded), size) < 0) {
        2717                 :          0 :             Py_DECREF(encoded);
        2718                 :          0 :             return -1;
        2719                 :            :         }
        2720                 :          0 :         Py_DECREF(encoded);
        2721                 :            :
        2722         [ #  # ]:          0 :         if (_Pickler_Write(self, "\n", 1) < 0)
        2723                 :          0 :             return -1;
        2724                 :            :     }
        2725         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        2726                 :          0 :         return -1;
        2727                 :            :
        2728                 :          0 :     return 0;
        2729                 :            : }
        2730                 :            :
        2731                 :            : /* A helper for save_tuple.  Push the len elements in tuple t on the stack. */
        2732                 :            : static int
        2733                 :          0 : store_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len)
        2734                 :            : {
        2735                 :            :     Py_ssize_t i;
        2736                 :            :
        2737                 :            :     assert(PyTuple_Size(t) == len);
        2738                 :            :
        2739         [ #  # ]:          0 :     for (i = 0; i < len; i++) {
        2740                 :          0 :         PyObject *element = PyTuple_GET_ITEM(t, i);
        2741                 :            :
        2742         [ #  # ]:          0 :         if (element == NULL)
        2743                 :          0 :             return -1;
        2744         [ #  # ]:          0 :         if (save(self, element, 0) < 0)
        2745                 :          0 :             return -1;
        2746                 :            :     }
        2747                 :            :
        2748                 :          0 :     return 0;
        2749                 :            : }
        2750                 :            :
        2751                 :            : /* Tuples are ubiquitous in the pickle protocols, so many techniques are
        2752                 :            :  * used across protocols to minimize the space needed to pickle them.
        2753                 :            :  * Tuples are also the only builtin immutable type that can be recursive
        2754                 :            :  * (a tuple can be reached from itself), and that requires some subtle
        2755                 :            :  * magic so that it works in all cases.  IOW, this is a long routine.
        2756                 :            :  */
        2757                 :            : static int
        2758                 :          0 : save_tuple(PicklerObject *self, PyObject *obj)
        2759                 :            : {
        2760                 :            :     Py_ssize_t len, i;
        2761                 :            :
        2762                 :          0 :     const char mark_op = MARK;
        2763                 :          0 :     const char tuple_op = TUPLE;
        2764                 :          0 :     const char pop_op = POP;
        2765                 :          0 :     const char pop_mark_op = POP_MARK;
        2766                 :          0 :     const char len2opcode[] = {EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3};
        2767                 :            :
        2768         [ #  # ]:          0 :     if ((len = PyTuple_Size(obj)) < 0)
        2769                 :          0 :         return -1;
        2770                 :            :
        2771         [ #  # ]:          0 :     if (len == 0) {
        2772                 :            :         char pdata[2];
        2773                 :            :
        2774         [ #  # ]:          0 :         if (self->proto) {
        2775                 :          0 :             pdata[0] = EMPTY_TUPLE;
        2776                 :          0 :             len = 1;
        2777                 :            :         }
        2778                 :            :         else {
        2779                 :          0 :             pdata[0] = MARK;
        2780                 :          0 :             pdata[1] = TUPLE;
        2781                 :          0 :             len = 2;
        2782                 :            :         }
        2783         [ #  # ]:          0 :         if (_Pickler_Write(self, pdata, len) < 0)
        2784                 :          0 :             return -1;
        2785                 :          0 :         return 0;
        2786                 :            :     }
        2787                 :            :
        2788                 :            :     /* The tuple isn't in the memo now.  If it shows up there after
        2789                 :            :      * saving the tuple elements, the tuple must be recursive, in
        2790                 :            :      * which case we'll pop everything we put on the stack, and fetch
        2791                 :            :      * its value from the memo.
        2792                 :            :      */
        2793   [ #  #  #  # ]:          0 :     if (len <= 3 && self->proto >= 2) {
        2794                 :            :         /* Use TUPLE{1,2,3} opcodes. */
        2795         [ #  # ]:          0 :         if (store_tuple_elements(self, obj, len) < 0)
        2796                 :          0 :             return -1;
        2797                 :            :
        2798         [ #  # ]:          0 :         if (PyMemoTable_Get(self->memo, obj)) {
        2799                 :            :             /* pop the len elements */
        2800         [ #  # ]:          0 :             for (i = 0; i < len; i++)
        2801         [ #  # ]:          0 :                 if (_Pickler_Write(self, &pop_op, 1) < 0)
        2802                 :          0 :                     return -1;
        2803                 :            :             /* fetch from memo */
        2804         [ #  # ]:          0 :             if (memo_get(self, obj) < 0)
        2805                 :          0 :                 return -1;
        2806                 :            :
        2807                 :          0 :             return 0;
        2808                 :            :         }
        2809                 :            :         else { /* Not recursive. */
        2810         [ #  # ]:          0 :             if (_Pickler_Write(self, len2opcode + len, 1) < 0)
        2811                 :          0 :                 return -1;
        2812                 :            :         }
        2813                 :          0 :         goto memoize;
        2814                 :            :     }
        2815                 :            :
        2816                 :            :     /* proto < 2 and len > 0, or proto >= 2 and len > 3.
        2817                 :            :      * Generate MARK e1 e2 ... TUPLE
        2818                 :            :      */
        2819         [ #  # ]:          0 :     if (_Pickler_Write(self, &mark_op, 1) < 0)
        2820                 :          0 :         return -1;
        2821                 :            :
        2822         [ #  # ]:          0 :     if (store_tuple_elements(self, obj, len) < 0)
        2823                 :          0 :         return -1;
        2824                 :            :
        2825         [ #  # ]:          0 :     if (PyMemoTable_Get(self->memo, obj)) {
        2826                 :            :         /* pop the stack stuff we pushed */
        2827         [ #  # ]:          0 :         if (self->bin) {
        2828         [ #  # ]:          0 :             if (_Pickler_Write(self, &pop_mark_op, 1) < 0)
        2829                 :          0 :                 return -1;
        2830                 :            :         }
        2831                 :            :         else {
        2832                 :            :             /* Note that we pop one more than len, to remove
        2833                 :            :              * the MARK too.
        2834                 :            :              */
        2835         [ #  # ]:          0 :             for (i = 0; i <= len; i++)
        2836         [ #  # ]:          0 :                 if (_Pickler_Write(self, &pop_op, 1) < 0)
        2837                 :          0 :                     return -1;
        2838                 :            :         }
        2839                 :            :         /* fetch from memo */
        2840         [ #  # ]:          0 :         if (memo_get(self, obj) < 0)
        2841                 :          0 :             return -1;
        2842                 :            :
        2843                 :          0 :         return 0;
        2844                 :            :     }
        2845                 :            :     else { /* Not recursive. */
        2846         [ #  # ]:          0 :         if (_Pickler_Write(self, &tuple_op, 1) < 0)
        2847                 :          0 :             return -1;
        2848                 :            :     }
        2849                 :            :
        2850                 :          0 :   memoize:
        2851         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        2852                 :          0 :         return -1;
        2853                 :            :
        2854                 :          0 :     return 0;
        2855                 :            : }
        2856                 :            :
        2857                 :            : /* iter is an iterator giving items, and we batch up chunks of
        2858                 :            :  *     MARK item item ... item APPENDS
        2859                 :            :  * opcode sequences.  Calling code should have arranged to first create an
        2860                 :            :  * empty list, or list-like object, for the APPENDS to operate on.
        2861                 :            :  * Returns 0 on success, <0 on error.
        2862                 :            :  */
        2863                 :            : static int
        2864                 :          0 : batch_list(PicklerObject *self, PyObject *iter)
        2865                 :            : {
        2866                 :          0 :     PyObject *obj = NULL;
        2867                 :          0 :     PyObject *firstitem = NULL;
        2868                 :            :     int i, n;
        2869                 :            :
        2870                 :          0 :     const char mark_op = MARK;
        2871                 :          0 :     const char append_op = APPEND;
        2872                 :          0 :     const char appends_op = APPENDS;
        2873                 :            :
        2874                 :            :     assert(iter != NULL);
        2875                 :            :
        2876                 :            :     /* XXX: I think this function could be made faster by avoiding the
        2877                 :            :        iterator interface and fetching objects directly from list using
        2878                 :            :        PyList_GET_ITEM.
        2879                 :            :     */
        2880                 :            :
        2881         [ #  # ]:          0 :     if (self->proto == 0) {
        2882                 :            :         /* APPENDS isn't available; do one at a time. */
        2883                 :            :         for (;;) {
        2884                 :          0 :             obj = PyIter_Next(iter);
        2885         [ #  # ]:          0 :             if (obj == NULL) {
        2886         [ #  # ]:          0 :                 if (PyErr_Occurred())
        2887                 :          0 :                     return -1;
        2888                 :          0 :                 break;
        2889                 :            :             }
        2890                 :          0 :             i = save(self, obj, 0);
        2891                 :          0 :             Py_DECREF(obj);
        2892         [ #  # ]:          0 :             if (i < 0)
        2893                 :          0 :                 return -1;
        2894         [ #  # ]:          0 :             if (_Pickler_Write(self, &append_op, 1) < 0)
        2895                 :          0 :                 return -1;
        2896                 :            :         }
        2897                 :          0 :         return 0;
        2898                 :            :     }
        2899                 :            :
        2900                 :            :     /* proto > 0:  write in batches of BATCHSIZE. */
        2901                 :            :     do {
        2902                 :            :         /* Get first item */
        2903                 :          0 :         firstitem = PyIter_Next(iter);
        2904         [ #  # ]:          0 :         if (firstitem == NULL) {
        2905         [ #  # ]:          0 :             if (PyErr_Occurred())
        2906                 :          0 :                 goto error;
        2907                 :            :
        2908                 :            :             /* nothing more to add */
        2909                 :          0 :             break;
        2910                 :            :         }
        2911                 :            :
        2912                 :            :         /* Try to get a second item */
        2913                 :          0 :         obj = PyIter_Next(iter);
        2914         [ #  # ]:          0 :         if (obj == NULL) {
        2915         [ #  # ]:          0 :             if (PyErr_Occurred())
        2916                 :          0 :                 goto error;
        2917                 :            :
        2918                 :            :             /* Only one item to write */
        2919         [ #  # ]:          0 :             if (save(self, firstitem, 0) < 0)
        2920                 :          0 :                 goto error;
        2921         [ #  # ]:          0 :             if (_Pickler_Write(self, &append_op, 1) < 0)
        2922                 :          0 :                 goto error;
        2923         [ #  # ]:          0 :             Py_CLEAR(firstitem);
        2924                 :          0 :             break;
        2925                 :            :         }
        2926                 :            :
        2927                 :            :         /* More than one item to write */
        2928                 :            :
        2929                 :            :         /* Pump out MARK, items, APPENDS. */
        2930         [ #  # ]:          0 :         if (_Pickler_Write(self, &mark_op, 1) < 0)
        2931                 :          0 :             goto error;
        2932                 :            :
        2933         [ #  # ]:          0 :         if (save(self, firstitem, 0) < 0)
        2934                 :          0 :             goto error;
        2935         [ #  # ]:          0 :         Py_CLEAR(firstitem);
        2936                 :          0 :         n = 1;
        2937                 :            :
        2938                 :            :         /* Fetch and save up to BATCHSIZE items */
        2939         [ #  # ]:          0 :         while (obj) {
        2940         [ #  # ]:          0 :             if (save(self, obj, 0) < 0)
        2941                 :          0 :                 goto error;
        2942         [ #  # ]:          0 :             Py_CLEAR(obj);
        2943                 :          0 :             n += 1;
        2944                 :            :
        2945         [ #  # ]:          0 :             if (n == BATCHSIZE)
        2946                 :          0 :                 break;
        2947                 :            :
        2948                 :          0 :             obj = PyIter_Next(iter);
        2949         [ #  # ]:          0 :             if (obj == NULL) {
        2950         [ #  # ]:          0 :                 if (PyErr_Occurred())
        2951                 :          0 :                     goto error;
        2952                 :          0 :                 break;
        2953                 :            :             }
        2954                 :            :         }
        2955                 :            :
        2956         [ #  # ]:          0 :         if (_Pickler_Write(self, &appends_op, 1) < 0)
        2957                 :          0 :             goto error;
        2958                 :            :
        2959         [ #  # ]:          0 :     } while (n == BATCHSIZE);
        2960                 :          0 :     return 0;
        2961                 :            :
        2962                 :          0 :   error:
        2963                 :          0 :     Py_XDECREF(firstitem);
        2964                 :          0 :     Py_XDECREF(obj);
        2965                 :          0 :     return -1;
        2966                 :            : }
        2967                 :            :
        2968                 :            : /* This is a variant of batch_list() above, specialized for lists (with no
        2969                 :            :  * support for list subclasses). Like batch_list(), we batch up chunks of
        2970                 :            :  *     MARK item item ... item APPENDS
        2971                 :            :  * opcode sequences.  Calling code should have arranged to first create an
        2972                 :            :  * empty list, or list-like object, for the APPENDS to operate on.
        2973                 :            :  * Returns 0 on success, -1 on error.
        2974                 :            :  *
        2975                 :            :  * This version is considerably faster than batch_list(), if less general.
        2976                 :            :  *
        2977                 :            :  * Note that this only works for protocols > 0.
        2978                 :            :  */
        2979                 :            : static int
        2980                 :          0 : batch_list_exact(PicklerObject *self, PyObject *obj)
        2981                 :            : {
        2982                 :          0 :     PyObject *item = NULL;
        2983                 :            :     Py_ssize_t this_batch, total;
        2984                 :            :
        2985                 :          0 :     const char append_op = APPEND;
        2986                 :          0 :     const char appends_op = APPENDS;
        2987                 :          0 :     const char mark_op = MARK;
        2988                 :            :
        2989                 :            :     assert(obj != NULL);
        2990                 :            :     assert(self->proto > 0);
        2991                 :            :     assert(PyList_CheckExact(obj));
        2992                 :            :
        2993         [ #  # ]:          0 :     if (PyList_GET_SIZE(obj) == 1) {
        2994                 :          0 :         item = PyList_GET_ITEM(obj, 0);
        2995                 :          0 :         Py_INCREF(item);
        2996                 :          0 :         int err = save(self, item, 0);
        2997                 :          0 :         Py_DECREF(item);
        2998         [ #  # ]:          0 :         if (err < 0)
        2999                 :          0 :             return -1;
        3000         [ #  # ]:          0 :         if (_Pickler_Write(self, &append_op, 1) < 0)
        3001                 :          0 :             return -1;
        3002                 :          0 :         return 0;
        3003                 :            :     }
        3004                 :            :
        3005                 :            :     /* Write in batches of BATCHSIZE. */
        3006                 :          0 :     total = 0;
        3007                 :            :     do {
        3008                 :          0 :         this_batch = 0;
        3009         [ #  # ]:          0 :         if (_Pickler_Write(self, &mark_op, 1) < 0)
        3010                 :          0 :             return -1;
        3011         [ #  # ]:          0 :         while (total < PyList_GET_SIZE(obj)) {
        3012                 :          0 :             item = PyList_GET_ITEM(obj, total);
        3013                 :          0 :             Py_INCREF(item);
        3014                 :          0 :             int err = save(self, item, 0);
        3015                 :          0 :             Py_DECREF(item);
        3016         [ #  # ]:          0 :             if (err < 0)
        3017                 :          0 :                 return -1;
        3018                 :          0 :             total++;
        3019         [ #  # ]:          0 :             if (++this_batch == BATCHSIZE)
        3020                 :          0 :                 break;
        3021                 :            :         }
        3022         [ #  # ]:          0 :         if (_Pickler_Write(self, &appends_op, 1) < 0)
        3023                 :          0 :             return -1;
        3024                 :            :
        3025         [ #  # ]:          0 :     } while (total < PyList_GET_SIZE(obj));
        3026                 :            :
        3027                 :          0 :     return 0;
        3028                 :            : }
        3029                 :            :
        3030                 :            : static int
        3031                 :          0 : save_list(PicklerObject *self, PyObject *obj)
        3032                 :            : {
        3033                 :            :     char header[3];
        3034                 :            :     Py_ssize_t len;
        3035                 :          0 :     int status = 0;
        3036                 :            :
        3037   [ #  #  #  # ]:          0 :     if (self->fast && !fast_save_enter(self, obj))
        3038                 :          0 :         goto error;
        3039                 :            :
        3040                 :            :     /* Create an empty list. */
        3041         [ #  # ]:          0 :     if (self->bin) {
        3042                 :          0 :         header[0] = EMPTY_LIST;
        3043                 :          0 :         len = 1;
        3044                 :            :     }
        3045                 :            :     else {
        3046                 :          0 :         header[0] = MARK;
        3047                 :          0 :         header[1] = LIST;
        3048                 :          0 :         len = 2;
        3049                 :            :     }
        3050                 :            :
        3051         [ #  # ]:          0 :     if (_Pickler_Write(self, header, len) < 0)
        3052                 :          0 :         goto error;
        3053                 :            :
        3054                 :            :     /* Get list length, and bow out early if empty. */
        3055         [ #  # ]:          0 :     if ((len = PyList_Size(obj)) < 0)
        3056                 :          0 :         goto error;
        3057                 :            :
        3058         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        3059                 :          0 :         goto error;
        3060                 :            :
        3061         [ #  # ]:          0 :     if (len != 0) {
        3062                 :            :         /* Materialize the list elements. */
        3063   [ #  #  #  # ]:          0 :         if (PyList_CheckExact(obj) && self->proto > 0) {
        3064         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while pickling an object"))
        3065                 :          0 :                 goto error;
        3066                 :          0 :             status = batch_list_exact(self, obj);
        3067                 :          0 :             _Py_LeaveRecursiveCall();
        3068                 :            :         } else {
        3069                 :          0 :             PyObject *iter = PyObject_GetIter(obj);
        3070         [ #  # ]:          0 :             if (iter == NULL)
        3071                 :          0 :                 goto error;
        3072                 :            :
        3073         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while pickling an object")) {
        3074                 :          0 :                 Py_DECREF(iter);
        3075                 :          0 :                 goto error;
        3076                 :            :             }
        3077                 :          0 :             status = batch_list(self, iter);
        3078                 :          0 :             _Py_LeaveRecursiveCall();
        3079                 :          0 :             Py_DECREF(iter);
        3080                 :            :         }
        3081                 :            :     }
        3082                 :            :     if (0) {
        3083                 :          0 :   error:
        3084                 :          0 :         status = -1;
        3085                 :            :     }
        3086                 :            :
        3087   [ #  #  #  # ]:          0 :     if (self->fast && !fast_save_leave(self, obj))
        3088                 :          0 :         status = -1;
        3089                 :            :
        3090                 :          0 :     return status;
        3091                 :            : }
        3092                 :            :
        3093                 :            : /* iter is an iterator giving (key, value) pairs, and we batch up chunks of
        3094                 :            :  *     MARK key value ... key value SETITEMS
        3095                 :            :  * opcode sequences.  Calling code should have arranged to first create an
        3096                 :            :  * empty dict, or dict-like object, for the SETITEMS to operate on.
        3097                 :            :  * Returns 0 on success, <0 on error.
        3098                 :            :  *
        3099                 :            :  * This is very much like batch_list().  The difference between saving
        3100                 :            :  * elements directly, and picking apart two-tuples, is so long-winded at
        3101                 :            :  * the C level, though, that attempts to combine these routines were too
        3102                 :            :  * ugly to bear.
        3103                 :            :  */
        3104                 :            : static int
        3105                 :          0 : batch_dict(PicklerObject *self, PyObject *iter)
        3106                 :            : {
        3107                 :          0 :     PyObject *obj = NULL;
        3108                 :          0 :     PyObject *firstitem = NULL;
        3109                 :            :     int i, n;
        3110                 :            :
        3111                 :          0 :     const char mark_op = MARK;
        3112                 :          0 :     const char setitem_op = SETITEM;
        3113                 :          0 :     const char setitems_op = SETITEMS;
        3114                 :            :
        3115                 :            :     assert(iter != NULL);
        3116                 :            :
        3117         [ #  # ]:          0 :     if (self->proto == 0) {
        3118                 :            :         /* SETITEMS isn't available; do one at a time. */
        3119                 :            :         for (;;) {
        3120                 :          0 :             obj = PyIter_Next(iter);
        3121         [ #  # ]:          0 :             if (obj == NULL) {
        3122         [ #  # ]:          0 :                 if (PyErr_Occurred())
        3123                 :          0 :                     return -1;
        3124                 :          0 :                 break;
        3125                 :            :             }
        3126   [ #  #  #  # ]:          0 :             if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) {
        3127                 :          0 :                 PyErr_SetString(PyExc_TypeError, "dict items "
        3128                 :            :                                 "iterator must return 2-tuples");
        3129                 :          0 :                 return -1;
        3130                 :            :             }
        3131                 :          0 :             i = save(self, PyTuple_GET_ITEM(obj, 0), 0);
        3132         [ #  # ]:          0 :             if (i >= 0)
        3133                 :          0 :                 i = save(self, PyTuple_GET_ITEM(obj, 1), 0);
        3134                 :          0 :             Py_DECREF(obj);
        3135         [ #  # ]:          0 :             if (i < 0)
        3136                 :          0 :                 return -1;
        3137         [ #  # ]:          0 :             if (_Pickler_Write(self, &setitem_op, 1) < 0)
        3138                 :          0 :                 return -1;
        3139                 :            :         }
        3140                 :          0 :         return 0;
        3141                 :            :     }
        3142                 :            :
        3143                 :            :     /* proto > 0:  write in batches of BATCHSIZE. */
        3144                 :            :     do {
        3145                 :            :         /* Get first item */
        3146                 :          0 :         firstitem = PyIter_Next(iter);
        3147         [ #  # ]:          0 :         if (firstitem == NULL) {
        3148         [ #  # ]:          0 :             if (PyErr_Occurred())
        3149                 :          0 :                 goto error;
        3150                 :            :
        3151                 :            :             /* nothing more to add */
        3152                 :          0 :             break;
        3153                 :            :         }
        3154   [ #  #  #  # ]:          0 :         if (!PyTuple_Check(firstitem) || PyTuple_Size(firstitem) != 2) {
        3155                 :          0 :             PyErr_SetString(PyExc_TypeError, "dict items "
        3156                 :            :                                 "iterator must return 2-tuples");
        3157                 :          0 :             goto error;
        3158                 :            :         }
        3159                 :            :
        3160                 :            :         /* Try to get a second item */
        3161                 :          0 :         obj = PyIter_Next(iter);
        3162         [ #  # ]:          0 :         if (obj == NULL) {
        3163         [ #  # ]:          0 :             if (PyErr_Occurred())
        3164                 :          0 :                 goto error;
        3165                 :            :
        3166                 :            :             /* Only one item to write */
        3167         [ #  # ]:          0 :             if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
        3168                 :          0 :                 goto error;
        3169         [ #  # ]:          0 :             if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
        3170                 :          0 :                 goto error;
        3171         [ #  # ]:          0 :             if (_Pickler_Write(self, &setitem_op, 1) < 0)
        3172                 :          0 :                 goto error;
        3173         [ #  # ]:          0 :             Py_CLEAR(firstitem);
        3174                 :          0 :             break;
        3175                 :            :         }
        3176                 :            :
        3177                 :            :         /* More than one item to write */
        3178                 :            :
        3179                 :            :         /* Pump out MARK, items, SETITEMS. */
        3180         [ #  # ]:          0 :         if (_Pickler_Write(self, &mark_op, 1) < 0)
        3181                 :          0 :             goto error;
        3182                 :            :
        3183         [ #  # ]:          0 :         if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
        3184                 :          0 :             goto error;
        3185         [ #  # ]:          0 :         if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
        3186                 :          0 :             goto error;
        3187         [ #  # ]:          0 :         Py_CLEAR(firstitem);
        3188                 :          0 :         n = 1;
        3189                 :            :
        3190                 :            :         /* Fetch and save up to BATCHSIZE items */
        3191         [ #  # ]:          0 :         while (obj) {
        3192   [ #  #  #  # ]:          0 :             if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2) {
        3193                 :          0 :                 PyErr_SetString(PyExc_TypeError, "dict items "
        3194                 :            :                     "iterator must return 2-tuples");
        3195                 :          0 :                 goto error;
        3196                 :            :             }
        3197   [ #  #  #  # ]:          0 :             if (save(self, PyTuple_GET_ITEM(obj, 0), 0) < 0 ||
        3198                 :          0 :                 save(self, PyTuple_GET_ITEM(obj, 1), 0) < 0)
        3199                 :          0 :                 goto error;
        3200         [ #  # ]:          0 :             Py_CLEAR(obj);
        3201                 :          0 :             n += 1;
        3202                 :            :
        3203         [ #  # ]:          0 :             if (n == BATCHSIZE)
        3204                 :          0 :                 break;
        3205                 :            :
        3206                 :          0 :             obj = PyIter_Next(iter);
        3207         [ #  # ]:          0 :             if (obj == NULL) {
        3208         [ #  # ]:          0 :                 if (PyErr_Occurred())
        3209                 :          0 :                     goto error;
        3210                 :          0 :                 break;
        3211                 :            :             }
        3212                 :            :         }
        3213                 :            :
        3214         [ #  # ]:          0 :         if (_Pickler_Write(self, &setitems_op, 1) < 0)
        3215                 :          0 :             goto error;
        3216                 :            :
        3217         [ #  # ]:          0 :     } while (n == BATCHSIZE);
        3218                 :          0 :     return 0;
        3219                 :            :
        3220                 :          0 :   error:
        3221                 :          0 :     Py_XDECREF(firstitem);
        3222                 :          0 :     Py_XDECREF(obj);
        3223                 :          0 :     return -1;
        3224                 :            : }
        3225                 :            :
        3226                 :            : /* This is a variant of batch_dict() above that specializes for dicts, with no
        3227                 :            :  * support for dict subclasses. Like batch_dict(), we batch up chunks of
        3228                 :            :  *     MARK key value ... key value SETITEMS
        3229                 :            :  * opcode sequences.  Calling code should have arranged to first create an
        3230                 :            :  * empty dict, or dict-like object, for the SETITEMS to operate on.
        3231                 :            :  * Returns 0 on success, -1 on error.
        3232                 :            :  *
        3233                 :            :  * Note that this currently doesn't work for protocol 0.
        3234                 :            :  */
        3235                 :            : static int
        3236                 :          0 : batch_dict_exact(PicklerObject *self, PyObject *obj)
        3237                 :            : {
        3238                 :          0 :     PyObject *key = NULL, *value = NULL;
        3239                 :            :     int i;
        3240                 :          0 :     Py_ssize_t dict_size, ppos = 0;
        3241                 :            :
        3242                 :          0 :     const char mark_op = MARK;
        3243                 :          0 :     const char setitem_op = SETITEM;
        3244                 :          0 :     const char setitems_op = SETITEMS;
        3245                 :            :
        3246                 :            :     assert(obj != NULL && PyDict_CheckExact(obj));
        3247                 :            :     assert(self->proto > 0);
        3248                 :            :
        3249                 :          0 :     dict_size = PyDict_GET_SIZE(obj);
        3250                 :            :
        3251                 :            :     /* Special-case len(d) == 1 to save space. */
        3252         [ #  # ]:          0 :     if (dict_size == 1) {
        3253                 :          0 :         PyDict_Next(obj, &ppos, &key, &value);
        3254                 :          0 :         Py_INCREF(key);
        3255                 :          0 :         Py_INCREF(value);
        3256         [ #  # ]:          0 :         if (save(self, key, 0) < 0) {
        3257                 :          0 :             goto error;
        3258                 :            :         }
        3259         [ #  # ]:          0 :         if (save(self, value, 0) < 0) {
        3260                 :          0 :             goto error;
        3261                 :            :         }
        3262         [ #  # ]:          0 :         Py_CLEAR(key);
        3263         [ #  # ]:          0 :         Py_CLEAR(value);
        3264         [ #  # ]:          0 :         if (_Pickler_Write(self, &setitem_op, 1) < 0)
        3265                 :          0 :             return -1;
        3266                 :          0 :         return 0;
        3267                 :            :     }
        3268                 :            :
        3269                 :            :     /* Write in batches of BATCHSIZE. */
        3270                 :            :     do {
        3271                 :          0 :         i = 0;
        3272         [ #  # ]:          0 :         if (_Pickler_Write(self, &mark_op, 1) < 0)
        3273                 :          0 :             return -1;
        3274         [ #  # ]:          0 :         while (PyDict_Next(obj, &ppos, &key, &value)) {
        3275                 :          0 :             Py_INCREF(key);
        3276                 :          0 :             Py_INCREF(value);
        3277         [ #  # ]:          0 :             if (save(self, key, 0) < 0) {
        3278                 :          0 :                 goto error;
        3279                 :            :             }
        3280         [ #  # ]:          0 :             if (save(self, value, 0) < 0) {
        3281                 :          0 :                 goto error;
        3282                 :            :             }
        3283         [ #  # ]:          0 :             Py_CLEAR(key);
        3284         [ #  # ]:          0 :             Py_CLEAR(value);
        3285         [ #  # ]:          0 :             if (++i == BATCHSIZE)
        3286                 :          0 :                 break;
        3287                 :            :         }
        3288         [ #  # ]:          0 :         if (_Pickler_Write(self, &setitems_op, 1) < 0)
        3289                 :          0 :             return -1;
        3290         [ #  # ]:          0 :         if (PyDict_GET_SIZE(obj) != dict_size) {
        3291                 :          0 :             PyErr_Format(
        3292                 :            :                 PyExc_RuntimeError,
        3293                 :            :                 "dictionary changed size during iteration");
        3294                 :          0 :             return -1;
        3295                 :            :         }
        3296                 :            :
        3297         [ #  # ]:          0 :     } while (i == BATCHSIZE);
        3298                 :          0 :     return 0;
        3299                 :          0 : error:
        3300                 :          0 :     Py_XDECREF(key);
        3301                 :          0 :     Py_XDECREF(value);
        3302                 :          0 :     return -1;
        3303                 :            : }
        3304                 :            :
        3305                 :            : static int
        3306                 :          0 : save_dict(PicklerObject *self, PyObject *obj)
        3307                 :            : {
        3308                 :            :     PyObject *items, *iter;
        3309                 :            :     char header[3];
        3310                 :            :     Py_ssize_t len;
        3311                 :          0 :     int status = 0;
        3312                 :            :     assert(PyDict_Check(obj));
        3313                 :            :
        3314   [ #  #  #  # ]:          0 :     if (self->fast && !fast_save_enter(self, obj))
        3315                 :          0 :         goto error;
        3316                 :            :
        3317                 :            :     /* Create an empty dict. */
        3318         [ #  # ]:          0 :     if (self->bin) {
        3319                 :          0 :         header[0] = EMPTY_DICT;
        3320                 :          0 :         len = 1;
        3321                 :            :     }
        3322                 :            :     else {
        3323                 :          0 :         header[0] = MARK;
        3324                 :          0 :         header[1] = DICT;
        3325                 :          0 :         len = 2;
        3326                 :            :     }
        3327                 :            :
        3328         [ #  # ]:          0 :     if (_Pickler_Write(self, header, len) < 0)
        3329                 :          0 :         goto error;
        3330                 :            :
        3331         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        3332                 :          0 :         goto error;
        3333                 :            :
        3334         [ #  # ]:          0 :     if (PyDict_GET_SIZE(obj)) {
        3335                 :            :         /* Save the dict items. */
        3336   [ #  #  #  # ]:          0 :         if (PyDict_CheckExact(obj) && self->proto > 0) {
        3337                 :            :             /* We can take certain shortcuts if we know this is a dict and
        3338                 :            :                not a dict subclass. */
        3339         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while pickling an object"))
        3340                 :          0 :                 goto error;
        3341                 :          0 :             status = batch_dict_exact(self, obj);
        3342                 :          0 :             _Py_LeaveRecursiveCall();
        3343                 :            :         } else {
        3344                 :          0 :             items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items));
        3345         [ #  # ]:          0 :             if (items == NULL)
        3346                 :          0 :                 goto error;
        3347                 :          0 :             iter = PyObject_GetIter(items);
        3348                 :          0 :             Py_DECREF(items);
        3349         [ #  # ]:          0 :             if (iter == NULL)
        3350                 :          0 :                 goto error;
        3351         [ #  # ]:          0 :             if (_Py_EnterRecursiveCall(" while pickling an object")) {
        3352                 :          0 :                 Py_DECREF(iter);
        3353                 :          0 :                 goto error;
        3354                 :            :             }
        3355                 :          0 :             status = batch_dict(self, iter);
        3356                 :          0 :             _Py_LeaveRecursiveCall();
        3357                 :          0 :             Py_DECREF(iter);
        3358                 :            :         }
        3359                 :            :     }
        3360                 :            :
        3361                 :            :     if (0) {
        3362                 :          0 :   error:
        3363                 :          0 :         status = -1;
        3364                 :            :     }
        3365                 :            :
        3366   [ #  #  #  # ]:          0 :     if (self->fast && !fast_save_leave(self, obj))
        3367                 :          0 :         status = -1;
        3368                 :            :
        3369                 :          0 :     return status;
        3370                 :            : }
        3371                 :            :
        3372                 :            : static int
        3373                 :          0 : save_set(PicklerObject *self, PyObject *obj)
        3374                 :            : {
        3375                 :            :     PyObject *item;
        3376                 :            :     int i;
        3377                 :          0 :     Py_ssize_t set_size, ppos = 0;
        3378                 :            :     Py_hash_t hash;
        3379                 :            :
        3380                 :          0 :     const char empty_set_op = EMPTY_SET;
        3381                 :          0 :     const char mark_op = MARK;
        3382                 :          0 :     const char additems_op = ADDITEMS;
        3383                 :            :
        3384         [ #  # ]:          0 :     if (self->proto < 4) {
        3385                 :            :         PyObject *items;
        3386                 :            :         PyObject *reduce_value;
        3387                 :            :         int status;
        3388                 :            :
        3389                 :          0 :         items = PySequence_List(obj);
        3390         [ #  # ]:          0 :         if (items == NULL) {
        3391                 :          0 :             return -1;
        3392                 :            :         }
        3393                 :          0 :         reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PySet_Type, items);
        3394                 :          0 :         Py_DECREF(items);
        3395         [ #  # ]:          0 :         if (reduce_value == NULL) {
        3396                 :          0 :             return -1;
        3397                 :            :         }
        3398                 :            :         /* save_reduce() will memoize the object automatically. */
        3399                 :          0 :         status = save_reduce(self, reduce_value, obj);
        3400                 :          0 :         Py_DECREF(reduce_value);
        3401                 :          0 :         return status;
        3402                 :            :     }
        3403                 :            :
        3404         [ #  # ]:          0 :     if (_Pickler_Write(self, &empty_set_op, 1) < 0)
        3405                 :          0 :         return -1;
        3406                 :            :
        3407         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        3408                 :          0 :         return -1;
        3409                 :            :
        3410                 :          0 :     set_size = PySet_GET_SIZE(obj);
        3411         [ #  # ]:          0 :     if (set_size == 0)
        3412                 :          0 :         return 0;  /* nothing to do */
        3413                 :            :
        3414                 :            :     /* Write in batches of BATCHSIZE. */
        3415                 :            :     do {
        3416                 :          0 :         i = 0;
        3417         [ #  # ]:          0 :         if (_Pickler_Write(self, &mark_op, 1) < 0)
        3418                 :          0 :             return -1;
        3419         [ #  # ]:          0 :         while (_PySet_NextEntry(obj, &ppos, &item, &hash)) {
        3420                 :          0 :             Py_INCREF(item);
        3421                 :          0 :             int err = save(self, item, 0);
        3422         [ #  # ]:          0 :             Py_CLEAR(item);
        3423         [ #  # ]:          0 :             if (err < 0)
        3424                 :          0 :                 return -1;
        3425         [ #  # ]:          0 :             if (++i == BATCHSIZE)
        3426                 :          0 :                 break;
        3427                 :            :         }
        3428         [ #  # ]:          0 :         if (_Pickler_Write(self, &additems_op, 1) < 0)
        3429                 :          0 :             return -1;
        3430         [ #  # ]:          0 :         if (PySet_GET_SIZE(obj) != set_size) {
        3431                 :          0 :             PyErr_Format(
        3432                 :            :                 PyExc_RuntimeError,
        3433                 :            :                 "set changed size during iteration");
        3434                 :          0 :             return -1;
        3435                 :            :         }
        3436         [ #  # ]:          0 :     } while (i == BATCHSIZE);
        3437                 :            :
        3438                 :          0 :     return 0;
        3439                 :            : }
        3440                 :            :
        3441                 :            : static int
        3442                 :          0 : save_frozenset(PicklerObject *self, PyObject *obj)
        3443                 :            : {
        3444                 :            :     PyObject *iter;
        3445                 :            :
        3446                 :          0 :     const char mark_op = MARK;
        3447                 :          0 :     const char frozenset_op = FROZENSET;
        3448                 :            :
        3449   [ #  #  #  # ]:          0 :     if (self->fast && !fast_save_enter(self, obj))
        3450                 :          0 :         return -1;
        3451                 :            :
        3452         [ #  # ]:          0 :     if (self->proto < 4) {
        3453                 :            :         PyObject *items;
        3454                 :            :         PyObject *reduce_value;
        3455                 :            :         int status;
        3456                 :            :
        3457                 :          0 :         items = PySequence_List(obj);
        3458         [ #  # ]:          0 :         if (items == NULL) {
        3459                 :          0 :             return -1;
        3460                 :            :         }
        3461                 :          0 :         reduce_value = Py_BuildValue("(O(O))", (PyObject*)&PyFrozenSet_Type,
        3462                 :            :                                      items);
        3463                 :          0 :         Py_DECREF(items);
        3464         [ #  # ]:          0 :         if (reduce_value == NULL) {
        3465                 :          0 :             return -1;
        3466                 :            :         }
        3467                 :            :         /* save_reduce() will memoize the object automatically. */
        3468                 :          0 :         status = save_reduce(self, reduce_value, obj);
        3469                 :          0 :         Py_DECREF(reduce_value);
        3470                 :          0 :         return status;
        3471                 :            :     }
        3472                 :            :
        3473         [ #  # ]:          0 :     if (_Pickler_Write(self, &mark_op, 1) < 0)
        3474                 :          0 :         return -1;
        3475                 :            :
        3476                 :          0 :     iter = PyObject_GetIter(obj);
        3477         [ #  # ]:          0 :     if (iter == NULL) {
        3478                 :          0 :         return -1;
        3479                 :            :     }
        3480                 :          0 :     for (;;) {
        3481                 :            :         PyObject *item;
        3482                 :            :
        3483                 :          0 :         item = PyIter_Next(iter);
        3484         [ #  # ]:          0 :         if (item == NULL) {
        3485         [ #  # ]:          0 :             if (PyErr_Occurred()) {
        3486                 :          0 :                 Py_DECREF(iter);
        3487                 :          0 :                 return -1;
        3488                 :            :             }
        3489                 :          0 :             break;
        3490                 :            :         }
        3491         [ #  # ]:          0 :         if (save(self, item, 0) < 0) {
        3492                 :          0 :             Py_DECREF(item);
        3493                 :          0 :             Py_DECREF(iter);
        3494                 :          0 :             return -1;
        3495                 :            :         }
        3496                 :          0 :         Py_DECREF(item);
        3497                 :            :     }
        3498                 :          0 :     Py_DECREF(iter);
        3499                 :            :
        3500                 :            :     /* If the object is already in the memo, this means it is
        3501                 :            :        recursive. In this case, throw away everything we put on the
        3502                 :            :        stack, and fetch the object back from the memo. */
        3503         [ #  # ]:          0 :     if (PyMemoTable_Get(self->memo, obj)) {
        3504                 :          0 :         const char pop_mark_op = POP_MARK;
        3505                 :            :
        3506         [ #  # ]:          0 :         if (_Pickler_Write(self, &pop_mark_op, 1) < 0)
        3507                 :          0 :             return -1;
        3508         [ #  # ]:          0 :         if (memo_get(self, obj) < 0)
        3509                 :          0 :             return -1;
        3510                 :          0 :         return 0;
        3511                 :            :     }
        3512                 :            :
        3513         [ #  # ]:          0 :     if (_Pickler_Write(self, &frozenset_op, 1) < 0)
        3514                 :          0 :         return -1;
        3515         [ #  # ]:          0 :     if (memo_put(self, obj) < 0)
        3516                 :          0 :         return -1;
        3517                 :            :
        3518                 :          0 :     return 0;
        3519                 :            : }
        3520                 :            :
        3521                 :            : static int
        3522                 :          0 : fix_imports(PyObject **module_name, PyObject **global_name)
        3523                 :            : {
        3524                 :            :     PyObject *key;
        3525                 :            :     PyObject *item;
        3526                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        3527                 :            :
        3528                 :          0 :     key = PyTuple_Pack(2, *module_name, *global_name);
        3529         [ #  # ]:          0 :     if (key == NULL)
        3530                 :          0 :         return -1;
        3531                 :          0 :     item = PyDict_GetItemWithError(st->name_mapping_3to2, key);
        3532                 :          0 :     Py_DECREF(key);
        3533         [ #  # ]:          0 :     if (item) {
        3534                 :            :         PyObject *fixed_module_name;
        3535                 :            :         PyObject *fixed_global_name;
        3536                 :            :
        3537   [ #  #  #  # ]:          0 :         if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
        3538                 :          0 :             PyErr_Format(PyExc_RuntimeError,
        3539                 :            :                          "_compat_pickle.REVERSE_NAME_MAPPING values "
        3540                 :            :                          "should be 2-tuples, not %.200s",
        3541                 :          0 :                          Py_TYPE(item)->tp_name);
        3542                 :          0 :             return -1;
        3543                 :            :         }
        3544                 :          0 :         fixed_module_name = PyTuple_GET_ITEM(item, 0);
        3545                 :          0 :         fixed_global_name = PyTuple_GET_ITEM(item, 1);
        3546   [ #  #  #  # ]:          0 :         if (!PyUnicode_Check(fixed_module_name) ||
        3547                 :          0 :             !PyUnicode_Check(fixed_global_name)) {
        3548                 :          0 :             PyErr_Format(PyExc_RuntimeError,
        3549                 :            :                          "_compat_pickle.REVERSE_NAME_MAPPING values "
        3550                 :            :                          "should be pairs of str, not (%.200s, %.200s)",
        3551                 :          0 :                          Py_TYPE(fixed_module_name)->tp_name,
        3552                 :          0 :                          Py_TYPE(fixed_global_name)->tp_name);
        3553                 :          0 :             return -1;
        3554                 :            :         }
        3555                 :            :
        3556         [ #  # ]:          0 :         Py_CLEAR(*module_name);
        3557         [ #  # ]:          0 :         Py_CLEAR(*global_name);
        3558                 :          0 :         *module_name = Py_NewRef(fixed_module_name);
        3559                 :          0 :         *global_name = Py_NewRef(fixed_global_name);
        3560                 :          0 :         return 0;
        3561                 :            :     }
        3562         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        3563                 :          0 :         return -1;
        3564                 :            :     }
        3565                 :            :
        3566                 :          0 :     item = PyDict_GetItemWithError(st->import_mapping_3to2, *module_name);
        3567         [ #  # ]:          0 :     if (item) {
        3568         [ #  # ]:          0 :         if (!PyUnicode_Check(item)) {
        3569                 :          0 :             PyErr_Format(PyExc_RuntimeError,
        3570                 :            :                          "_compat_pickle.REVERSE_IMPORT_MAPPING values "
        3571                 :            :                          "should be strings, not %.200s",
        3572                 :          0 :                          Py_TYPE(item)->tp_name);
        3573                 :          0 :             return -1;
        3574                 :            :         }
        3575                 :          0 :         Py_XSETREF(*module_name, Py_NewRef(item));
        3576                 :            :     }
        3577         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        3578                 :          0 :         return -1;
        3579                 :            :     }
        3580                 :            :
        3581                 :          0 :     return 0;
        3582                 :            : }
        3583                 :            :
        3584                 :            : static int
        3585                 :          0 : save_global(PicklerObject *self, PyObject *obj, PyObject *name)
        3586                 :            : {
        3587                 :          0 :     PyObject *global_name = NULL;
        3588                 :          0 :     PyObject *module_name = NULL;
        3589                 :          0 :     PyObject *module = NULL;
        3590                 :          0 :     PyObject *parent = NULL;
        3591                 :          0 :     PyObject *dotted_path = NULL;
        3592                 :          0 :     PyObject *lastname = NULL;
        3593                 :            :     PyObject *cls;
        3594                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        3595                 :          0 :     int status = 0;
        3596                 :            :
        3597                 :          0 :     const char global_op = GLOBAL;
        3598                 :            :
        3599         [ #  # ]:          0 :     if (name) {
        3600                 :          0 :         global_name = Py_NewRef(name);
        3601                 :            :     }
        3602                 :            :     else {
        3603         [ #  # ]:          0 :         if (_PyObject_LookupAttr(obj, &_Py_ID(__qualname__), &global_name) < 0)
        3604                 :          0 :             goto error;
        3605         [ #  # ]:          0 :         if (global_name == NULL) {
        3606                 :          0 :             global_name = PyObject_GetAttr(obj, &_Py_ID(__name__));
        3607         [ #  # ]:          0 :             if (global_name == NULL)
        3608                 :          0 :                 goto error;
        3609                 :            :         }
        3610                 :            :     }
        3611                 :            :
        3612                 :          0 :     dotted_path = get_dotted_path(module, global_name);
        3613         [ #  # ]:          0 :     if (dotted_path == NULL)
        3614                 :          0 :         goto error;
        3615                 :          0 :     module_name = whichmodule(obj, dotted_path);
        3616         [ #  # ]:          0 :     if (module_name == NULL)
        3617                 :          0 :         goto error;
        3618                 :            :
        3619                 :            :     /* XXX: Change to use the import C API directly with level=0 to disallow
        3620                 :            :        relative imports.
        3621                 :            :
        3622                 :            :        XXX: PyImport_ImportModuleLevel could be used. However, this bypasses
        3623                 :            :        builtins.__import__. Therefore, _pickle, unlike pickle.py, will ignore
        3624                 :            :        custom import functions (IMHO, this would be a nice security
        3625                 :            :        feature). The import C API would need to be extended to support the
        3626                 :            :        extra parameters of __import__ to fix that. */
        3627                 :          0 :     module = PyImport_Import(module_name);
        3628         [ #  # ]:          0 :     if (module == NULL) {
        3629                 :          0 :         PyErr_Format(st->PicklingError,
        3630                 :            :                      "Can't pickle %R: import of module %R failed",
        3631                 :            :                      obj, module_name);
        3632                 :          0 :         goto error;
        3633                 :            :     }
        3634                 :          0 :     lastname = Py_NewRef(PyList_GET_ITEM(dotted_path,
        3635                 :            :                          PyList_GET_SIZE(dotted_path) - 1));
        3636                 :          0 :     cls = get_deep_attribute(module, dotted_path, &parent);
        3637         [ #  # ]:          0 :     Py_CLEAR(dotted_path);
        3638         [ #  # ]:          0 :     if (cls == NULL) {
        3639                 :          0 :         PyErr_Format(st->PicklingError,
        3640                 :            :                      "Can't pickle %R: attribute lookup %S on %S failed",
        3641                 :            :                      obj, global_name, module_name);
        3642                 :          0 :         goto error;
        3643                 :            :     }
        3644         [ #  # ]:          0 :     if (cls != obj) {
        3645                 :          0 :         Py_DECREF(cls);
        3646                 :          0 :         PyErr_Format(st->PicklingError,
        3647                 :            :                      "Can't pickle %R: it's not the same object as %S.%S",
        3648                 :            :                      obj, module_name, global_name);
        3649                 :          0 :         goto error;
        3650                 :            :     }
        3651                 :          0 :     Py_DECREF(cls);
        3652                 :            :
        3653         [ #  # ]:          0 :     if (self->proto >= 2) {
        3654                 :            :         /* See whether this is in the extension registry, and if
        3655                 :            :          * so generate an EXT opcode.
        3656                 :            :          */
        3657                 :            :         PyObject *extension_key;
        3658                 :            :         PyObject *code_obj;      /* extension code as Python object */
        3659                 :            :         long code;               /* extension code as C value */
        3660                 :            :         char pdata[5];
        3661                 :            :         Py_ssize_t n;
        3662                 :            :
        3663                 :          0 :         extension_key = PyTuple_Pack(2, module_name, global_name);
        3664         [ #  # ]:          0 :         if (extension_key == NULL) {
        3665                 :          0 :             goto error;
        3666                 :            :         }
        3667                 :          0 :         code_obj = PyDict_GetItemWithError(st->extension_registry,
        3668                 :            :                                            extension_key);
        3669                 :          0 :         Py_DECREF(extension_key);
        3670                 :            :         /* The object is not registered in the extension registry.
        3671                 :            :            This is the most likely code path. */
        3672         [ #  # ]:          0 :         if (code_obj == NULL) {
        3673         [ #  # ]:          0 :             if (PyErr_Occurred()) {
        3674                 :          0 :                 goto error;
        3675                 :            :             }
        3676                 :          0 :             goto gen_global;
        3677                 :            :         }
        3678                 :            :
        3679                 :            :         /* XXX: pickle.py doesn't check neither the type, nor the range
        3680                 :            :            of the value returned by the extension_registry. It should for
        3681                 :            :            consistency. */
        3682                 :            :
        3683                 :            :         /* Verify code_obj has the right type and value. */
        3684         [ #  # ]:          0 :         if (!PyLong_Check(code_obj)) {
        3685                 :          0 :             PyErr_Format(st->PicklingError,
        3686                 :            :                          "Can't pickle %R: extension code %R isn't an integer",
        3687                 :            :                          obj, code_obj);
        3688                 :          0 :             goto error;
        3689                 :            :         }
        3690                 :          0 :         code = PyLong_AS_LONG(code_obj);
        3691   [ #  #  #  # ]:          0 :         if (code <= 0 || code > 0x7fffffffL) {
        3692         [ #  # ]:          0 :             if (!PyErr_Occurred())
        3693                 :          0 :                 PyErr_Format(st->PicklingError, "Can't pickle %R: extension "
        3694                 :            :                              "code %ld is out of range", obj, code);
        3695                 :          0 :             goto error;
        3696                 :            :         }
        3697                 :            :
        3698                 :            :         /* Generate an EXT opcode. */
        3699         [ #  # ]:          0 :         if (code <= 0xff) {
        3700                 :          0 :             pdata[0] = EXT1;
        3701                 :          0 :             pdata[1] = (unsigned char)code;
        3702                 :          0 :             n = 2;
        3703                 :            :         }
        3704         [ #  # ]:          0 :         else if (code <= 0xffff) {
        3705                 :          0 :             pdata[0] = EXT2;
        3706                 :          0 :             pdata[1] = (unsigned char)(code & 0xff);
        3707                 :          0 :             pdata[2] = (unsigned char)((code >> 8) & 0xff);
        3708                 :          0 :             n = 3;
        3709                 :            :         }
        3710                 :            :         else {
        3711                 :          0 :             pdata[0] = EXT4;
        3712                 :          0 :             pdata[1] = (unsigned char)(code & 0xff);
        3713                 :          0 :             pdata[2] = (unsigned char)((code >> 8) & 0xff);
        3714                 :          0 :             pdata[3] = (unsigned char)((code >> 16) & 0xff);
        3715                 :          0 :             pdata[4] = (unsigned char)((code >> 24) & 0xff);
        3716                 :          0 :             n = 5;
        3717                 :            :         }
        3718                 :            :
        3719         [ #  # ]:          0 :         if (_Pickler_Write(self, pdata, n) < 0)
        3720                 :          0 :             goto error;
        3721                 :            :     }
        3722                 :            :     else {
        3723                 :          0 :   gen_global:
        3724         [ #  # ]:          0 :         if (parent == module) {
        3725                 :          0 :             Py_SETREF(global_name, Py_NewRef(lastname));
        3726                 :            :         }
        3727         [ #  # ]:          0 :         if (self->proto >= 4) {
        3728                 :          0 :             const char stack_global_op = STACK_GLOBAL;
        3729                 :            :
        3730         [ #  # ]:          0 :             if (save(self, module_name, 0) < 0)
        3731                 :          0 :                 goto error;
        3732         [ #  # ]:          0 :             if (save(self, global_name, 0) < 0)
        3733                 :          0 :                 goto error;
        3734                 :            :
        3735         [ #  # ]:          0 :             if (_Pickler_Write(self, &stack_global_op, 1) < 0)
        3736                 :          0 :                 goto error;
        3737                 :            :         }
        3738         [ #  # ]:          0 :         else if (parent != module) {
        3739                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        3740                 :          0 :             PyObject *reduce_value = Py_BuildValue("(O(OO))",
        3741                 :            :                                         st->getattr, parent, lastname);
        3742         [ #  # ]:          0 :             if (reduce_value == NULL)
        3743                 :          0 :                 goto error;
        3744                 :          0 :             status = save_reduce(self, reduce_value, NULL);
        3745                 :          0 :             Py_DECREF(reduce_value);
        3746         [ #  # ]:          0 :             if (status < 0)
        3747                 :          0 :                 goto error;
        3748                 :            :         }
        3749                 :            :         else {
        3750                 :            :             /* Generate a normal global opcode if we are using a pickle
        3751                 :            :                protocol < 4, or if the object is not registered in the
        3752                 :            :                extension registry. */
        3753                 :            :             PyObject *encoded;
        3754                 :            :             PyObject *(*unicode_encoder)(PyObject *);
        3755                 :            :
        3756         [ #  # ]:          0 :             if (_Pickler_Write(self, &global_op, 1) < 0)
        3757                 :          0 :                 goto error;
        3758                 :            :
        3759                 :            :             /* For protocol < 3 and if the user didn't request against doing
        3760                 :            :                so, we convert module names to the old 2.x module names. */
        3761   [ #  #  #  # ]:          0 :             if (self->proto < 3 && self->fix_imports) {
        3762         [ #  # ]:          0 :                 if (fix_imports(&module_name, &global_name) < 0) {
        3763                 :          0 :                     goto error;
        3764                 :            :                 }
        3765                 :            :             }
        3766                 :            :
        3767                 :            :             /* Since Python 3.0 now supports non-ASCII identifiers, we encode
        3768                 :            :                both the module name and the global name using UTF-8. We do so
        3769                 :            :                only when we are using the pickle protocol newer than version
        3770                 :            :                3. This is to ensure compatibility with older Unpickler running
        3771                 :            :                on Python 2.x. */
        3772         [ #  # ]:          0 :             if (self->proto == 3) {
        3773                 :          0 :                 unicode_encoder = PyUnicode_AsUTF8String;
        3774                 :            :             }
        3775                 :            :             else {
        3776                 :          0 :                 unicode_encoder = PyUnicode_AsASCIIString;
        3777                 :            :             }
        3778                 :          0 :             encoded = unicode_encoder(module_name);
        3779         [ #  # ]:          0 :             if (encoded == NULL) {
        3780         [ #  # ]:          0 :                 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError))
        3781                 :          0 :                     PyErr_Format(st->PicklingError,
        3782                 :            :                                  "can't pickle module identifier '%S' using "
        3783                 :            :                                  "pickle protocol %i",
        3784                 :            :                                  module_name, self->proto);
        3785                 :          0 :                 goto error;
        3786                 :            :             }
        3787         [ #  # ]:          0 :             if (_Pickler_Write(self, PyBytes_AS_STRING(encoded),
        3788                 :            :                                PyBytes_GET_SIZE(encoded)) < 0) {
        3789                 :          0 :                 Py_DECREF(encoded);
        3790                 :          0 :                 goto error;
        3791                 :            :             }
        3792                 :          0 :             Py_DECREF(encoded);
        3793         [ #  # ]:          0 :             if(_Pickler_Write(self, "\n", 1) < 0)
        3794                 :          0 :                 goto error;
        3795                 :            :
        3796                 :            :             /* Save the name of the module. */
        3797                 :          0 :             encoded = unicode_encoder(global_name);
        3798         [ #  # ]:          0 :             if (encoded == NULL) {
        3799         [ #  # ]:          0 :                 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError))
        3800                 :          0 :                     PyErr_Format(st->PicklingError,
        3801                 :            :                                  "can't pickle global identifier '%S' using "
        3802                 :            :                                  "pickle protocol %i",
        3803                 :            :                                  global_name, self->proto);
        3804                 :          0 :                 goto error;
        3805                 :            :             }
        3806         [ #  # ]:          0 :             if (_Pickler_Write(self, PyBytes_AS_STRING(encoded),
        3807                 :            :                                PyBytes_GET_SIZE(encoded)) < 0) {
        3808                 :          0 :                 Py_DECREF(encoded);
        3809                 :          0 :                 goto error;
        3810                 :            :             }
        3811                 :          0 :             Py_DECREF(encoded);
        3812         [ #  # ]:          0 :             if (_Pickler_Write(self, "\n", 1) < 0)
        3813                 :          0 :                 goto error;
        3814                 :            :         }
        3815                 :            :         /* Memoize the object. */
        3816         [ #  # ]:          0 :         if (memo_put(self, obj) < 0)
        3817                 :          0 :             goto error;
        3818                 :            :     }
        3819                 :            :
        3820                 :            :     if (0) {
        3821                 :          0 :   error:
        3822                 :          0 :         status = -1;
        3823                 :            :     }
        3824                 :          0 :     Py_XDECREF(module_name);
        3825                 :          0 :     Py_XDECREF(global_name);
        3826                 :          0 :     Py_XDECREF(module);
        3827                 :          0 :     Py_XDECREF(parent);
        3828                 :          0 :     Py_XDECREF(dotted_path);
        3829                 :          0 :     Py_XDECREF(lastname);
        3830                 :            :
        3831                 :          0 :     return status;
        3832                 :            : }
        3833                 :            :
        3834                 :            : static int
        3835                 :          0 : save_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton)
        3836                 :            : {
        3837                 :            :     PyObject *reduce_value;
        3838                 :            :     int status;
        3839                 :            :
        3840                 :          0 :     reduce_value = Py_BuildValue("O(O)", &PyType_Type, singleton);
        3841         [ #  # ]:          0 :     if (reduce_value == NULL) {
        3842                 :          0 :         return -1;
        3843                 :            :     }
        3844                 :          0 :     status = save_reduce(self, reduce_value, obj);
        3845                 :          0 :     Py_DECREF(reduce_value);
        3846                 :          0 :     return status;
        3847                 :            : }
        3848                 :            :
        3849                 :            : static int
        3850                 :          0 : save_type(PicklerObject *self, PyObject *obj)
        3851                 :            : {
        3852         [ #  # ]:          0 :     if (obj == (PyObject *)&_PyNone_Type) {
        3853                 :          0 :         return save_singleton_type(self, obj, Py_None);
        3854                 :            :     }
        3855         [ #  # ]:          0 :     else if (obj == (PyObject *)&PyEllipsis_Type) {
        3856                 :          0 :         return save_singleton_type(self, obj, Py_Ellipsis);
        3857                 :            :     }
        3858         [ #  # ]:          0 :     else if (obj == (PyObject *)&_PyNotImplemented_Type) {
        3859                 :          0 :         return save_singleton_type(self, obj, Py_NotImplemented);
        3860                 :            :     }
        3861                 :          0 :     return save_global(self, obj, NULL);
        3862                 :            : }
        3863                 :            :
        3864                 :            : static int
        3865                 :          0 : save_pers(PicklerObject *self, PyObject *obj)
        3866                 :            : {
        3867                 :          0 :     PyObject *pid = NULL;
        3868                 :          0 :     int status = 0;
        3869                 :            :
        3870                 :          0 :     const char persid_op = PERSID;
        3871                 :          0 :     const char binpersid_op = BINPERSID;
        3872                 :            :
        3873                 :          0 :     pid = call_method(self->pers_func, self->pers_func_self, obj);
        3874         [ #  # ]:          0 :     if (pid == NULL)
        3875                 :          0 :         return -1;
        3876                 :            :
        3877         [ #  # ]:          0 :     if (pid != Py_None) {
        3878         [ #  # ]:          0 :         if (self->bin) {
        3879   [ #  #  #  # ]:          0 :             if (save(self, pid, 1) < 0 ||
        3880                 :          0 :                 _Pickler_Write(self, &binpersid_op, 1) < 0)
        3881                 :          0 :                 goto error;
        3882                 :            :         }
        3883                 :            :         else {
        3884                 :            :             PyObject *pid_str;
        3885                 :            :
        3886                 :          0 :             pid_str = PyObject_Str(pid);
        3887         [ #  # ]:          0 :             if (pid_str == NULL)
        3888                 :          0 :                 goto error;
        3889                 :            :
        3890                 :            :             /* XXX: Should it check whether the pid contains embedded
        3891                 :            :                newlines? */
        3892         [ #  # ]:          0 :             if (!PyUnicode_IS_ASCII(pid_str)) {
        3893                 :          0 :                 PyErr_SetString(_Pickle_GetGlobalState()->PicklingError,
        3894                 :            :                                 "persistent IDs in protocol 0 must be "
        3895                 :            :                                 "ASCII strings");
        3896                 :          0 :                 Py_DECREF(pid_str);
        3897                 :          0 :                 goto error;
        3898                 :            :             }
        3899                 :            :
        3900   [ #  #  #  # ]:          0 :             if (_Pickler_Write(self, &persid_op, 1) < 0 ||
        3901                 :          0 :                 _Pickler_Write(self, PyUnicode_DATA(pid_str),
        3902         [ #  # ]:          0 :                                PyUnicode_GET_LENGTH(pid_str)) < 0 ||
        3903                 :          0 :                 _Pickler_Write(self, "\n", 1) < 0) {
        3904                 :          0 :                 Py_DECREF(pid_str);
        3905                 :          0 :                 goto error;
        3906                 :            :             }
        3907                 :          0 :             Py_DECREF(pid_str);
        3908                 :            :         }
        3909                 :          0 :         status = 1;
        3910                 :            :     }
        3911                 :            :
        3912                 :            :     if (0) {
        3913                 :          0 :   error:
        3914                 :          0 :         status = -1;
        3915                 :            :     }
        3916                 :          0 :     Py_XDECREF(pid);
        3917                 :            :
        3918                 :          0 :     return status;
        3919                 :            : }
        3920                 :            :
        3921                 :            : static PyObject *
        3922                 :          0 : get_class(PyObject *obj)
        3923                 :            : {
        3924                 :            :     PyObject *cls;
        3925                 :            :
        3926         [ #  # ]:          0 :     if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &cls) == 0) {
        3927                 :          0 :         cls = Py_NewRef(Py_TYPE(obj));
        3928                 :            :     }
        3929                 :          0 :     return cls;
        3930                 :            : }
        3931                 :            :
        3932                 :            : /* We're saving obj, and args is the 2-thru-5 tuple returned by the
        3933                 :            :  * appropriate __reduce__ method for obj.
        3934                 :            :  */
        3935                 :            : static int
        3936                 :          0 : save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
        3937                 :            : {
        3938                 :            :     PyObject *callable;
        3939                 :            :     PyObject *argtup;
        3940                 :          0 :     PyObject *state = NULL;
        3941                 :          0 :     PyObject *listitems = Py_None;
        3942                 :          0 :     PyObject *dictitems = Py_None;
        3943                 :          0 :     PyObject *state_setter = Py_None;
        3944                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        3945                 :            :     Py_ssize_t size;
        3946                 :          0 :     int use_newobj = 0, use_newobj_ex = 0;
        3947                 :            :
        3948                 :          0 :     const char reduce_op = REDUCE;
        3949                 :          0 :     const char build_op = BUILD;
        3950                 :          0 :     const char newobj_op = NEWOBJ;
        3951                 :          0 :     const char newobj_ex_op = NEWOBJ_EX;
        3952                 :            :
        3953                 :          0 :     size = PyTuple_Size(args);
        3954   [ #  #  #  # ]:          0 :     if (size < 2 || size > 6) {
        3955                 :          0 :         PyErr_SetString(st->PicklingError, "tuple returned by "
        3956                 :            :                         "__reduce__ must contain 2 through 6 elements");
        3957                 :          0 :         return -1;
        3958                 :            :     }
        3959                 :            :
        3960         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "save_reduce", 2, 6,
        3961                 :            :                            &callable, &argtup, &state, &listitems, &dictitems,
        3962                 :            :                            &state_setter))
        3963                 :          0 :         return -1;
        3964                 :            :
        3965         [ #  # ]:          0 :     if (!PyCallable_Check(callable)) {
        3966                 :          0 :         PyErr_SetString(st->PicklingError, "first item of the tuple "
        3967                 :            :                         "returned by __reduce__ must be callable");
        3968                 :          0 :         return -1;
        3969                 :            :     }
        3970         [ #  # ]:          0 :     if (!PyTuple_Check(argtup)) {
        3971                 :          0 :         PyErr_SetString(st->PicklingError, "second item of the tuple "
        3972                 :            :                         "returned by __reduce__ must be a tuple");
        3973                 :          0 :         return -1;
        3974                 :            :     }
        3975                 :            :
        3976         [ #  # ]:          0 :     if (state == Py_None)
        3977                 :          0 :         state = NULL;
        3978                 :            :
        3979         [ #  # ]:          0 :     if (listitems == Py_None)
        3980                 :          0 :         listitems = NULL;
        3981         [ #  # ]:          0 :     else if (!PyIter_Check(listitems)) {
        3982                 :          0 :         PyErr_Format(st->PicklingError, "fourth element of the tuple "
        3983                 :            :                      "returned by __reduce__ must be an iterator, not %s",
        3984                 :          0 :                      Py_TYPE(listitems)->tp_name);
        3985                 :          0 :         return -1;
        3986                 :            :     }
        3987                 :            :
        3988         [ #  # ]:          0 :     if (dictitems == Py_None)
        3989                 :          0 :         dictitems = NULL;
        3990         [ #  # ]:          0 :     else if (!PyIter_Check(dictitems)) {
        3991                 :          0 :         PyErr_Format(st->PicklingError, "fifth element of the tuple "
        3992                 :            :                      "returned by __reduce__ must be an iterator, not %s",
        3993                 :          0 :                      Py_TYPE(dictitems)->tp_name);
        3994                 :          0 :         return -1;
        3995                 :            :     }
        3996                 :            :
        3997         [ #  # ]:          0 :     if (state_setter == Py_None)
        3998                 :          0 :         state_setter = NULL;
        3999         [ #  # ]:          0 :     else if (!PyCallable_Check(state_setter)) {
        4000                 :          0 :         PyErr_Format(st->PicklingError, "sixth element of the tuple "
        4001                 :            :                      "returned by __reduce__ must be a function, not %s",
        4002                 :          0 :                      Py_TYPE(state_setter)->tp_name);
        4003                 :          0 :         return -1;
        4004                 :            :     }
        4005                 :            :
        4006         [ #  # ]:          0 :     if (self->proto >= 2) {
        4007                 :            :         PyObject *name;
        4008                 :            :
        4009         [ #  # ]:          0 :         if (_PyObject_LookupAttr(callable, &_Py_ID(__name__), &name) < 0) {
        4010                 :          0 :             return -1;
        4011                 :            :         }
        4012   [ #  #  #  # ]:          0 :         if (name != NULL && PyUnicode_Check(name)) {
        4013                 :          0 :             use_newobj_ex = _PyUnicode_Equal(name, &_Py_ID(__newobj_ex__));
        4014         [ #  # ]:          0 :             if (!use_newobj_ex) {
        4015                 :          0 :                 use_newobj = _PyUnicode_Equal(name, &_Py_ID(__newobj__));
        4016                 :            :             }
        4017                 :            :         }
        4018                 :          0 :         Py_XDECREF(name);
        4019                 :            :     }
        4020                 :            :
        4021         [ #  # ]:          0 :     if (use_newobj_ex) {
        4022                 :            :         PyObject *cls;
        4023                 :            :         PyObject *args;
        4024                 :            :         PyObject *kwargs;
        4025                 :            :
        4026         [ #  # ]:          0 :         if (PyTuple_GET_SIZE(argtup) != 3) {
        4027                 :          0 :             PyErr_Format(st->PicklingError,
        4028                 :            :                          "length of the NEWOBJ_EX argument tuple must be "
        4029                 :            :                          "exactly 3, not %zd", PyTuple_GET_SIZE(argtup));
        4030                 :          0 :             return -1;
        4031                 :            :         }
        4032                 :            :
        4033                 :          0 :         cls = PyTuple_GET_ITEM(argtup, 0);
        4034         [ #  # ]:          0 :         if (!PyType_Check(cls)) {
        4035                 :          0 :             PyErr_Format(st->PicklingError,
        4036                 :            :                          "first item from NEWOBJ_EX argument tuple must "
        4037                 :          0 :                          "be a class, not %.200s", Py_TYPE(cls)->tp_name);
        4038                 :          0 :             return -1;
        4039                 :            :         }
        4040                 :          0 :         args = PyTuple_GET_ITEM(argtup, 1);
        4041         [ #  # ]:          0 :         if (!PyTuple_Check(args)) {
        4042                 :          0 :             PyErr_Format(st->PicklingError,
        4043                 :            :                          "second item from NEWOBJ_EX argument tuple must "
        4044                 :          0 :                          "be a tuple, not %.200s", Py_TYPE(args)->tp_name);
        4045                 :          0 :             return -1;
        4046                 :            :         }
        4047                 :          0 :         kwargs = PyTuple_GET_ITEM(argtup, 2);
        4048         [ #  # ]:          0 :         if (!PyDict_Check(kwargs)) {
        4049                 :          0 :             PyErr_Format(st->PicklingError,
        4050                 :            :                          "third item from NEWOBJ_EX argument tuple must "
        4051                 :          0 :                          "be a dict, not %.200s", Py_TYPE(kwargs)->tp_name);
        4052                 :          0 :             return -1;
        4053                 :            :         }
        4054                 :            :
        4055         [ #  # ]:          0 :         if (self->proto >= 4) {
        4056   [ #  #  #  # ]:          0 :             if (save(self, cls, 0) < 0 ||
        4057         [ #  # ]:          0 :                 save(self, args, 0) < 0 ||
        4058         [ #  # ]:          0 :                 save(self, kwargs, 0) < 0 ||
        4059                 :          0 :                 _Pickler_Write(self, &newobj_ex_op, 1) < 0) {
        4060                 :          0 :                 return -1;
        4061                 :            :             }
        4062                 :            :         }
        4063                 :            :         else {
        4064                 :            :             PyObject *newargs;
        4065                 :            :             PyObject *cls_new;
        4066                 :            :             Py_ssize_t i;
        4067                 :            :
        4068                 :          0 :             newargs = PyTuple_New(PyTuple_GET_SIZE(args) + 2);
        4069         [ #  # ]:          0 :             if (newargs == NULL)
        4070                 :          0 :                 return -1;
        4071                 :            :
        4072                 :          0 :             cls_new = PyObject_GetAttr(cls, &_Py_ID(__new__));
        4073         [ #  # ]:          0 :             if (cls_new == NULL) {
        4074                 :          0 :                 Py_DECREF(newargs);
        4075                 :          0 :                 return -1;
        4076                 :            :             }
        4077                 :          0 :             PyTuple_SET_ITEM(newargs, 0, cls_new);
        4078                 :          0 :             PyTuple_SET_ITEM(newargs, 1, Py_NewRef(cls));
        4079         [ #  # ]:          0 :             for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
        4080                 :          0 :                 PyObject *item = PyTuple_GET_ITEM(args, i);
        4081                 :          0 :                 PyTuple_SET_ITEM(newargs, i + 2, Py_NewRef(item));
        4082                 :            :             }
        4083                 :            :
        4084                 :          0 :             callable = PyObject_Call(st->partial, newargs, kwargs);
        4085                 :          0 :             Py_DECREF(newargs);
        4086         [ #  # ]:          0 :             if (callable == NULL)
        4087                 :          0 :                 return -1;
        4088                 :            :
        4089                 :          0 :             newargs = PyTuple_New(0);
        4090         [ #  # ]:          0 :             if (newargs == NULL) {
        4091                 :          0 :                 Py_DECREF(callable);
        4092                 :          0 :                 return -1;
        4093                 :            :             }
        4094                 :            :
        4095   [ #  #  #  # ]:          0 :             if (save(self, callable, 0) < 0 ||
        4096         [ #  # ]:          0 :                 save(self, newargs, 0) < 0 ||
        4097                 :          0 :                 _Pickler_Write(self, &reduce_op, 1) < 0) {
        4098                 :          0 :                 Py_DECREF(newargs);
        4099                 :          0 :                 Py_DECREF(callable);
        4100                 :          0 :                 return -1;
        4101                 :            :             }
        4102                 :          0 :             Py_DECREF(newargs);
        4103                 :          0 :             Py_DECREF(callable);
        4104                 :            :         }
        4105                 :            :     }
        4106         [ #  # ]:          0 :     else if (use_newobj) {
        4107                 :            :         PyObject *cls;
        4108                 :            :         PyObject *newargtup;
        4109                 :            :         PyObject *obj_class;
        4110                 :            :         int p;
        4111                 :            :
        4112                 :            :         /* Sanity checks. */
        4113         [ #  # ]:          0 :         if (PyTuple_GET_SIZE(argtup) < 1) {
        4114                 :          0 :             PyErr_SetString(st->PicklingError, "__newobj__ arglist is empty");
        4115                 :          0 :             return -1;
        4116                 :            :         }
        4117                 :            :
        4118                 :          0 :         cls = PyTuple_GET_ITEM(argtup, 0);
        4119         [ #  # ]:          0 :         if (!PyType_Check(cls)) {
        4120                 :          0 :             PyErr_SetString(st->PicklingError, "args[0] from "
        4121                 :            :                             "__newobj__ args is not a type");
        4122                 :          0 :             return -1;
        4123                 :            :         }
        4124                 :            :
        4125         [ #  # ]:          0 :         if (obj != NULL) {
        4126                 :          0 :             obj_class = get_class(obj);
        4127         [ #  # ]:          0 :             if (obj_class == NULL) {
        4128                 :          0 :                 return -1;
        4129                 :            :             }
        4130                 :          0 :             p = obj_class != cls;
        4131                 :          0 :             Py_DECREF(obj_class);
        4132         [ #  # ]:          0 :             if (p) {
        4133                 :          0 :                 PyErr_SetString(st->PicklingError, "args[0] from "
        4134                 :            :                                 "__newobj__ args has the wrong class");
        4135                 :          0 :                 return -1;
        4136                 :            :             }
        4137                 :            :         }
        4138                 :            :         /* XXX: These calls save() are prone to infinite recursion. Imagine
        4139                 :            :            what happen if the value returned by the __reduce__() method of
        4140                 :            :            some extension type contains another object of the same type. Ouch!
        4141                 :            :
        4142                 :            :            Here is a quick example, that I ran into, to illustrate what I
        4143                 :            :            mean:
        4144                 :            :
        4145                 :            :              >>> import pickle, copyreg
        4146                 :            :              >>> copyreg.dispatch_table.pop(complex)
        4147                 :            :              >>> pickle.dumps(1+2j)
        4148                 :            :              Traceback (most recent call last):
        4149                 :            :                ...
        4150                 :            :              RecursionError: maximum recursion depth exceeded
        4151                 :            :
        4152                 :            :            Removing the complex class from copyreg.dispatch_table made the
        4153                 :            :            __reduce_ex__() method emit another complex object:
        4154                 :            :
        4155                 :            :              >>> (1+1j).__reduce_ex__(2)
        4156                 :            :              (<function __newobj__ at 0xb7b71c3c>,
        4157                 :            :                (<class 'complex'>, (1+1j)), None, None, None)
        4158                 :            :
        4159                 :            :            Thus when save() was called on newargstup (the 2nd item) recursion
        4160                 :            :            ensued. Of course, the bug was in the complex class which had a
        4161                 :            :            broken __getnewargs__() that emitted another complex object. But,
        4162                 :            :            the point, here, is it is quite easy to end up with a broken reduce
        4163                 :            :            function. */
        4164                 :            :
        4165                 :            :         /* Save the class and its __new__ arguments. */
        4166         [ #  # ]:          0 :         if (save(self, cls, 0) < 0)
        4167                 :          0 :             return -1;
        4168                 :            :
        4169                 :          0 :         newargtup = PyTuple_GetSlice(argtup, 1, PyTuple_GET_SIZE(argtup));
        4170         [ #  # ]:          0 :         if (newargtup == NULL)
        4171                 :          0 :             return -1;
        4172                 :            :
        4173                 :          0 :         p = save(self, newargtup, 0);
        4174                 :          0 :         Py_DECREF(newargtup);
        4175         [ #  # ]:          0 :         if (p < 0)
        4176                 :          0 :             return -1;
        4177                 :            :
        4178                 :            :         /* Add NEWOBJ opcode. */
        4179         [ #  # ]:          0 :         if (_Pickler_Write(self, &newobj_op, 1) < 0)
        4180                 :          0 :             return -1;
        4181                 :            :     }
        4182                 :            :     else { /* Not using NEWOBJ. */
        4183   [ #  #  #  # ]:          0 :         if (save(self, callable, 0) < 0 ||
        4184         [ #  # ]:          0 :             save(self, argtup, 0) < 0 ||
        4185                 :          0 :             _Pickler_Write(self, &reduce_op, 1) < 0)
        4186                 :          0 :             return -1;
        4187                 :            :     }
        4188                 :            :
        4189                 :            :     /* obj can be NULL when save_reduce() is used directly. A NULL obj means
        4190                 :            :        the caller do not want to memoize the object. Not particularly useful,
        4191                 :            :        but that is to mimic the behavior save_reduce() in pickle.py when
        4192                 :            :        obj is None. */
        4193         [ #  # ]:          0 :     if (obj != NULL) {
        4194                 :            :         /* If the object is already in the memo, this means it is
        4195                 :            :            recursive. In this case, throw away everything we put on the
        4196                 :            :            stack, and fetch the object back from the memo. */
        4197         [ #  # ]:          0 :         if (PyMemoTable_Get(self->memo, obj)) {
        4198                 :          0 :             const char pop_op = POP;
        4199                 :            :
        4200         [ #  # ]:          0 :             if (_Pickler_Write(self, &pop_op, 1) < 0)
        4201                 :          0 :                 return -1;
        4202         [ #  # ]:          0 :             if (memo_get(self, obj) < 0)
        4203                 :          0 :                 return -1;
        4204                 :            :
        4205                 :          0 :             return 0;
        4206                 :            :         }
        4207         [ #  # ]:          0 :         else if (memo_put(self, obj) < 0)
        4208                 :          0 :             return -1;
        4209                 :            :     }
        4210                 :            :
        4211   [ #  #  #  # ]:          0 :     if (listitems && batch_list(self, listitems) < 0)
        4212                 :          0 :         return -1;
        4213                 :            :
        4214   [ #  #  #  # ]:          0 :     if (dictitems && batch_dict(self, dictitems) < 0)
        4215                 :          0 :         return -1;
        4216                 :            :
        4217         [ #  # ]:          0 :     if (state) {
        4218         [ #  # ]:          0 :         if (state_setter == NULL) {
        4219   [ #  #  #  # ]:          0 :             if (save(self, state, 0) < 0 ||
        4220                 :          0 :                 _Pickler_Write(self, &build_op, 1) < 0)
        4221                 :          0 :                 return -1;
        4222                 :            :         }
        4223                 :            :         else {
        4224                 :            :
        4225                 :            :             /* If a state_setter is specified, call it instead of load_build to
        4226                 :            :              * update obj's with its previous state.
        4227                 :            :              * The first 4 save/write instructions push state_setter and its
        4228                 :            :              * tuple of expected arguments (obj, state) onto the stack. The
        4229                 :            :              * REDUCE opcode triggers the state_setter(obj, state) function
        4230                 :            :              * call. Finally, because state-updating routines only do in-place
        4231                 :            :              * modification, the whole operation has to be stack-transparent.
        4232                 :            :              * Thus, we finally pop the call's output from the stack.*/
        4233                 :            :
        4234                 :          0 :             const char tupletwo_op = TUPLE2;
        4235                 :          0 :             const char pop_op = POP;
        4236   [ #  #  #  # ]:          0 :             if (save(self, state_setter, 0) < 0 ||
        4237   [ #  #  #  # ]:          0 :                 save(self, obj, 0) < 0 || save(self, state, 0) < 0 ||
        4238         [ #  # ]:          0 :                 _Pickler_Write(self, &tupletwo_op, 1) < 0 ||
        4239         [ #  # ]:          0 :                 _Pickler_Write(self, &reduce_op, 1) < 0 ||
        4240                 :          0 :                 _Pickler_Write(self, &pop_op, 1) < 0)
        4241                 :          0 :                 return -1;
        4242                 :            :         }
        4243                 :            :     }
        4244                 :          0 :     return 0;
        4245                 :            : }
        4246                 :            :
        4247                 :            : static int
        4248                 :          0 : save(PicklerObject *self, PyObject *obj, int pers_save)
        4249                 :            : {
        4250                 :            :     PyTypeObject *type;
        4251                 :          0 :     PyObject *reduce_func = NULL;
        4252                 :          0 :     PyObject *reduce_value = NULL;
        4253                 :          0 :     int status = 0;
        4254                 :            :
        4255         [ #  # ]:          0 :     if (_Pickler_OpcodeBoundary(self) < 0)
        4256                 :          0 :         return -1;
        4257                 :            :
        4258                 :            :     /* The extra pers_save argument is necessary to avoid calling save_pers()
        4259                 :            :        on its returned object. */
        4260   [ #  #  #  # ]:          0 :     if (!pers_save && self->pers_func) {
        4261                 :            :         /* save_pers() returns:
        4262                 :            :             -1   to signal an error;
        4263                 :            :              0   if it did nothing successfully;
        4264                 :            :              1   if a persistent id was saved.
        4265                 :            :          */
        4266         [ #  # ]:          0 :         if ((status = save_pers(self, obj)) != 0)
        4267                 :          0 :             return status;
        4268                 :            :     }
        4269                 :            :
        4270                 :          0 :     type = Py_TYPE(obj);
        4271                 :            :
        4272                 :            :     /* The old cPickle had an optimization that used switch-case statement
        4273                 :            :        dispatching on the first letter of the type name.  This has was removed
        4274                 :            :        since benchmarks shown that this optimization was actually slowing
        4275                 :            :        things down. */
        4276                 :            :
        4277                 :            :     /* Atom types; these aren't memoized, so don't check the memo. */
        4278                 :            :
        4279         [ #  # ]:          0 :     if (obj == Py_None) {
        4280                 :          0 :         return save_none(self, obj);
        4281                 :            :     }
        4282   [ #  #  #  # ]:          0 :     else if (obj == Py_False || obj == Py_True) {
        4283                 :          0 :         return save_bool(self, obj);
        4284                 :            :     }
        4285         [ #  # ]:          0 :     else if (type == &PyLong_Type) {
        4286                 :          0 :         return save_long(self, obj);
        4287                 :            :     }
        4288         [ #  # ]:          0 :     else if (type == &PyFloat_Type) {
        4289                 :          0 :         return save_float(self, obj);
        4290                 :            :     }
        4291                 :            :
        4292                 :            :     /* Check the memo to see if it has the object. If so, generate
        4293                 :            :        a GET (or BINGET) opcode, instead of pickling the object
        4294                 :            :        once again. */
        4295         [ #  # ]:          0 :     if (PyMemoTable_Get(self->memo, obj)) {
        4296                 :          0 :         return memo_get(self, obj);
        4297                 :            :     }
        4298                 :            :
        4299         [ #  # ]:          0 :     if (type == &PyBytes_Type) {
        4300                 :          0 :         return save_bytes(self, obj);
        4301                 :            :     }
        4302         [ #  # ]:          0 :     else if (type == &PyUnicode_Type) {
        4303                 :          0 :         return save_unicode(self, obj);
        4304                 :            :     }
        4305                 :            :
        4306                 :            :     /* We're only calling _Py_EnterRecursiveCall here so that atomic
        4307                 :            :        types above are pickled faster. */
        4308         [ #  # ]:          0 :     if (_Py_EnterRecursiveCall(" while pickling an object")) {
        4309                 :          0 :         return -1;
        4310                 :            :     }
        4311                 :            :
        4312         [ #  # ]:          0 :     if (type == &PyDict_Type) {
        4313                 :          0 :         status = save_dict(self, obj);
        4314                 :          0 :         goto done;
        4315                 :            :     }
        4316         [ #  # ]:          0 :     else if (type == &PySet_Type) {
        4317                 :          0 :         status = save_set(self, obj);
        4318                 :          0 :         goto done;
        4319                 :            :     }
        4320         [ #  # ]:          0 :     else if (type == &PyFrozenSet_Type) {
        4321                 :          0 :         status = save_frozenset(self, obj);
        4322                 :          0 :         goto done;
        4323                 :            :     }
        4324         [ #  # ]:          0 :     else if (type == &PyList_Type) {
        4325                 :          0 :         status = save_list(self, obj);
        4326                 :          0 :         goto done;
        4327                 :            :     }
        4328         [ #  # ]:          0 :     else if (type == &PyTuple_Type) {
        4329                 :          0 :         status = save_tuple(self, obj);
        4330                 :          0 :         goto done;
        4331                 :            :     }
        4332         [ #  # ]:          0 :     else if (type == &PyByteArray_Type) {
        4333                 :          0 :         status = save_bytearray(self, obj);
        4334                 :          0 :         goto done;
        4335                 :            :     }
        4336         [ #  # ]:          0 :     else if (type == &PyPickleBuffer_Type) {
        4337                 :          0 :         status = save_picklebuffer(self, obj);
        4338                 :          0 :         goto done;
        4339                 :            :     }
        4340                 :            :
        4341                 :            :     /* Now, check reducer_override.  If it returns NotImplemented,
        4342                 :            :      * fallback to save_type or save_global, and then perhaps to the
        4343                 :            :      * regular reduction mechanism.
        4344                 :            :      */
        4345         [ #  # ]:          0 :     if (self->reducer_override != NULL) {
        4346                 :          0 :         reduce_value = PyObject_CallOneArg(self->reducer_override, obj);
        4347         [ #  # ]:          0 :         if (reduce_value == NULL) {
        4348                 :          0 :             goto error;
        4349                 :            :         }
        4350         [ #  # ]:          0 :         if (reduce_value != Py_NotImplemented) {
        4351                 :          0 :             goto reduce;
        4352                 :            :         }
        4353                 :          0 :         Py_SETREF(reduce_value, NULL);
        4354                 :            :     }
        4355                 :            :
        4356         [ #  # ]:          0 :     if (type == &PyType_Type) {
        4357                 :          0 :         status = save_type(self, obj);
        4358                 :          0 :         goto done;
        4359                 :            :     }
        4360         [ #  # ]:          0 :     else if (type == &PyFunction_Type) {
        4361                 :          0 :         status = save_global(self, obj, NULL);
        4362                 :          0 :         goto done;
        4363                 :            :     }
        4364                 :            :
        4365                 :            :     /* XXX: This part needs some unit tests. */
        4366                 :            :
        4367                 :            :     /* Get a reduction callable, and call it.  This may come from
        4368                 :            :      * self.dispatch_table, copyreg.dispatch_table, the object's
        4369                 :            :      * __reduce_ex__ method, or the object's __reduce__ method.
        4370                 :            :      */
        4371         [ #  # ]:          0 :     if (self->dispatch_table == NULL) {
        4372                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        4373                 :          0 :         reduce_func = PyDict_GetItemWithError(st->dispatch_table,
        4374                 :            :                                               (PyObject *)type);
        4375         [ #  # ]:          0 :         if (reduce_func == NULL) {
        4376         [ #  # ]:          0 :             if (PyErr_Occurred()) {
        4377                 :          0 :                 goto error;
        4378                 :            :             }
        4379                 :            :         } else {
        4380                 :            :             /* PyDict_GetItemWithError() returns a borrowed reference.
        4381                 :            :                Increase the reference count to be consistent with
        4382                 :            :                PyObject_GetItem and _PyObject_GetAttrId used below. */
        4383                 :          0 :             Py_INCREF(reduce_func);
        4384                 :            :         }
        4385                 :            :     } else {
        4386                 :          0 :         reduce_func = PyObject_GetItem(self->dispatch_table,
        4387                 :            :                                        (PyObject *)type);
        4388         [ #  # ]:          0 :         if (reduce_func == NULL) {
        4389         [ #  # ]:          0 :             if (PyErr_ExceptionMatches(PyExc_KeyError))
        4390                 :          0 :                 PyErr_Clear();
        4391                 :            :             else
        4392                 :          0 :                 goto error;
        4393                 :            :         }
        4394                 :            :     }
        4395         [ #  # ]:          0 :     if (reduce_func != NULL) {
        4396                 :          0 :         reduce_value = _Pickle_FastCall(reduce_func, Py_NewRef(obj));
        4397                 :            :     }
        4398         [ #  # ]:          0 :     else if (PyType_IsSubtype(type, &PyType_Type)) {
        4399                 :          0 :         status = save_global(self, obj, NULL);
        4400                 :          0 :         goto done;
        4401                 :            :     }
        4402                 :            :     else {
        4403                 :            :         /* XXX: If the __reduce__ method is defined, __reduce_ex__ is
        4404                 :            :            automatically defined as __reduce__. While this is convenient, this
        4405                 :            :            make it impossible to know which method was actually called. Of
        4406                 :            :            course, this is not a big deal. But still, it would be nice to let
        4407                 :            :            the user know which method was called when something go
        4408                 :            :            wrong. Incidentally, this means if __reduce_ex__ is not defined, we
        4409                 :            :            don't actually have to check for a __reduce__ method. */
        4410                 :            :
        4411                 :            :         /* Check for a __reduce_ex__ method. */
        4412         [ #  # ]:          0 :         if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce_ex__), &reduce_func) < 0) {
        4413                 :          0 :             goto error;
        4414                 :            :         }
        4415         [ #  # ]:          0 :         if (reduce_func != NULL) {
        4416                 :            :             PyObject *proto;
        4417                 :          0 :             proto = PyLong_FromLong(self->proto);
        4418         [ #  # ]:          0 :             if (proto != NULL) {
        4419                 :          0 :                 reduce_value = _Pickle_FastCall(reduce_func, proto);
        4420                 :            :             }
        4421                 :            :         }
        4422                 :            :         else {
        4423                 :            :             /* Check for a __reduce__ method. */
        4424         [ #  # ]:          0 :             if (_PyObject_LookupAttr(obj, &_Py_ID(__reduce__), &reduce_func) < 0) {
        4425                 :          0 :                 goto error;
        4426                 :            :             }
        4427         [ #  # ]:          0 :             if (reduce_func != NULL) {
        4428                 :          0 :                 reduce_value = PyObject_CallNoArgs(reduce_func);
        4429                 :            :             }
        4430                 :            :             else {
        4431                 :          0 :                 PickleState *st = _Pickle_GetGlobalState();
        4432                 :          0 :                 PyErr_Format(st->PicklingError,
        4433                 :            :                              "can't pickle '%.200s' object: %R",
        4434                 :            :                              type->tp_name, obj);
        4435                 :          0 :                 goto error;
        4436                 :            :             }
        4437                 :            :         }
        4438                 :            :     }
        4439                 :            :
        4440         [ #  # ]:          0 :     if (reduce_value == NULL)
        4441                 :          0 :         goto error;
        4442                 :            :
        4443                 :          0 :   reduce:
        4444         [ #  # ]:          0 :     if (PyUnicode_Check(reduce_value)) {
        4445                 :          0 :         status = save_global(self, obj, reduce_value);
        4446                 :          0 :         goto done;
        4447                 :            :     }
        4448                 :            :
        4449         [ #  # ]:          0 :     if (!PyTuple_Check(reduce_value)) {
        4450                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        4451                 :          0 :         PyErr_SetString(st->PicklingError,
        4452                 :            :                         "__reduce__ must return a string or tuple");
        4453                 :          0 :         goto error;
        4454                 :            :     }
        4455                 :            :
        4456                 :          0 :     status = save_reduce(self, reduce_value, obj);
        4457                 :            :
        4458                 :            :     if (0) {
        4459                 :          0 :   error:
        4460                 :          0 :         status = -1;
        4461                 :            :     }
        4462                 :          0 :   done:
        4463                 :            :
        4464                 :          0 :     _Py_LeaveRecursiveCall();
        4465                 :          0 :     Py_XDECREF(reduce_func);
        4466                 :          0 :     Py_XDECREF(reduce_value);
        4467                 :            :
        4468                 :          0 :     return status;
        4469                 :            : }
        4470                 :            :
        4471                 :            : static int
        4472                 :          0 : dump(PicklerObject *self, PyObject *obj)
        4473                 :            : {
        4474                 :          0 :     const char stop_op = STOP;
        4475                 :          0 :     int status = -1;
        4476                 :            :     PyObject *tmp;
        4477                 :            :
        4478         [ #  # ]:          0 :     if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(reducer_override),
        4479                 :            :                              &tmp) < 0) {
        4480                 :          0 :       goto error;
        4481                 :            :     }
        4482                 :            :     /* Cache the reducer_override method, if it exists. */
        4483         [ #  # ]:          0 :     if (tmp != NULL) {
        4484                 :          0 :         Py_XSETREF(self->reducer_override, tmp);
        4485                 :            :     }
        4486                 :            :     else {
        4487         [ #  # ]:          0 :         Py_CLEAR(self->reducer_override);
        4488                 :            :     }
        4489                 :            :
        4490         [ #  # ]:          0 :     if (self->proto >= 2) {
        4491                 :            :         char header[2];
        4492                 :            :
        4493                 :          0 :         header[0] = PROTO;
        4494                 :            :         assert(self->proto >= 0 && self->proto < 256);
        4495                 :          0 :         header[1] = (unsigned char)self->proto;
        4496         [ #  # ]:          0 :         if (_Pickler_Write(self, header, 2) < 0)
        4497                 :          0 :             goto error;
        4498         [ #  # ]:          0 :         if (self->proto >= 4)
        4499                 :          0 :             self->framing = 1;
        4500                 :            :     }
        4501                 :            :
        4502   [ #  #  #  # ]:          0 :     if (save(self, obj, 0) < 0 ||
        4503         [ #  # ]:          0 :         _Pickler_Write(self, &stop_op, 1) < 0 ||
        4504                 :          0 :         _Pickler_CommitFrame(self) < 0)
        4505                 :          0 :         goto error;
        4506                 :            :
        4507                 :            :     // Success
        4508                 :          0 :     status = 0;
        4509                 :            :
        4510                 :          0 :   error:
        4511                 :          0 :     self->framing = 0;
        4512                 :            :
        4513                 :            :     /* Break the reference cycle we generated at the beginning this function
        4514                 :            :      * call when setting the reducer_override attribute of the Pickler instance
        4515                 :            :      * to a bound method of the same instance. This is important as the Pickler
        4516                 :            :      * instance holds a reference to each object it has pickled (through its
        4517                 :            :      * memo): thus, these objects won't be garbage-collected as long as the
        4518                 :            :      * Pickler itself is not collected. */
        4519         [ #  # ]:          0 :     Py_CLEAR(self->reducer_override);
        4520                 :          0 :     return status;
        4521                 :            : }
        4522                 :            :
        4523                 :            : /*[clinic input]
        4524                 :            :
        4525                 :            : _pickle.Pickler.clear_memo
        4526                 :            :
        4527                 :            : Clears the pickler's "memo".
        4528                 :            :
        4529                 :            : The memo is the data structure that remembers which objects the
        4530                 :            : pickler has already seen, so that shared or recursive objects are
        4531                 :            : pickled by reference and not by value.  This method is useful when
        4532                 :            : re-using picklers.
        4533                 :            : [clinic start generated code]*/
        4534                 :            :
        4535                 :            : static PyObject *
        4536                 :          0 : _pickle_Pickler_clear_memo_impl(PicklerObject *self)
        4537                 :            : /*[clinic end generated code: output=8665c8658aaa094b input=01bdad52f3d93e56]*/
        4538                 :            : {
        4539         [ #  # ]:          0 :     if (self->memo)
        4540                 :          0 :         PyMemoTable_Clear(self->memo);
        4541                 :            :
        4542                 :          0 :     Py_RETURN_NONE;
        4543                 :            : }
        4544                 :            :
        4545                 :            : /*[clinic input]
        4546                 :            :
        4547                 :            : _pickle.Pickler.dump
        4548                 :            :
        4549                 :            :   obj: object
        4550                 :            :   /
        4551                 :            :
        4552                 :            : Write a pickled representation of the given object to the open file.
        4553                 :            : [clinic start generated code]*/
        4554                 :            :
        4555                 :            : static PyObject *
        4556                 :          0 : _pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
        4557                 :            : /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/
        4558                 :            : {
        4559                 :            :     /* Check whether the Pickler was initialized correctly (issue3664).
        4560                 :            :        Developers often forget to call __init__() in their subclasses, which
        4561                 :            :        would trigger a segfault without this check. */
        4562         [ #  # ]:          0 :     if (self->write == NULL) {
        4563                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        4564                 :          0 :         PyErr_Format(st->PicklingError,
        4565                 :            :                      "Pickler.__init__() was not called by %s.__init__()",
        4566                 :          0 :                      Py_TYPE(self)->tp_name);
        4567                 :          0 :         return NULL;
        4568                 :            :     }
        4569                 :            :
        4570         [ #  # ]:          0 :     if (_Pickler_ClearBuffer(self) < 0)
        4571                 :          0 :         return NULL;
        4572                 :            :
        4573         [ #  # ]:          0 :     if (dump(self, obj) < 0)
        4574                 :          0 :         return NULL;
        4575                 :            :
        4576         [ #  # ]:          0 :     if (_Pickler_FlushToFile(self) < 0)
        4577                 :          0 :         return NULL;
        4578                 :            :
        4579                 :          0 :     Py_RETURN_NONE;
        4580                 :            : }
        4581                 :            :
        4582                 :            : /*[clinic input]
        4583                 :            :
        4584                 :            : _pickle.Pickler.__sizeof__ -> size_t
        4585                 :            :
        4586                 :            : Returns size in memory, in bytes.
        4587                 :            : [clinic start generated code]*/
        4588                 :            :
        4589                 :            : static size_t
        4590                 :          0 : _pickle_Pickler___sizeof___impl(PicklerObject *self)
        4591                 :            : /*[clinic end generated code: output=23ad75658d3b59ff input=d8127c8e7012ebd7]*/
        4592                 :            : {
        4593                 :          0 :     size_t res = _PyObject_SIZE(Py_TYPE(self));
        4594         [ #  # ]:          0 :     if (self->memo != NULL) {
        4595                 :          0 :         res += sizeof(PyMemoTable);
        4596                 :          0 :         res += self->memo->mt_allocated * sizeof(PyMemoEntry);
        4597                 :            :     }
        4598         [ #  # ]:          0 :     if (self->output_buffer != NULL) {
        4599                 :          0 :         size_t s = _PySys_GetSizeOf(self->output_buffer);
        4600         [ #  # ]:          0 :         if (s == (size_t)-1) {
        4601                 :          0 :             return -1;
        4602                 :            :         }
        4603                 :          0 :         res += s;
        4604                 :            :     }
        4605                 :          0 :     return res;
        4606                 :            : }
        4607                 :            :
        4608                 :            : static struct PyMethodDef Pickler_methods[] = {
        4609                 :            :     _PICKLE_PICKLER_DUMP_METHODDEF
        4610                 :            :     _PICKLE_PICKLER_CLEAR_MEMO_METHODDEF
        4611                 :            :     _PICKLE_PICKLER___SIZEOF___METHODDEF
        4612                 :            :     {NULL, NULL}                /* sentinel */
        4613                 :            : };
        4614                 :            :
        4615                 :            : static void
        4616                 :          0 : Pickler_dealloc(PicklerObject *self)
        4617                 :            : {
        4618                 :          0 :     PyObject_GC_UnTrack(self);
        4619                 :            :
        4620                 :          0 :     Py_XDECREF(self->output_buffer);
        4621                 :          0 :     Py_XDECREF(self->write);
        4622                 :          0 :     Py_XDECREF(self->pers_func);
        4623                 :          0 :     Py_XDECREF(self->dispatch_table);
        4624                 :          0 :     Py_XDECREF(self->fast_memo);
        4625                 :          0 :     Py_XDECREF(self->reducer_override);
        4626                 :          0 :     Py_XDECREF(self->buffer_callback);
        4627                 :            :
        4628                 :          0 :     PyMemoTable_Del(self->memo);
        4629                 :            :
        4630                 :          0 :     Py_TYPE(self)->tp_free((PyObject *)self);
        4631                 :          0 : }
        4632                 :            :
        4633                 :            : static int
        4634                 :          0 : Pickler_traverse(PicklerObject *self, visitproc visit, void *arg)
        4635                 :            : {
        4636   [ #  #  #  # ]:          0 :     Py_VISIT(self->write);
        4637   [ #  #  #  # ]:          0 :     Py_VISIT(self->pers_func);
        4638   [ #  #  #  # ]:          0 :     Py_VISIT(self->dispatch_table);
        4639   [ #  #  #  # ]:          0 :     Py_VISIT(self->fast_memo);
        4640   [ #  #  #  # ]:          0 :     Py_VISIT(self->reducer_override);
        4641   [ #  #  #  # ]:          0 :     Py_VISIT(self->buffer_callback);
        4642                 :          0 :     return 0;
        4643                 :            : }
        4644                 :            :
        4645                 :            : static int
        4646                 :          0 : Pickler_clear(PicklerObject *self)
        4647                 :            : {
        4648         [ #  # ]:          0 :     Py_CLEAR(self->output_buffer);
        4649         [ #  # ]:          0 :     Py_CLEAR(self->write);
        4650         [ #  # ]:          0 :     Py_CLEAR(self->pers_func);
        4651         [ #  # ]:          0 :     Py_CLEAR(self->dispatch_table);
        4652         [ #  # ]:          0 :     Py_CLEAR(self->fast_memo);
        4653         [ #  # ]:          0 :     Py_CLEAR(self->reducer_override);
        4654         [ #  # ]:          0 :     Py_CLEAR(self->buffer_callback);
        4655                 :            :
        4656         [ #  # ]:          0 :     if (self->memo != NULL) {
        4657                 :          0 :         PyMemoTable *memo = self->memo;
        4658                 :          0 :         self->memo = NULL;
        4659                 :          0 :         PyMemoTable_Del(memo);
        4660                 :            :     }
        4661                 :          0 :     return 0;
        4662                 :            : }
        4663                 :            :
        4664                 :            :
        4665                 :            : /*[clinic input]
        4666                 :            :
        4667                 :            : _pickle.Pickler.__init__
        4668                 :            :
        4669                 :            :   file: object
        4670                 :            :   protocol: object = None
        4671                 :            :   fix_imports: bool = True
        4672                 :            :   buffer_callback: object = None
        4673                 :            :
        4674                 :            : This takes a binary file for writing a pickle data stream.
        4675                 :            :
        4676                 :            : The optional *protocol* argument tells the pickler to use the given
        4677                 :            : protocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
        4678                 :            : protocol is 4. It was introduced in Python 3.4, and is incompatible
        4679                 :            : with previous versions.
        4680                 :            :
        4681                 :            : Specifying a negative protocol version selects the highest protocol
        4682                 :            : version supported.  The higher the protocol used, the more recent the
        4683                 :            : version of Python needed to read the pickle produced.
        4684                 :            :
        4685                 :            : The *file* argument must have a write() method that accepts a single
        4686                 :            : bytes argument. It can thus be a file object opened for binary
        4687                 :            : writing, an io.BytesIO instance, or any other custom object that meets
        4688                 :            : this interface.
        4689                 :            :
        4690                 :            : If *fix_imports* is True and protocol is less than 3, pickle will try
        4691                 :            : to map the new Python 3 names to the old module names used in Python
        4692                 :            : 2, so that the pickle data stream is readable with Python 2.
        4693                 :            :
        4694                 :            : If *buffer_callback* is None (the default), buffer views are
        4695                 :            : serialized into *file* as part of the pickle stream.
        4696                 :            :
        4697                 :            : If *buffer_callback* is not None, then it can be called any number
        4698                 :            : of times with a buffer view.  If the callback returns a false value
        4699                 :            : (such as None), the given buffer is out-of-band; otherwise the
        4700                 :            : buffer is serialized in-band, i.e. inside the pickle stream.
        4701                 :            :
        4702                 :            : It is an error if *buffer_callback* is not None and *protocol*
        4703                 :            : is None or smaller than 5.
        4704                 :            :
        4705                 :            : [clinic start generated code]*/
        4706                 :            :
        4707                 :            : static int
        4708                 :          0 : _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
        4709                 :            :                               PyObject *protocol, int fix_imports,
        4710                 :            :                               PyObject *buffer_callback)
        4711                 :            : /*[clinic end generated code: output=0abedc50590d259b input=a7c969699bf5dad3]*/
        4712                 :            : {
        4713                 :            :     /* In case of multiple __init__() calls, clear previous content. */
        4714         [ #  # ]:          0 :     if (self->write != NULL)
        4715                 :          0 :         (void)Pickler_clear(self);
        4716                 :            :
        4717         [ #  # ]:          0 :     if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
        4718                 :          0 :         return -1;
        4719                 :            :
        4720         [ #  # ]:          0 :     if (_Pickler_SetOutputStream(self, file) < 0)
        4721                 :          0 :         return -1;
        4722                 :            :
        4723         [ #  # ]:          0 :     if (_Pickler_SetBufferCallback(self, buffer_callback) < 0)
        4724                 :          0 :         return -1;
        4725                 :            :
        4726                 :            :     /* memo and output_buffer may have already been created in _Pickler_New */
        4727         [ #  # ]:          0 :     if (self->memo == NULL) {
        4728                 :          0 :         self->memo = PyMemoTable_New();
        4729         [ #  # ]:          0 :         if (self->memo == NULL)
        4730                 :          0 :             return -1;
        4731                 :            :     }
        4732                 :          0 :     self->output_len = 0;
        4733         [ #  # ]:          0 :     if (self->output_buffer == NULL) {
        4734                 :          0 :         self->max_output_len = WRITE_BUF_SIZE;
        4735                 :          0 :         self->output_buffer = PyBytes_FromStringAndSize(NULL,
        4736                 :            :                                                         self->max_output_len);
        4737         [ #  # ]:          0 :         if (self->output_buffer == NULL)
        4738                 :          0 :             return -1;
        4739                 :            :     }
        4740                 :            :
        4741                 :          0 :     self->fast = 0;
        4742                 :          0 :     self->fast_nesting = 0;
        4743                 :          0 :     self->fast_memo = NULL;
        4744                 :            :
        4745         [ #  # ]:          0 :     if (init_method_ref((PyObject *)self, &_Py_ID(persistent_id),
        4746                 :            :                         &self->pers_func, &self->pers_func_self) < 0)
        4747                 :            :     {
        4748                 :          0 :         return -1;
        4749                 :            :     }
        4750         [ #  # ]:          0 :     if (self->dispatch_table != NULL) {
        4751                 :          0 :         return 0;
        4752                 :            :     }
        4753         [ #  # ]:          0 :     if (_PyObject_LookupAttr((PyObject *)self, &_Py_ID(dispatch_table),
        4754                 :            :                              &self->dispatch_table) < 0) {
        4755                 :          0 :         return -1;
        4756                 :            :     }
        4757                 :            :
        4758                 :          0 :     return 0;
        4759                 :            : }
        4760                 :            :
        4761                 :            :
        4762                 :            : /* Define a proxy object for the Pickler's internal memo object. This is to
        4763                 :            :  * avoid breaking code like:
        4764                 :            :  *  pickler.memo.clear()
        4765                 :            :  * and
        4766                 :            :  *  pickler.memo = saved_memo
        4767                 :            :  * Is this a good idea? Not really, but we don't want to break code that uses
        4768                 :            :  * it. Note that we don't implement the entire mapping API here. This is
        4769                 :            :  * intentional, as these should be treated as black-box implementation details.
        4770                 :            :  */
        4771                 :            :
        4772                 :            : /*[clinic input]
        4773                 :            : _pickle.PicklerMemoProxy.clear
        4774                 :            :
        4775                 :            : Remove all items from memo.
        4776                 :            : [clinic start generated code]*/
        4777                 :            :
        4778                 :            : static PyObject *
        4779                 :          0 : _pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self)
        4780                 :            : /*[clinic end generated code: output=5fb9370d48ae8b05 input=ccc186dacd0f1405]*/
        4781                 :            : {
        4782         [ #  # ]:          0 :     if (self->pickler->memo)
        4783                 :          0 :         PyMemoTable_Clear(self->pickler->memo);
        4784                 :          0 :     Py_RETURN_NONE;
        4785                 :            : }
        4786                 :            :
        4787                 :            : /*[clinic input]
        4788                 :            : _pickle.PicklerMemoProxy.copy
        4789                 :            :
        4790                 :            : Copy the memo to a new object.
        4791                 :            : [clinic start generated code]*/
        4792                 :            :
        4793                 :            : static PyObject *
        4794                 :          0 : _pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
        4795                 :            : /*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
        4796                 :            : {
        4797                 :            :     PyMemoTable *memo;
        4798                 :          0 :     PyObject *new_memo = PyDict_New();
        4799         [ #  # ]:          0 :     if (new_memo == NULL)
        4800                 :          0 :         return NULL;
        4801                 :            :
        4802                 :          0 :     memo = self->pickler->memo;
        4803         [ #  # ]:          0 :     for (size_t i = 0; i < memo->mt_allocated; ++i) {
        4804                 :          0 :         PyMemoEntry entry = memo->mt_table[i];
        4805         [ #  # ]:          0 :         if (entry.me_key != NULL) {
        4806                 :            :             int status;
        4807                 :            :             PyObject *key, *value;
        4808                 :            :
        4809                 :          0 :             key = PyLong_FromVoidPtr(entry.me_key);
        4810                 :          0 :             value = Py_BuildValue("nO", entry.me_value, entry.me_key);
        4811                 :            :
        4812   [ #  #  #  # ]:          0 :             if (key == NULL || value == NULL) {
        4813                 :          0 :                 Py_XDECREF(key);
        4814                 :          0 :                 Py_XDECREF(value);
        4815                 :          0 :                 goto error;
        4816                 :            :             }
        4817                 :          0 :             status = PyDict_SetItem(new_memo, key, value);
        4818                 :          0 :             Py_DECREF(key);
        4819                 :          0 :             Py_DECREF(value);
        4820         [ #  # ]:          0 :             if (status < 0)
        4821                 :          0 :                 goto error;
        4822                 :            :         }
        4823                 :            :     }
        4824                 :          0 :     return new_memo;
        4825                 :            :
        4826                 :          0 :   error:
        4827                 :          0 :     Py_XDECREF(new_memo);
        4828                 :          0 :     return NULL;
        4829                 :            : }
        4830                 :            :
        4831                 :            : /*[clinic input]
        4832                 :            : _pickle.PicklerMemoProxy.__reduce__
        4833                 :            :
        4834                 :            : Implement pickle support.
        4835                 :            : [clinic start generated code]*/
        4836                 :            :
        4837                 :            : static PyObject *
        4838                 :          0 : _pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self)
        4839                 :            : /*[clinic end generated code: output=bebba1168863ab1d input=2f7c540e24b7aae4]*/
        4840                 :            : {
        4841                 :            :     PyObject *reduce_value, *dict_args;
        4842                 :          0 :     PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self);
        4843         [ #  # ]:          0 :     if (contents == NULL)
        4844                 :          0 :         return NULL;
        4845                 :            :
        4846                 :          0 :     reduce_value = PyTuple_New(2);
        4847         [ #  # ]:          0 :     if (reduce_value == NULL) {
        4848                 :          0 :         Py_DECREF(contents);
        4849                 :          0 :         return NULL;
        4850                 :            :     }
        4851                 :          0 :     dict_args = PyTuple_New(1);
        4852         [ #  # ]:          0 :     if (dict_args == NULL) {
        4853                 :          0 :         Py_DECREF(contents);
        4854                 :          0 :         Py_DECREF(reduce_value);
        4855                 :          0 :         return NULL;
        4856                 :            :     }
        4857                 :          0 :     PyTuple_SET_ITEM(dict_args, 0, contents);
        4858                 :          0 :     PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type));
        4859                 :          0 :     PyTuple_SET_ITEM(reduce_value, 1, dict_args);
        4860                 :          0 :     return reduce_value;
        4861                 :            : }
        4862                 :            :
        4863                 :            : static PyMethodDef picklerproxy_methods[] = {
        4864                 :            :     _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF
        4865                 :            :     _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF
        4866                 :            :     _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF
        4867                 :            :     {NULL, NULL} /* sentinel */
        4868                 :            : };
        4869                 :            :
        4870                 :            : static void
        4871                 :          0 : PicklerMemoProxy_dealloc(PicklerMemoProxyObject *self)
        4872                 :            : {
        4873                 :          0 :     PyObject_GC_UnTrack(self);
        4874                 :          0 :     Py_XDECREF(self->pickler);
        4875                 :          0 :     PyObject_GC_Del((PyObject *)self);
        4876                 :          0 : }
        4877                 :            :
        4878                 :            : static int
        4879                 :          0 : PicklerMemoProxy_traverse(PicklerMemoProxyObject *self,
        4880                 :            :                           visitproc visit, void *arg)
        4881                 :            : {
        4882   [ #  #  #  # ]:          0 :     Py_VISIT(self->pickler);
        4883                 :          0 :     return 0;
        4884                 :            : }
        4885                 :            :
        4886                 :            : static int
        4887                 :          0 : PicklerMemoProxy_clear(PicklerMemoProxyObject *self)
        4888                 :            : {
        4889         [ #  # ]:          0 :     Py_CLEAR(self->pickler);
        4890                 :          0 :     return 0;
        4891                 :            : }
        4892                 :            :
        4893                 :            : static PyTypeObject PicklerMemoProxyType = {
        4894                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        4895                 :            :     "_pickle.PicklerMemoProxy",                 /*tp_name*/
        4896                 :            :     sizeof(PicklerMemoProxyObject),             /*tp_basicsize*/
        4897                 :            :     0,
        4898                 :            :     (destructor)PicklerMemoProxy_dealloc,       /* tp_dealloc */
        4899                 :            :     0,                                          /* tp_vectorcall_offset */
        4900                 :            :     0,                                          /* tp_getattr */
        4901                 :            :     0,                                          /* tp_setattr */
        4902                 :            :     0,                                          /* tp_as_async */
        4903                 :            :     0,                                          /* tp_repr */
        4904                 :            :     0,                                          /* tp_as_number */
        4905                 :            :     0,                                          /* tp_as_sequence */
        4906                 :            :     0,                                          /* tp_as_mapping */
        4907                 :            :     PyObject_HashNotImplemented,                /* tp_hash */
        4908                 :            :     0,                                          /* tp_call */
        4909                 :            :     0,                                          /* tp_str */
        4910                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
        4911                 :            :     PyObject_GenericSetAttr,                    /* tp_setattro */
        4912                 :            :     0,                                          /* tp_as_buffer */
        4913                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
        4914                 :            :     0,                                          /* tp_doc */
        4915                 :            :     (traverseproc)PicklerMemoProxy_traverse,    /* tp_traverse */
        4916                 :            :     (inquiry)PicklerMemoProxy_clear,            /* tp_clear */
        4917                 :            :     0,                                          /* tp_richcompare */
        4918                 :            :     0,                                          /* tp_weaklistoffset */
        4919                 :            :     0,                                          /* tp_iter */
        4920                 :            :     0,                                          /* tp_iternext */
        4921                 :            :     picklerproxy_methods,                       /* tp_methods */
        4922                 :            : };
        4923                 :            :
        4924                 :            : static PyObject *
        4925                 :          0 : PicklerMemoProxy_New(PicklerObject *pickler)
        4926                 :            : {
        4927                 :            :     PicklerMemoProxyObject *self;
        4928                 :            :
        4929                 :          0 :     self = PyObject_GC_New(PicklerMemoProxyObject, &PicklerMemoProxyType);
        4930         [ #  # ]:          0 :     if (self == NULL)
        4931                 :          0 :         return NULL;
        4932                 :          0 :     self->pickler = (PicklerObject*)Py_NewRef(pickler);
        4933                 :          0 :     PyObject_GC_Track(self);
        4934                 :          0 :     return (PyObject *)self;
        4935                 :            : }
        4936                 :            :
        4937                 :            : /*****************************************************************************/
        4938                 :            :
        4939                 :            : static PyObject *
        4940                 :          0 : Pickler_get_memo(PicklerObject *self, void *Py_UNUSED(ignored))
        4941                 :            : {
        4942                 :          0 :     return PicklerMemoProxy_New(self);
        4943                 :            : }
        4944                 :            :
        4945                 :            : static int
        4946                 :          0 : Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
        4947                 :            : {
        4948                 :          0 :     PyMemoTable *new_memo = NULL;
        4949                 :            :
        4950         [ #  # ]:          0 :     if (obj == NULL) {
        4951                 :          0 :         PyErr_SetString(PyExc_TypeError,
        4952                 :            :                         "attribute deletion is not supported");
        4953                 :          0 :         return -1;
        4954                 :            :     }
        4955                 :            :
        4956         [ #  # ]:          0 :     if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) {
        4957                 :          0 :         PicklerObject *pickler =
        4958                 :            :             ((PicklerMemoProxyObject *)obj)->pickler;
        4959                 :            :
        4960                 :          0 :         new_memo = PyMemoTable_Copy(pickler->memo);
        4961         [ #  # ]:          0 :         if (new_memo == NULL)
        4962                 :          0 :             return -1;
        4963                 :            :     }
        4964         [ #  # ]:          0 :     else if (PyDict_Check(obj)) {
        4965                 :          0 :         Py_ssize_t i = 0;
        4966                 :            :         PyObject *key, *value;
        4967                 :            :
        4968                 :          0 :         new_memo = PyMemoTable_New();
        4969         [ #  # ]:          0 :         if (new_memo == NULL)
        4970                 :          0 :             return -1;
        4971                 :            :
        4972         [ #  # ]:          0 :         while (PyDict_Next(obj, &i, &key, &value)) {
        4973                 :            :             Py_ssize_t memo_id;
        4974                 :            :             PyObject *memo_obj;
        4975                 :            :
        4976   [ #  #  #  # ]:          0 :             if (!PyTuple_Check(value) || PyTuple_GET_SIZE(value) != 2) {
        4977                 :          0 :                 PyErr_SetString(PyExc_TypeError,
        4978                 :            :                                 "'memo' values must be 2-item tuples");
        4979                 :          0 :                 goto error;
        4980                 :            :             }
        4981                 :          0 :             memo_id = PyLong_AsSsize_t(PyTuple_GET_ITEM(value, 0));
        4982   [ #  #  #  # ]:          0 :             if (memo_id == -1 && PyErr_Occurred())
        4983                 :          0 :                 goto error;
        4984                 :          0 :             memo_obj = PyTuple_GET_ITEM(value, 1);
        4985         [ #  # ]:          0 :             if (PyMemoTable_Set(new_memo, memo_obj, memo_id) < 0)
        4986                 :          0 :                 goto error;
        4987                 :            :         }
        4988                 :            :     }
        4989                 :            :     else {
        4990                 :          0 :         PyErr_Format(PyExc_TypeError,
        4991                 :            :                      "'memo' attribute must be a PicklerMemoProxy object "
        4992                 :          0 :                      "or dict, not %.200s", Py_TYPE(obj)->tp_name);
        4993                 :          0 :         return -1;
        4994                 :            :     }
        4995                 :            :
        4996                 :          0 :     PyMemoTable_Del(self->memo);
        4997                 :          0 :     self->memo = new_memo;
        4998                 :            :
        4999                 :          0 :     return 0;
        5000                 :            :
        5001                 :          0 :   error:
        5002         [ #  # ]:          0 :     if (new_memo)
        5003                 :          0 :         PyMemoTable_Del(new_memo);
        5004                 :          0 :     return -1;
        5005                 :            : }
        5006                 :            :
        5007                 :            : static PyObject *
        5008                 :          0 : Pickler_get_persid(PicklerObject *self, void *Py_UNUSED(ignored))
        5009                 :            : {
        5010         [ #  # ]:          0 :     if (self->pers_func == NULL) {
        5011                 :          0 :         PyErr_SetString(PyExc_AttributeError, "persistent_id");
        5012                 :          0 :         return NULL;
        5013                 :            :     }
        5014                 :          0 :     return reconstruct_method(self->pers_func, self->pers_func_self);
        5015                 :            : }
        5016                 :            :
        5017                 :            : static int
        5018                 :          0 : Pickler_set_persid(PicklerObject *self, PyObject *value, void *Py_UNUSED(ignored))
        5019                 :            : {
        5020         [ #  # ]:          0 :     if (value == NULL) {
        5021                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5022                 :            :                         "attribute deletion is not supported");
        5023                 :          0 :         return -1;
        5024                 :            :     }
        5025         [ #  # ]:          0 :     if (!PyCallable_Check(value)) {
        5026                 :          0 :         PyErr_SetString(PyExc_TypeError,
        5027                 :            :                         "persistent_id must be a callable taking one argument");
        5028                 :          0 :         return -1;
        5029                 :            :     }
        5030                 :            :
        5031                 :          0 :     self->pers_func_self = NULL;
        5032                 :          0 :     Py_XSETREF(self->pers_func, Py_NewRef(value));
        5033                 :            :
        5034                 :          0 :     return 0;
        5035                 :            : }
        5036                 :            :
        5037                 :            : static PyMemberDef Pickler_members[] = {
        5038                 :            :     {"bin", T_INT, offsetof(PicklerObject, bin)},
        5039                 :            :     {"fast", T_INT, offsetof(PicklerObject, fast)},
        5040                 :            :     {"dispatch_table", T_OBJECT_EX, offsetof(PicklerObject, dispatch_table)},
        5041                 :            :     {NULL}
        5042                 :            : };
        5043                 :            :
        5044                 :            : static PyGetSetDef Pickler_getsets[] = {
        5045                 :            :     {"memo",          (getter)Pickler_get_memo,
        5046                 :            :                       (setter)Pickler_set_memo},
        5047                 :            :     {"persistent_id", (getter)Pickler_get_persid,
        5048                 :            :                       (setter)Pickler_set_persid},
        5049                 :            :     {NULL}
        5050                 :            : };
        5051                 :            :
        5052                 :            : static PyTypeObject Pickler_Type = {
        5053                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        5054                 :            :     "_pickle.Pickler"  ,                /*tp_name*/
        5055                 :            :     sizeof(PicklerObject),              /*tp_basicsize*/
        5056                 :            :     0,                                  /*tp_itemsize*/
        5057                 :            :     (destructor)Pickler_dealloc,        /*tp_dealloc*/
        5058                 :            :     0,                                  /*tp_vectorcall_offset*/
        5059                 :            :     0,                                  /*tp_getattr*/
        5060                 :            :     0,                                  /*tp_setattr*/
        5061                 :            :     0,                                  /*tp_as_async*/
        5062                 :            :     0,                                  /*tp_repr*/
        5063                 :            :     0,                                  /*tp_as_number*/
        5064                 :            :     0,                                  /*tp_as_sequence*/
        5065                 :            :     0,                                  /*tp_as_mapping*/
        5066                 :            :     0,                                  /*tp_hash*/
        5067                 :            :     0,                                  /*tp_call*/
        5068                 :            :     0,                                  /*tp_str*/
        5069                 :            :     0,                                  /*tp_getattro*/
        5070                 :            :     0,                                  /*tp_setattro*/
        5071                 :            :     0,                                  /*tp_as_buffer*/
        5072                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
        5073                 :            :     _pickle_Pickler___init____doc__,    /*tp_doc*/
        5074                 :            :     (traverseproc)Pickler_traverse,     /*tp_traverse*/
        5075                 :            :     (inquiry)Pickler_clear,             /*tp_clear*/
        5076                 :            :     0,                                  /*tp_richcompare*/
        5077                 :            :     0,                                  /*tp_weaklistoffset*/
        5078                 :            :     0,                                  /*tp_iter*/
        5079                 :            :     0,                                  /*tp_iternext*/
        5080                 :            :     Pickler_methods,                    /*tp_methods*/
        5081                 :            :     Pickler_members,                    /*tp_members*/
        5082                 :            :     Pickler_getsets,                    /*tp_getset*/
        5083                 :            :     0,                                  /*tp_base*/
        5084                 :            :     0,                                  /*tp_dict*/
        5085                 :            :     0,                                  /*tp_descr_get*/
        5086                 :            :     0,                                  /*tp_descr_set*/
        5087                 :            :     0,                                  /*tp_dictoffset*/
        5088                 :            :     _pickle_Pickler___init__,           /*tp_init*/
        5089                 :            :     PyType_GenericAlloc,                /*tp_alloc*/
        5090                 :            :     PyType_GenericNew,                  /*tp_new*/
        5091                 :            :     PyObject_GC_Del,                    /*tp_free*/
        5092                 :            :     0,                                  /*tp_is_gc*/
        5093                 :            : };
        5094                 :            :
        5095                 :            : /* Temporary helper for calling self.find_class().
        5096                 :            :
        5097                 :            :    XXX: It would be nice to able to avoid Python function call overhead, by
        5098                 :            :    using directly the C version of find_class(), when find_class() is not
        5099                 :            :    overridden by a subclass. Although, this could become rather hackish. A
        5100                 :            :    simpler optimization would be to call the C function when self is not a
        5101                 :            :    subclass instance. */
        5102                 :            : static PyObject *
        5103                 :          0 : find_class(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
        5104                 :            : {
        5105                 :          0 :     return PyObject_CallMethodObjArgs((PyObject *)self, &_Py_ID(find_class),
        5106                 :            :                                       module_name, global_name, NULL);
        5107                 :            : }
        5108                 :            :
        5109                 :            : static Py_ssize_t
        5110                 :          0 : marker(UnpicklerObject *self)
        5111                 :            : {
        5112                 :            :     Py_ssize_t mark;
        5113                 :            :
        5114         [ #  # ]:          0 :     if (self->num_marks < 1) {
        5115                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5116                 :          0 :         PyErr_SetString(st->UnpicklingError, "could not find MARK");
        5117                 :          0 :         return -1;
        5118                 :            :     }
        5119                 :            :
        5120                 :          0 :     mark = self->marks[--self->num_marks];
        5121                 :          0 :     self->stack->mark_set = self->num_marks != 0;
        5122                 :          0 :     self->stack->fence = self->num_marks ?
        5123         [ #  # ]:          0 :             self->marks[self->num_marks - 1] : 0;
        5124                 :          0 :     return mark;
        5125                 :            : }
        5126                 :            :
        5127                 :            : static int
        5128                 :          0 : load_none(UnpicklerObject *self)
        5129                 :            : {
        5130         [ #  # ]:          0 :     PDATA_APPEND(self->stack, Py_None, -1);
        5131                 :          0 :     return 0;
        5132                 :            : }
        5133                 :            :
        5134                 :            : static int
        5135                 :          0 : load_int(UnpicklerObject *self)
        5136                 :            : {
        5137                 :            :     PyObject *value;
        5138                 :            :     char *endptr, *s;
        5139                 :            :     Py_ssize_t len;
        5140                 :            :     long x;
        5141                 :            :
        5142         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5143                 :          0 :         return -1;
        5144         [ #  # ]:          0 :     if (len < 2)
        5145                 :          0 :         return bad_readline();
        5146                 :            :
        5147                 :          0 :     errno = 0;
        5148                 :            :     /* XXX: Should the base argument of strtol() be explicitly set to 10?
        5149                 :            :        XXX(avassalotti): Should this uses PyOS_strtol()? */
        5150                 :          0 :     x = strtol(s, &endptr, 0);
        5151                 :            :
        5152   [ #  #  #  #  :          0 :     if (errno || (*endptr != '\n' && *endptr != '\0')) {
                       #  # ]
        5153                 :            :         /* Hm, maybe we've got something long.  Let's try reading
        5154                 :            :          * it as a Python int object. */
        5155                 :          0 :         errno = 0;
        5156                 :            :         /* XXX: Same thing about the base here. */
        5157                 :          0 :         value = PyLong_FromString(s, NULL, 0);
        5158         [ #  # ]:          0 :         if (value == NULL) {
        5159                 :          0 :             PyErr_SetString(PyExc_ValueError,
        5160                 :            :                             "could not convert string to int");
        5161                 :          0 :             return -1;
        5162                 :            :         }
        5163                 :            :     }
        5164                 :            :     else {
        5165   [ #  #  #  #  :          0 :         if (len == 3 && (x == 0 || x == 1)) {
                       #  # ]
        5166         [ #  # ]:          0 :             if ((value = PyBool_FromLong(x)) == NULL)
        5167                 :          0 :                 return -1;
        5168                 :            :         }
        5169                 :            :         else {
        5170         [ #  # ]:          0 :             if ((value = PyLong_FromLong(x)) == NULL)
        5171                 :          0 :                 return -1;
        5172                 :            :         }
        5173                 :            :     }
        5174                 :            :
        5175         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5176                 :          0 :     return 0;
        5177                 :            : }
        5178                 :            :
        5179                 :            : static int
        5180                 :          0 : load_bool(UnpicklerObject *self, PyObject *boolean)
        5181                 :            : {
        5182                 :            :     assert(boolean == Py_True || boolean == Py_False);
        5183         [ #  # ]:          0 :     PDATA_APPEND(self->stack, boolean, -1);
        5184                 :          0 :     return 0;
        5185                 :            : }
        5186                 :            :
        5187                 :            : /* s contains x bytes of an unsigned little-endian integer.  Return its value
        5188                 :            :  * as a C Py_ssize_t, or -1 if it's higher than PY_SSIZE_T_MAX.
        5189                 :            :  */
        5190                 :            : static Py_ssize_t
        5191                 :          0 : calc_binsize(char *bytes, int nbytes)
        5192                 :            : {
        5193                 :          0 :     unsigned char *s = (unsigned char *)bytes;
        5194                 :            :     int i;
        5195                 :          0 :     size_t x = 0;
        5196                 :            :
        5197         [ #  # ]:          0 :     if (nbytes > (int)sizeof(size_t)) {
        5198                 :            :         /* Check for integer overflow.  BINBYTES8 and BINUNICODE8 opcodes
        5199                 :            :          * have 64-bit size that can't be represented on 32-bit platform.
        5200                 :            :          */
        5201         [ #  # ]:          0 :         for (i = (int)sizeof(size_t); i < nbytes; i++) {
        5202         [ #  # ]:          0 :             if (s[i])
        5203                 :          0 :                 return -1;
        5204                 :            :         }
        5205                 :          0 :         nbytes = (int)sizeof(size_t);
        5206                 :            :     }
        5207         [ #  # ]:          0 :     for (i = 0; i < nbytes; i++) {
        5208                 :          0 :         x |= (size_t) s[i] << (8 * i);
        5209                 :            :     }
        5210                 :            :
        5211         [ #  # ]:          0 :     if (x > PY_SSIZE_T_MAX)
        5212                 :          0 :         return -1;
        5213                 :            :     else
        5214                 :          0 :         return (Py_ssize_t) x;
        5215                 :            : }
        5216                 :            :
        5217                 :            : /* s contains x bytes of a little-endian integer.  Return its value as a
        5218                 :            :  * C int.  Obscure:  when x is 1 or 2, this is an unsigned little-endian
        5219                 :            :  * int, but when x is 4 it's a signed one.  This is a historical source
        5220                 :            :  * of x-platform bugs.
        5221                 :            :  */
        5222                 :            : static long
        5223                 :          0 : calc_binint(char *bytes, int nbytes)
        5224                 :            : {
        5225                 :          0 :     unsigned char *s = (unsigned char *)bytes;
        5226                 :            :     Py_ssize_t i;
        5227                 :          0 :     long x = 0;
        5228                 :            :
        5229         [ #  # ]:          0 :     for (i = 0; i < nbytes; i++) {
        5230                 :          0 :         x |= (long)s[i] << (8 * i);
        5231                 :            :     }
        5232                 :            :
        5233                 :            :     /* Unlike BININT1 and BININT2, BININT (more accurately BININT4)
        5234                 :            :      * is signed, so on a box with longs bigger than 4 bytes we need
        5235                 :            :      * to extend a BININT's sign bit to the full width.
        5236                 :            :      */
        5237         [ #  # ]:          0 :     if (SIZEOF_LONG > 4 && nbytes == 4) {
        5238                 :          0 :         x |= -(x & (1L << 31));
        5239                 :            :     }
        5240                 :            :
        5241                 :          0 :     return x;
        5242                 :            : }
        5243                 :            :
        5244                 :            : static int
        5245                 :          0 : load_binintx(UnpicklerObject *self, char *s, int size)
        5246                 :            : {
        5247                 :            :     PyObject *value;
        5248                 :            :     long x;
        5249                 :            :
        5250                 :          0 :     x = calc_binint(s, size);
        5251                 :            :
        5252         [ #  # ]:          0 :     if ((value = PyLong_FromLong(x)) == NULL)
        5253                 :          0 :         return -1;
        5254                 :            :
        5255         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5256                 :          0 :     return 0;
        5257                 :            : }
        5258                 :            :
        5259                 :            : static int
        5260                 :          0 : load_binint(UnpicklerObject *self)
        5261                 :            : {
        5262                 :            :     char *s;
        5263                 :            :
        5264   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 4) < 0)
        5265                 :          0 :         return -1;
        5266                 :            :
        5267                 :          0 :     return load_binintx(self, s, 4);
        5268                 :            : }
        5269                 :            :
        5270                 :            : static int
        5271                 :          0 : load_binint1(UnpicklerObject *self)
        5272                 :            : {
        5273                 :            :     char *s;
        5274                 :            :
        5275   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 1) < 0)
        5276                 :          0 :         return -1;
        5277                 :            :
        5278                 :          0 :     return load_binintx(self, s, 1);
        5279                 :            : }
        5280                 :            :
        5281                 :            : static int
        5282                 :          0 : load_binint2(UnpicklerObject *self)
        5283                 :            : {
        5284                 :            :     char *s;
        5285                 :            :
        5286   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 2) < 0)
        5287                 :          0 :         return -1;
        5288                 :            :
        5289                 :          0 :     return load_binintx(self, s, 2);
        5290                 :            : }
        5291                 :            :
        5292                 :            : static int
        5293                 :          0 : load_long(UnpicklerObject *self)
        5294                 :            : {
        5295                 :            :     PyObject *value;
        5296                 :          0 :     char *s = NULL;
        5297                 :            :     Py_ssize_t len;
        5298                 :            :
        5299         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5300                 :          0 :         return -1;
        5301         [ #  # ]:          0 :     if (len < 2)
        5302                 :          0 :         return bad_readline();
        5303                 :            :
        5304                 :            :     /* s[len-2] will usually be 'L' (and s[len-1] is '\n'); we need to remove
        5305                 :            :        the 'L' before calling PyLong_FromString.  In order to maintain
        5306                 :            :        compatibility with Python 3.0.0, we don't actually *require*
        5307                 :            :        the 'L' to be present. */
        5308         [ #  # ]:          0 :     if (s[len-2] == 'L')
        5309                 :          0 :         s[len-2] = '\0';
        5310                 :            :     /* XXX: Should the base argument explicitly set to 10? */
        5311                 :          0 :     value = PyLong_FromString(s, NULL, 0);
        5312         [ #  # ]:          0 :     if (value == NULL)
        5313                 :          0 :         return -1;
        5314                 :            :
        5315         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5316                 :          0 :     return 0;
        5317                 :            : }
        5318                 :            :
        5319                 :            : /* 'size' bytes contain the # of bytes of little-endian 256's-complement
        5320                 :            :  * data following.
        5321                 :            :  */
        5322                 :            : static int
        5323                 :          0 : load_counted_long(UnpicklerObject *self, int size)
        5324                 :            : {
        5325                 :            :     PyObject *value;
        5326                 :            :     char *nbytes;
        5327                 :            :     char *pdata;
        5328                 :            :
        5329                 :            :     assert(size == 1 || size == 4);
        5330   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &nbytes, size) < 0)
        5331                 :          0 :         return -1;
        5332                 :            :
        5333                 :          0 :     size = calc_binint(nbytes, size);
        5334         [ #  # ]:          0 :     if (size < 0) {
        5335                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5336                 :            :         /* Corrupt or hostile pickle -- we never write one like this */
        5337                 :          0 :         PyErr_SetString(st->UnpicklingError,
        5338                 :            :                         "LONG pickle has negative byte count");
        5339                 :          0 :         return -1;
        5340                 :            :     }
        5341                 :            :
        5342         [ #  # ]:          0 :     if (size == 0)
        5343                 :          0 :         value = PyLong_FromLong(0L);
        5344                 :            :     else {
        5345                 :            :         /* Read the raw little-endian bytes and convert. */
        5346   [ #  #  #  # ]:          0 :         if (_Unpickler_Read(self, &pdata, size) < 0)
        5347                 :          0 :             return -1;
        5348                 :          0 :         value = _PyLong_FromByteArray((unsigned char *)pdata, (size_t)size,
        5349                 :            :                                       1 /* little endian */ , 1 /* signed */ );
        5350                 :            :     }
        5351         [ #  # ]:          0 :     if (value == NULL)
        5352                 :          0 :         return -1;
        5353         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5354                 :          0 :     return 0;
        5355                 :            : }
        5356                 :            :
        5357                 :            : static int
        5358                 :          0 : load_float(UnpicklerObject *self)
        5359                 :            : {
        5360                 :            :     PyObject *value;
        5361                 :            :     char *endptr, *s;
        5362                 :            :     Py_ssize_t len;
        5363                 :            :     double d;
        5364                 :            :
        5365         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5366                 :          0 :         return -1;
        5367         [ #  # ]:          0 :     if (len < 2)
        5368                 :          0 :         return bad_readline();
        5369                 :            :
        5370                 :          0 :     errno = 0;
        5371                 :          0 :     d = PyOS_string_to_double(s, &endptr, PyExc_OverflowError);
        5372   [ #  #  #  # ]:          0 :     if (d == -1.0 && PyErr_Occurred())
        5373                 :          0 :         return -1;
        5374   [ #  #  #  # ]:          0 :     if ((endptr[0] != '\n') && (endptr[0] != '\0')) {
        5375                 :          0 :         PyErr_SetString(PyExc_ValueError, "could not convert string to float");
        5376                 :          0 :         return -1;
        5377                 :            :     }
        5378                 :          0 :     value = PyFloat_FromDouble(d);
        5379         [ #  # ]:          0 :     if (value == NULL)
        5380                 :          0 :         return -1;
        5381                 :            :
        5382         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5383                 :          0 :     return 0;
        5384                 :            : }
        5385                 :            :
        5386                 :            : static int
        5387                 :          0 : load_binfloat(UnpicklerObject *self)
        5388                 :            : {
        5389                 :            :     PyObject *value;
        5390                 :            :     double x;
        5391                 :            :     char *s;
        5392                 :            :
        5393   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 8) < 0)
        5394                 :          0 :         return -1;
        5395                 :            :
        5396                 :          0 :     x = PyFloat_Unpack8(s, 0);
        5397   [ #  #  #  # ]:          0 :     if (x == -1.0 && PyErr_Occurred())
        5398                 :          0 :         return -1;
        5399                 :            :
        5400         [ #  # ]:          0 :     if ((value = PyFloat_FromDouble(x)) == NULL)
        5401                 :          0 :         return -1;
        5402                 :            :
        5403         [ #  # ]:          0 :     PDATA_PUSH(self->stack, value, -1);
        5404                 :          0 :     return 0;
        5405                 :            : }
        5406                 :            :
        5407                 :            : static int
        5408                 :          0 : load_string(UnpicklerObject *self)
        5409                 :            : {
        5410                 :            :     PyObject *bytes;
        5411                 :            :     PyObject *obj;
        5412                 :            :     Py_ssize_t len;
        5413                 :            :     char *s, *p;
        5414                 :            :
        5415         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5416                 :          0 :         return -1;
        5417                 :            :     /* Strip the newline */
        5418                 :          0 :     len--;
        5419                 :            :     /* Strip outermost quotes */
        5420   [ #  #  #  #  :          0 :     if (len >= 2 && s[0] == s[len - 1] && (s[0] == '\'' || s[0] == '"')) {
                 #  #  #  # ]
        5421                 :          0 :         p = s + 1;
        5422                 :          0 :         len -= 2;
        5423                 :            :     }
        5424                 :            :     else {
        5425                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5426                 :          0 :         PyErr_SetString(st->UnpicklingError,
        5427                 :            :                         "the STRING opcode argument must be quoted");
        5428                 :          0 :         return -1;
        5429                 :            :     }
        5430                 :            :     assert(len >= 0);
        5431                 :            :
        5432                 :            :     /* Use the PyBytes API to decode the string, since that is what is used
        5433                 :            :        to encode, and then coerce the result to Unicode. */
        5434                 :          0 :     bytes = PyBytes_DecodeEscape(p, len, NULL, 0, NULL);
        5435         [ #  # ]:          0 :     if (bytes == NULL)
        5436                 :          0 :         return -1;
        5437                 :            :
        5438                 :            :     /* Leave the Python 2.x strings as bytes if the *encoding* given to the
        5439                 :            :        Unpickler was 'bytes'. Otherwise, convert them to unicode. */
        5440         [ #  # ]:          0 :     if (strcmp(self->encoding, "bytes") == 0) {
        5441                 :          0 :         obj = bytes;
        5442                 :            :     }
        5443                 :            :     else {
        5444                 :          0 :         obj = PyUnicode_FromEncodedObject(bytes, self->encoding, self->errors);
        5445                 :          0 :         Py_DECREF(bytes);
        5446         [ #  # ]:          0 :         if (obj == NULL) {
        5447                 :          0 :             return -1;
        5448                 :            :         }
        5449                 :            :     }
        5450                 :            :
        5451         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        5452                 :          0 :     return 0;
        5453                 :            : }
        5454                 :            :
        5455                 :            : static int
        5456                 :          0 : load_counted_binstring(UnpicklerObject *self, int nbytes)
        5457                 :            : {
        5458                 :            :     PyObject *obj;
        5459                 :            :     Py_ssize_t size;
        5460                 :            :     char *s;
        5461                 :            :
        5462   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, nbytes) < 0)
        5463                 :          0 :         return -1;
        5464                 :            :
        5465                 :          0 :     size = calc_binsize(s, nbytes);
        5466         [ #  # ]:          0 :     if (size < 0) {
        5467                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5468                 :          0 :         PyErr_Format(st->UnpicklingError,
        5469                 :            :                      "BINSTRING exceeds system's maximum size of %zd bytes",
        5470                 :            :                      PY_SSIZE_T_MAX);
        5471                 :          0 :         return -1;
        5472                 :            :     }
        5473                 :            :
        5474   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, size) < 0)
        5475                 :          0 :         return -1;
        5476                 :            :
        5477                 :            :     /* Convert Python 2.x strings to bytes if the *encoding* given to the
        5478                 :            :        Unpickler was 'bytes'. Otherwise, convert them to unicode. */
        5479         [ #  # ]:          0 :     if (strcmp(self->encoding, "bytes") == 0) {
        5480                 :          0 :         obj = PyBytes_FromStringAndSize(s, size);
        5481                 :            :     }
        5482                 :            :     else {
        5483                 :          0 :         obj = PyUnicode_Decode(s, size, self->encoding, self->errors);
        5484                 :            :     }
        5485         [ #  # ]:          0 :     if (obj == NULL) {
        5486                 :          0 :         return -1;
        5487                 :            :     }
        5488                 :            :
        5489         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        5490                 :          0 :     return 0;
        5491                 :            : }
        5492                 :            :
        5493                 :            : static int
        5494                 :          0 : load_counted_binbytes(UnpicklerObject *self, int nbytes)
        5495                 :            : {
        5496                 :            :     PyObject *bytes;
        5497                 :            :     Py_ssize_t size;
        5498                 :            :     char *s;
        5499                 :            :
        5500   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, nbytes) < 0)
        5501                 :          0 :         return -1;
        5502                 :            :
        5503                 :          0 :     size = calc_binsize(s, nbytes);
        5504         [ #  # ]:          0 :     if (size < 0) {
        5505                 :          0 :         PyErr_Format(PyExc_OverflowError,
        5506                 :            :                      "BINBYTES exceeds system's maximum size of %zd bytes",
        5507                 :            :                      PY_SSIZE_T_MAX);
        5508                 :          0 :         return -1;
        5509                 :            :     }
        5510                 :            :
        5511                 :          0 :     bytes = PyBytes_FromStringAndSize(NULL, size);
        5512         [ #  # ]:          0 :     if (bytes == NULL)
        5513                 :          0 :         return -1;
        5514         [ #  # ]:          0 :     if (_Unpickler_ReadInto(self, PyBytes_AS_STRING(bytes), size) < 0) {
        5515                 :          0 :         Py_DECREF(bytes);
        5516                 :          0 :         return -1;
        5517                 :            :     }
        5518                 :            :
        5519         [ #  # ]:          0 :     PDATA_PUSH(self->stack, bytes, -1);
        5520                 :          0 :     return 0;
        5521                 :            : }
        5522                 :            :
        5523                 :            : static int
        5524                 :          0 : load_counted_bytearray(UnpicklerObject *self)
        5525                 :            : {
        5526                 :            :     PyObject *bytearray;
        5527                 :            :     Py_ssize_t size;
        5528                 :            :     char *s;
        5529                 :            :
        5530   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 8) < 0) {
        5531                 :          0 :         return -1;
        5532                 :            :     }
        5533                 :            :
        5534                 :          0 :     size = calc_binsize(s, 8);
        5535         [ #  # ]:          0 :     if (size < 0) {
        5536                 :          0 :         PyErr_Format(PyExc_OverflowError,
        5537                 :            :                      "BYTEARRAY8 exceeds system's maximum size of %zd bytes",
        5538                 :            :                      PY_SSIZE_T_MAX);
        5539                 :          0 :         return -1;
        5540                 :            :     }
        5541                 :            :
        5542                 :          0 :     bytearray = PyByteArray_FromStringAndSize(NULL, size);
        5543         [ #  # ]:          0 :     if (bytearray == NULL) {
        5544                 :          0 :         return -1;
        5545                 :            :     }
        5546         [ #  # ]:          0 :     if (_Unpickler_ReadInto(self, PyByteArray_AS_STRING(bytearray), size) < 0) {
        5547                 :          0 :         Py_DECREF(bytearray);
        5548                 :          0 :         return -1;
        5549                 :            :     }
        5550                 :            :
        5551         [ #  # ]:          0 :     PDATA_PUSH(self->stack, bytearray, -1);
        5552                 :          0 :     return 0;
        5553                 :            : }
        5554                 :            :
        5555                 :            : static int
        5556                 :          0 : load_next_buffer(UnpicklerObject *self)
        5557                 :            : {
        5558         [ #  # ]:          0 :     if (self->buffers == NULL) {
        5559                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5560                 :          0 :         PyErr_SetString(st->UnpicklingError,
        5561                 :            :                         "pickle stream refers to out-of-band data "
        5562                 :            :                         "but no *buffers* argument was given");
        5563                 :          0 :         return -1;
        5564                 :            :     }
        5565                 :          0 :     PyObject *buf = PyIter_Next(self->buffers);
        5566         [ #  # ]:          0 :     if (buf == NULL) {
        5567         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        5568                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        5569                 :          0 :             PyErr_SetString(st->UnpicklingError,
        5570                 :            :                             "not enough out-of-band buffers");
        5571                 :            :         }
        5572                 :          0 :         return -1;
        5573                 :            :     }
        5574                 :            :
        5575         [ #  # ]:          0 :     PDATA_PUSH(self->stack, buf, -1);
        5576                 :          0 :     return 0;
        5577                 :            : }
        5578                 :            :
        5579                 :            : static int
        5580                 :          0 : load_readonly_buffer(UnpicklerObject *self)
        5581                 :            : {
        5582                 :          0 :     Py_ssize_t len = Py_SIZE(self->stack);
        5583         [ #  # ]:          0 :     if (len <= self->stack->fence) {
        5584                 :          0 :         return Pdata_stack_underflow(self->stack);
        5585                 :            :     }
        5586                 :            :
        5587                 :          0 :     PyObject *obj = self->stack->data[len - 1];
        5588                 :          0 :     PyObject *view = PyMemoryView_FromObject(obj);
        5589         [ #  # ]:          0 :     if (view == NULL) {
        5590                 :          0 :         return -1;
        5591                 :            :     }
        5592         [ #  # ]:          0 :     if (!PyMemoryView_GET_BUFFER(view)->readonly) {
        5593                 :            :         /* Original object is writable */
        5594                 :          0 :         PyMemoryView_GET_BUFFER(view)->readonly = 1;
        5595                 :          0 :         self->stack->data[len - 1] = view;
        5596                 :          0 :         Py_DECREF(obj);
        5597                 :            :     }
        5598                 :            :     else {
        5599                 :            :         /* Original object is read-only, no need to replace it */
        5600                 :          0 :         Py_DECREF(view);
        5601                 :            :     }
        5602                 :          0 :     return 0;
        5603                 :            : }
        5604                 :            :
        5605                 :            : static int
        5606                 :          0 : load_unicode(UnpicklerObject *self)
        5607                 :            : {
        5608                 :            :     PyObject *str;
        5609                 :            :     Py_ssize_t len;
        5610                 :          0 :     char *s = NULL;
        5611                 :            :
        5612         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5613                 :          0 :         return -1;
        5614         [ #  # ]:          0 :     if (len < 1)
        5615                 :          0 :         return bad_readline();
        5616                 :            :
        5617                 :          0 :     str = PyUnicode_DecodeRawUnicodeEscape(s, len - 1, NULL);
        5618         [ #  # ]:          0 :     if (str == NULL)
        5619                 :          0 :         return -1;
        5620                 :            :
        5621         [ #  # ]:          0 :     PDATA_PUSH(self->stack, str, -1);
        5622                 :          0 :     return 0;
        5623                 :            : }
        5624                 :            :
        5625                 :            : static int
        5626                 :          0 : load_counted_binunicode(UnpicklerObject *self, int nbytes)
        5627                 :            : {
        5628                 :            :     PyObject *str;
        5629                 :            :     Py_ssize_t size;
        5630                 :            :     char *s;
        5631                 :            :
        5632   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, nbytes) < 0)
        5633                 :          0 :         return -1;
        5634                 :            :
        5635                 :          0 :     size = calc_binsize(s, nbytes);
        5636         [ #  # ]:          0 :     if (size < 0) {
        5637                 :          0 :         PyErr_Format(PyExc_OverflowError,
        5638                 :            :                      "BINUNICODE exceeds system's maximum size of %zd bytes",
        5639                 :            :                      PY_SSIZE_T_MAX);
        5640                 :          0 :         return -1;
        5641                 :            :     }
        5642                 :            :
        5643   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, size) < 0)
        5644                 :          0 :         return -1;
        5645                 :            :
        5646                 :          0 :     str = PyUnicode_DecodeUTF8(s, size, "surrogatepass");
        5647         [ #  # ]:          0 :     if (str == NULL)
        5648                 :          0 :         return -1;
        5649                 :            :
        5650         [ #  # ]:          0 :     PDATA_PUSH(self->stack, str, -1);
        5651                 :          0 :     return 0;
        5652                 :            : }
        5653                 :            :
        5654                 :            : static int
        5655                 :          0 : load_counted_tuple(UnpicklerObject *self, Py_ssize_t len)
        5656                 :            : {
        5657                 :            :     PyObject *tuple;
        5658                 :            :
        5659         [ #  # ]:          0 :     if (Py_SIZE(self->stack) < len)
        5660                 :          0 :         return Pdata_stack_underflow(self->stack);
        5661                 :            :
        5662                 :          0 :     tuple = Pdata_poptuple(self->stack, Py_SIZE(self->stack) - len);
        5663         [ #  # ]:          0 :     if (tuple == NULL)
        5664                 :          0 :         return -1;
        5665         [ #  # ]:          0 :     PDATA_PUSH(self->stack, tuple, -1);
        5666                 :          0 :     return 0;
        5667                 :            : }
        5668                 :            :
        5669                 :            : static int
        5670                 :          0 : load_tuple(UnpicklerObject *self)
        5671                 :            : {
        5672                 :            :     Py_ssize_t i;
        5673                 :            :
        5674         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5675                 :          0 :         return -1;
        5676                 :            :
        5677                 :          0 :     return load_counted_tuple(self, Py_SIZE(self->stack) - i);
        5678                 :            : }
        5679                 :            :
        5680                 :            : static int
        5681                 :          0 : load_empty_list(UnpicklerObject *self)
        5682                 :            : {
        5683                 :            :     PyObject *list;
        5684                 :            :
        5685         [ #  # ]:          0 :     if ((list = PyList_New(0)) == NULL)
        5686                 :          0 :         return -1;
        5687         [ #  # ]:          0 :     PDATA_PUSH(self->stack, list, -1);
        5688                 :          0 :     return 0;
        5689                 :            : }
        5690                 :            :
        5691                 :            : static int
        5692                 :          0 : load_empty_dict(UnpicklerObject *self)
        5693                 :            : {
        5694                 :            :     PyObject *dict;
        5695                 :            :
        5696         [ #  # ]:          0 :     if ((dict = PyDict_New()) == NULL)
        5697                 :          0 :         return -1;
        5698         [ #  # ]:          0 :     PDATA_PUSH(self->stack, dict, -1);
        5699                 :          0 :     return 0;
        5700                 :            : }
        5701                 :            :
        5702                 :            : static int
        5703                 :          0 : load_empty_set(UnpicklerObject *self)
        5704                 :            : {
        5705                 :            :     PyObject *set;
        5706                 :            :
        5707         [ #  # ]:          0 :     if ((set = PySet_New(NULL)) == NULL)
        5708                 :          0 :         return -1;
        5709         [ #  # ]:          0 :     PDATA_PUSH(self->stack, set, -1);
        5710                 :          0 :     return 0;
        5711                 :            : }
        5712                 :            :
        5713                 :            : static int
        5714                 :          0 : load_list(UnpicklerObject *self)
        5715                 :            : {
        5716                 :            :     PyObject *list;
        5717                 :            :     Py_ssize_t i;
        5718                 :            :
        5719         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5720                 :          0 :         return -1;
        5721                 :            :
        5722                 :          0 :     list = Pdata_poplist(self->stack, i);
        5723         [ #  # ]:          0 :     if (list == NULL)
        5724                 :          0 :         return -1;
        5725         [ #  # ]:          0 :     PDATA_PUSH(self->stack, list, -1);
        5726                 :          0 :     return 0;
        5727                 :            : }
        5728                 :            :
        5729                 :            : static int
        5730                 :          0 : load_dict(UnpicklerObject *self)
        5731                 :            : {
        5732                 :            :     PyObject *dict, *key, *value;
        5733                 :            :     Py_ssize_t i, j, k;
        5734                 :            :
        5735         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5736                 :          0 :         return -1;
        5737                 :          0 :     j = Py_SIZE(self->stack);
        5738                 :            :
        5739         [ #  # ]:          0 :     if ((dict = PyDict_New()) == NULL)
        5740                 :          0 :         return -1;
        5741                 :            :
        5742         [ #  # ]:          0 :     if ((j - i) % 2 != 0) {
        5743                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        5744                 :          0 :         PyErr_SetString(st->UnpicklingError, "odd number of items for DICT");
        5745                 :          0 :         Py_DECREF(dict);
        5746                 :          0 :         return -1;
        5747                 :            :     }
        5748                 :            :
        5749         [ #  # ]:          0 :     for (k = i + 1; k < j; k += 2) {
        5750                 :          0 :         key = self->stack->data[k - 1];
        5751                 :          0 :         value = self->stack->data[k];
        5752         [ #  # ]:          0 :         if (PyDict_SetItem(dict, key, value) < 0) {
        5753                 :          0 :             Py_DECREF(dict);
        5754                 :          0 :             return -1;
        5755                 :            :         }
        5756                 :            :     }
        5757                 :          0 :     Pdata_clear(self->stack, i);
        5758         [ #  # ]:          0 :     PDATA_PUSH(self->stack, dict, -1);
        5759                 :          0 :     return 0;
        5760                 :            : }
        5761                 :            :
        5762                 :            : static int
        5763                 :          0 : load_frozenset(UnpicklerObject *self)
        5764                 :            : {
        5765                 :            :     PyObject *items;
        5766                 :            :     PyObject *frozenset;
        5767                 :            :     Py_ssize_t i;
        5768                 :            :
        5769         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5770                 :          0 :         return -1;
        5771                 :            :
        5772                 :          0 :     items = Pdata_poptuple(self->stack, i);
        5773         [ #  # ]:          0 :     if (items == NULL)
        5774                 :          0 :         return -1;
        5775                 :            :
        5776                 :          0 :     frozenset = PyFrozenSet_New(items);
        5777                 :          0 :     Py_DECREF(items);
        5778         [ #  # ]:          0 :     if (frozenset == NULL)
        5779                 :          0 :         return -1;
        5780                 :            :
        5781         [ #  # ]:          0 :     PDATA_PUSH(self->stack, frozenset, -1);
        5782                 :          0 :     return 0;
        5783                 :            : }
        5784                 :            :
        5785                 :            : static PyObject *
        5786                 :          0 : instantiate(PyObject *cls, PyObject *args)
        5787                 :            : {
        5788                 :            :     /* Caller must assure args are a tuple.  Normally, args come from
        5789                 :            :        Pdata_poptuple which packs objects from the top of the stack
        5790                 :            :        into a newly created tuple. */
        5791                 :            :     assert(PyTuple_Check(args));
        5792   [ #  #  #  # ]:          0 :     if (!PyTuple_GET_SIZE(args) && PyType_Check(cls)) {
        5793                 :            :         PyObject *func;
        5794         [ #  # ]:          0 :         if (_PyObject_LookupAttr(cls, &_Py_ID(__getinitargs__), &func) < 0) {
        5795                 :          0 :             return NULL;
        5796                 :            :         }
        5797         [ #  # ]:          0 :         if (func == NULL) {
        5798                 :          0 :             return PyObject_CallMethodOneArg(cls, &_Py_ID(__new__), cls);
        5799                 :            :         }
        5800                 :          0 :         Py_DECREF(func);
        5801                 :            :     }
        5802                 :          0 :     return PyObject_CallObject(cls, args);
        5803                 :            : }
        5804                 :            :
        5805                 :            : static int
        5806                 :          0 : load_obj(UnpicklerObject *self)
        5807                 :            : {
        5808                 :          0 :     PyObject *cls, *args, *obj = NULL;
        5809                 :            :     Py_ssize_t i;
        5810                 :            :
        5811         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5812                 :          0 :         return -1;
        5813                 :            :
        5814         [ #  # ]:          0 :     if (Py_SIZE(self->stack) - i < 1)
        5815                 :          0 :         return Pdata_stack_underflow(self->stack);
        5816                 :            :
        5817                 :          0 :     args = Pdata_poptuple(self->stack, i + 1);
        5818         [ #  # ]:          0 :     if (args == NULL)
        5819                 :          0 :         return -1;
        5820                 :            :
        5821                 :          0 :     PDATA_POP(self->stack, cls);
        5822         [ #  # ]:          0 :     if (cls) {
        5823                 :          0 :         obj = instantiate(cls, args);
        5824                 :          0 :         Py_DECREF(cls);
        5825                 :            :     }
        5826                 :          0 :     Py_DECREF(args);
        5827         [ #  # ]:          0 :     if (obj == NULL)
        5828                 :          0 :         return -1;
        5829                 :            :
        5830         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        5831                 :          0 :     return 0;
        5832                 :            : }
        5833                 :            :
        5834                 :            : static int
        5835                 :          0 : load_inst(UnpicklerObject *self)
        5836                 :            : {
        5837                 :          0 :     PyObject *cls = NULL;
        5838                 :          0 :     PyObject *args = NULL;
        5839                 :          0 :     PyObject *obj = NULL;
        5840                 :            :     PyObject *module_name;
        5841                 :            :     PyObject *class_name;
        5842                 :            :     Py_ssize_t len;
        5843                 :            :     Py_ssize_t i;
        5844                 :            :     char *s;
        5845                 :            :
        5846         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        5847                 :          0 :         return -1;
        5848         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5849                 :          0 :         return -1;
        5850         [ #  # ]:          0 :     if (len < 2)
        5851                 :          0 :         return bad_readline();
        5852                 :            :
        5853                 :            :     /* Here it is safe to use PyUnicode_DecodeASCII(), even though non-ASCII
        5854                 :            :        identifiers are permitted in Python 3.0, since the INST opcode is only
        5855                 :            :        supported by older protocols on Python 2.x. */
        5856                 :          0 :     module_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
        5857         [ #  # ]:          0 :     if (module_name == NULL)
        5858                 :          0 :         return -1;
        5859                 :            :
        5860         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) >= 0) {
        5861         [ #  # ]:          0 :         if (len < 2) {
        5862                 :          0 :             Py_DECREF(module_name);
        5863                 :          0 :             return bad_readline();
        5864                 :            :         }
        5865                 :          0 :         class_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
        5866         [ #  # ]:          0 :         if (class_name != NULL) {
        5867                 :          0 :             cls = find_class(self, module_name, class_name);
        5868                 :          0 :             Py_DECREF(class_name);
        5869                 :            :         }
        5870                 :            :     }
        5871                 :          0 :     Py_DECREF(module_name);
        5872                 :            :
        5873         [ #  # ]:          0 :     if (cls == NULL)
        5874                 :          0 :         return -1;
        5875                 :            :
        5876         [ #  # ]:          0 :     if ((args = Pdata_poptuple(self->stack, i)) != NULL) {
        5877                 :          0 :         obj = instantiate(cls, args);
        5878                 :          0 :         Py_DECREF(args);
        5879                 :            :     }
        5880                 :          0 :     Py_DECREF(cls);
        5881                 :            :
        5882         [ #  # ]:          0 :     if (obj == NULL)
        5883                 :          0 :         return -1;
        5884                 :            :
        5885         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        5886                 :          0 :     return 0;
        5887                 :            : }
        5888                 :            :
        5889                 :            : static void
        5890                 :          0 : newobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg)
        5891                 :            : {
        5892                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        5893         [ #  # ]:          0 :     PyErr_Format(st->UnpicklingError, msg,
        5894                 :            :                  use_kwargs ? "NEWOBJ_EX" : "NEWOBJ",
        5895                 :          0 :                  Py_TYPE(arg)->tp_name);
        5896                 :          0 : }
        5897                 :            :
        5898                 :            : static int
        5899                 :          0 : load_newobj(UnpicklerObject *self, int use_kwargs)
        5900                 :            : {
        5901                 :          0 :     PyObject *cls, *args, *kwargs = NULL;
        5902                 :            :     PyObject *obj;
        5903                 :            :
        5904                 :            :     /* Stack is ... cls args [kwargs], and we want to call
        5905                 :            :      * cls.__new__(cls, *args, **kwargs).
        5906                 :            :      */
        5907         [ #  # ]:          0 :     if (use_kwargs) {
        5908                 :          0 :         PDATA_POP(self->stack, kwargs);
        5909         [ #  # ]:          0 :         if (kwargs == NULL) {
        5910                 :          0 :             return -1;
        5911                 :            :         }
        5912                 :            :     }
        5913                 :          0 :     PDATA_POP(self->stack, args);
        5914         [ #  # ]:          0 :     if (args == NULL) {
        5915                 :          0 :         Py_XDECREF(kwargs);
        5916                 :          0 :         return -1;
        5917                 :            :     }
        5918                 :          0 :     PDATA_POP(self->stack, cls);
        5919         [ #  # ]:          0 :     if (cls == NULL) {
        5920                 :          0 :         Py_XDECREF(kwargs);
        5921                 :          0 :         Py_DECREF(args);
        5922                 :          0 :         return -1;
        5923                 :            :     }
        5924                 :            :
        5925         [ #  # ]:          0 :     if (!PyType_Check(cls)) {
        5926                 :          0 :         newobj_unpickling_error("%s class argument must be a type, not %.200s",
        5927                 :            :                                 use_kwargs, cls);
        5928                 :          0 :         goto error;
        5929                 :            :     }
        5930         [ #  # ]:          0 :     if (((PyTypeObject *)cls)->tp_new == NULL) {
        5931                 :          0 :         newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__",
        5932                 :            :                                 use_kwargs, cls);
        5933                 :          0 :         goto error;
        5934                 :            :     }
        5935         [ #  # ]:          0 :     if (!PyTuple_Check(args)) {
        5936                 :          0 :         newobj_unpickling_error("%s args argument must be a tuple, not %.200s",
        5937                 :            :                                 use_kwargs, args);
        5938                 :          0 :         goto error;
        5939                 :            :     }
        5940   [ #  #  #  # ]:          0 :     if (use_kwargs && !PyDict_Check(kwargs)) {
        5941                 :          0 :         newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s",
        5942                 :            :                                 use_kwargs, kwargs);
        5943                 :          0 :         goto error;
        5944                 :            :     }
        5945                 :            :
        5946                 :          0 :     obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
        5947         [ #  # ]:          0 :     if (obj == NULL) {
        5948                 :          0 :         goto error;
        5949                 :            :     }
        5950                 :          0 :     Py_XDECREF(kwargs);
        5951                 :          0 :     Py_DECREF(args);
        5952                 :          0 :     Py_DECREF(cls);
        5953         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        5954                 :          0 :     return 0;
        5955                 :            :
        5956                 :          0 : error:
        5957                 :          0 :     Py_XDECREF(kwargs);
        5958                 :          0 :     Py_DECREF(args);
        5959                 :          0 :     Py_DECREF(cls);
        5960                 :          0 :     return -1;
        5961                 :            : }
        5962                 :            :
        5963                 :            : static int
        5964                 :          0 : load_global(UnpicklerObject *self)
        5965                 :            : {
        5966                 :          0 :     PyObject *global = NULL;
        5967                 :            :     PyObject *module_name;
        5968                 :            :     PyObject *global_name;
        5969                 :            :     Py_ssize_t len;
        5970                 :            :     char *s;
        5971                 :            :
        5972         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        5973                 :          0 :         return -1;
        5974         [ #  # ]:          0 :     if (len < 2)
        5975                 :          0 :         return bad_readline();
        5976                 :          0 :     module_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
        5977         [ #  # ]:          0 :     if (!module_name)
        5978                 :          0 :         return -1;
        5979                 :            :
        5980         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) >= 0) {
        5981         [ #  # ]:          0 :         if (len < 2) {
        5982                 :          0 :             Py_DECREF(module_name);
        5983                 :          0 :             return bad_readline();
        5984                 :            :         }
        5985                 :          0 :         global_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
        5986         [ #  # ]:          0 :         if (global_name) {
        5987                 :          0 :             global = find_class(self, module_name, global_name);
        5988                 :          0 :             Py_DECREF(global_name);
        5989                 :            :         }
        5990                 :            :     }
        5991                 :          0 :     Py_DECREF(module_name);
        5992                 :            :
        5993         [ #  # ]:          0 :     if (global == NULL)
        5994                 :          0 :         return -1;
        5995         [ #  # ]:          0 :     PDATA_PUSH(self->stack, global, -1);
        5996                 :          0 :     return 0;
        5997                 :            : }
        5998                 :            :
        5999                 :            : static int
        6000                 :          0 : load_stack_global(UnpicklerObject *self)
        6001                 :            : {
        6002                 :            :     PyObject *global;
        6003                 :            :     PyObject *module_name;
        6004                 :            :     PyObject *global_name;
        6005                 :            :
        6006                 :          0 :     PDATA_POP(self->stack, global_name);
        6007                 :          0 :     PDATA_POP(self->stack, module_name);
        6008   [ #  #  #  #  :          0 :     if (module_name == NULL || !PyUnicode_CheckExact(module_name) ||
                       #  # ]
        6009         [ #  # ]:          0 :         global_name == NULL || !PyUnicode_CheckExact(global_name)) {
        6010                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        6011                 :          0 :         PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str");
        6012                 :          0 :         Py_XDECREF(global_name);
        6013                 :          0 :         Py_XDECREF(module_name);
        6014                 :          0 :         return -1;
        6015                 :            :     }
        6016                 :          0 :     global = find_class(self, module_name, global_name);
        6017                 :          0 :     Py_DECREF(global_name);
        6018                 :          0 :     Py_DECREF(module_name);
        6019         [ #  # ]:          0 :     if (global == NULL)
        6020                 :          0 :         return -1;
        6021         [ #  # ]:          0 :     PDATA_PUSH(self->stack, global, -1);
        6022                 :          0 :     return 0;
        6023                 :            : }
        6024                 :            :
        6025                 :            : static int
        6026                 :          0 : load_persid(UnpicklerObject *self)
        6027                 :            : {
        6028                 :            :     PyObject *pid, *obj;
        6029                 :            :     Py_ssize_t len;
        6030                 :            :     char *s;
        6031                 :            :
        6032         [ #  # ]:          0 :     if (self->pers_func) {
        6033         [ #  # ]:          0 :         if ((len = _Unpickler_Readline(self, &s)) < 0)
        6034                 :          0 :             return -1;
        6035         [ #  # ]:          0 :         if (len < 1)
        6036                 :          0 :             return bad_readline();
        6037                 :            :
        6038                 :          0 :         pid = PyUnicode_DecodeASCII(s, len - 1, "strict");
        6039         [ #  # ]:          0 :         if (pid == NULL) {
        6040         [ #  # ]:          0 :             if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
        6041                 :          0 :                 PyErr_SetString(_Pickle_GetGlobalState()->UnpicklingError,
        6042                 :            :                                 "persistent IDs in protocol 0 must be "
        6043                 :            :                                 "ASCII strings");
        6044                 :            :             }
        6045                 :          0 :             return -1;
        6046                 :            :         }
        6047                 :            :
        6048                 :          0 :         obj = call_method(self->pers_func, self->pers_func_self, pid);
        6049                 :          0 :         Py_DECREF(pid);
        6050         [ #  # ]:          0 :         if (obj == NULL)
        6051                 :          0 :             return -1;
        6052                 :            :
        6053         [ #  # ]:          0 :         PDATA_PUSH(self->stack, obj, -1);
        6054                 :          0 :         return 0;
        6055                 :            :     }
        6056                 :            :     else {
        6057                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        6058                 :          0 :         PyErr_SetString(st->UnpicklingError,
        6059                 :            :                         "A load persistent id instruction was encountered, "
        6060                 :            :                         "but no persistent_load function was specified.");
        6061                 :          0 :         return -1;
        6062                 :            :     }
        6063                 :            : }
        6064                 :            :
        6065                 :            : static int
        6066                 :          0 : load_binpersid(UnpicklerObject *self)
        6067                 :            : {
        6068                 :            :     PyObject *pid, *obj;
        6069                 :            :
        6070         [ #  # ]:          0 :     if (self->pers_func) {
        6071                 :          0 :         PDATA_POP(self->stack, pid);
        6072         [ #  # ]:          0 :         if (pid == NULL)
        6073                 :          0 :             return -1;
        6074                 :            :
        6075                 :          0 :         obj = call_method(self->pers_func, self->pers_func_self, pid);
        6076                 :          0 :         Py_DECREF(pid);
        6077         [ #  # ]:          0 :         if (obj == NULL)
        6078                 :          0 :             return -1;
        6079                 :            :
        6080         [ #  # ]:          0 :         PDATA_PUSH(self->stack, obj, -1);
        6081                 :          0 :         return 0;
        6082                 :            :     }
        6083                 :            :     else {
        6084                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        6085                 :          0 :         PyErr_SetString(st->UnpicklingError,
        6086                 :            :                         "A load persistent id instruction was encountered, "
        6087                 :            :                         "but no persistent_load function was specified.");
        6088                 :          0 :         return -1;
        6089                 :            :     }
        6090                 :            : }
        6091                 :            :
        6092                 :            : static int
        6093                 :          0 : load_pop(UnpicklerObject *self)
        6094                 :            : {
        6095                 :          0 :     Py_ssize_t len = Py_SIZE(self->stack);
        6096                 :            :
        6097                 :            :     /* Note that we split the (pickle.py) stack into two stacks,
        6098                 :            :      * an object stack and a mark stack. We have to be clever and
        6099                 :            :      * pop the right one. We do this by looking at the top of the
        6100                 :            :      * mark stack first, and only signalling a stack underflow if
        6101                 :            :      * the object stack is empty and the mark stack doesn't match
        6102                 :            :      * our expectations.
        6103                 :            :      */
        6104   [ #  #  #  # ]:          0 :     if (self->num_marks > 0 && self->marks[self->num_marks - 1] == len) {
        6105                 :          0 :         self->num_marks--;
        6106                 :          0 :         self->stack->mark_set = self->num_marks != 0;
        6107                 :          0 :         self->stack->fence = self->num_marks ?
        6108         [ #  # ]:          0 :                 self->marks[self->num_marks - 1] : 0;
        6109         [ #  # ]:          0 :     } else if (len <= self->stack->fence)
        6110                 :          0 :         return Pdata_stack_underflow(self->stack);
        6111                 :            :     else {
        6112                 :          0 :         len--;
        6113                 :          0 :         Py_DECREF(self->stack->data[len]);
        6114                 :          0 :         Py_SET_SIZE(self->stack, len);
        6115                 :            :     }
        6116                 :          0 :     return 0;
        6117                 :            : }
        6118                 :            :
        6119                 :            : static int
        6120                 :          0 : load_pop_mark(UnpicklerObject *self)
        6121                 :            : {
        6122                 :            :     Py_ssize_t i;
        6123                 :            :
        6124         [ #  # ]:          0 :     if ((i = marker(self)) < 0)
        6125                 :          0 :         return -1;
        6126                 :            :
        6127                 :          0 :     Pdata_clear(self->stack, i);
        6128                 :            :
        6129                 :          0 :     return 0;
        6130                 :            : }
        6131                 :            :
        6132                 :            : static int
        6133                 :          0 : load_dup(UnpicklerObject *self)
        6134                 :            : {
        6135                 :            :     PyObject *last;
        6136                 :          0 :     Py_ssize_t len = Py_SIZE(self->stack);
        6137                 :            :
        6138         [ #  # ]:          0 :     if (len <= self->stack->fence)
        6139                 :          0 :         return Pdata_stack_underflow(self->stack);
        6140                 :          0 :     last = self->stack->data[len - 1];
        6141         [ #  # ]:          0 :     PDATA_APPEND(self->stack, last, -1);
        6142                 :          0 :     return 0;
        6143                 :            : }
        6144                 :            :
        6145                 :            : static int
        6146                 :          0 : load_get(UnpicklerObject *self)
        6147                 :            : {
        6148                 :            :     PyObject *key, *value;
        6149                 :            :     Py_ssize_t idx;
        6150                 :            :     Py_ssize_t len;
        6151                 :            :     char *s;
        6152                 :            :
        6153         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        6154                 :          0 :         return -1;
        6155         [ #  # ]:          0 :     if (len < 2)
        6156                 :          0 :         return bad_readline();
        6157                 :            :
        6158                 :          0 :     key = PyLong_FromString(s, NULL, 10);
        6159         [ #  # ]:          0 :     if (key == NULL)
        6160                 :          0 :         return -1;
        6161                 :          0 :     idx = PyLong_AsSsize_t(key);
        6162   [ #  #  #  # ]:          0 :     if (idx == -1 && PyErr_Occurred()) {
        6163                 :          0 :         Py_DECREF(key);
        6164                 :          0 :         return -1;
        6165                 :            :     }
        6166                 :            :
        6167                 :          0 :     value = _Unpickler_MemoGet(self, idx);
        6168         [ #  # ]:          0 :     if (value == NULL) {
        6169         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        6170                 :          0 :            PickleState *st = _Pickle_GetGlobalState();
        6171                 :          0 :            PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
        6172                 :            :         }
        6173                 :          0 :         Py_DECREF(key);
        6174                 :          0 :         return -1;
        6175                 :            :     }
        6176                 :          0 :     Py_DECREF(key);
        6177                 :            :
        6178         [ #  # ]:          0 :     PDATA_APPEND(self->stack, value, -1);
        6179                 :          0 :     return 0;
        6180                 :            : }
        6181                 :            :
        6182                 :            : static int
        6183                 :          0 : load_binget(UnpicklerObject *self)
        6184                 :            : {
        6185                 :            :     PyObject *value;
        6186                 :            :     Py_ssize_t idx;
        6187                 :            :     char *s;
        6188                 :            :
        6189   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 1) < 0)
        6190                 :          0 :         return -1;
        6191                 :            :
        6192                 :          0 :     idx = Py_CHARMASK(s[0]);
        6193                 :            :
        6194                 :          0 :     value = _Unpickler_MemoGet(self, idx);
        6195         [ #  # ]:          0 :     if (value == NULL) {
        6196                 :          0 :         PyObject *key = PyLong_FromSsize_t(idx);
        6197         [ #  # ]:          0 :         if (key != NULL) {
        6198                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        6199                 :          0 :             PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
        6200                 :          0 :             Py_DECREF(key);
        6201                 :            :         }
        6202                 :          0 :         return -1;
        6203                 :            :     }
        6204                 :            :
        6205         [ #  # ]:          0 :     PDATA_APPEND(self->stack, value, -1);
        6206                 :          0 :     return 0;
        6207                 :            : }
        6208                 :            :
        6209                 :            : static int
        6210                 :          0 : load_long_binget(UnpicklerObject *self)
        6211                 :            : {
        6212                 :            :     PyObject *value;
        6213                 :            :     Py_ssize_t idx;
        6214                 :            :     char *s;
        6215                 :            :
        6216   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 4) < 0)
        6217                 :          0 :         return -1;
        6218                 :            :
        6219                 :          0 :     idx = calc_binsize(s, 4);
        6220                 :            :
        6221                 :          0 :     value = _Unpickler_MemoGet(self, idx);
        6222         [ #  # ]:          0 :     if (value == NULL) {
        6223                 :          0 :         PyObject *key = PyLong_FromSsize_t(idx);
        6224         [ #  # ]:          0 :         if (key != NULL) {
        6225                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        6226                 :          0 :             PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
        6227                 :          0 :             Py_DECREF(key);
        6228                 :            :         }
        6229                 :          0 :         return -1;
        6230                 :            :     }
        6231                 :            :
        6232         [ #  # ]:          0 :     PDATA_APPEND(self->stack, value, -1);
        6233                 :          0 :     return 0;
        6234                 :            : }
        6235                 :            :
        6236                 :            : /* Push an object from the extension registry (EXT[124]).  nbytes is
        6237                 :            :  * the number of bytes following the opcode, holding the index (code) value.
        6238                 :            :  */
        6239                 :            : static int
        6240                 :          0 : load_extension(UnpicklerObject *self, int nbytes)
        6241                 :            : {
        6242                 :            :     char *codebytes;            /* the nbytes bytes after the opcode */
        6243                 :            :     long code;                  /* calc_binint returns long */
        6244                 :            :     PyObject *py_code;          /* code as a Python int */
        6245                 :            :     PyObject *obj;              /* the object to push */
        6246                 :            :     PyObject *pair;             /* (module_name, class_name) */
        6247                 :            :     PyObject *module_name, *class_name;
        6248                 :          0 :     PickleState *st = _Pickle_GetGlobalState();
        6249                 :            :
        6250                 :            :     assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
        6251   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &codebytes, nbytes) < 0)
        6252                 :          0 :         return -1;
        6253                 :          0 :     code = calc_binint(codebytes, nbytes);
        6254         [ #  # ]:          0 :     if (code <= 0) {            /* note that 0 is forbidden */
        6255                 :            :         /* Corrupt or hostile pickle. */
        6256                 :          0 :         PyErr_SetString(st->UnpicklingError, "EXT specifies code <= 0");
        6257                 :          0 :         return -1;
        6258                 :            :     }
        6259                 :            :
        6260                 :            :     /* Look for the code in the cache. */
        6261                 :          0 :     py_code = PyLong_FromLong(code);
        6262         [ #  # ]:          0 :     if (py_code == NULL)
        6263                 :          0 :         return -1;
        6264                 :          0 :     obj = PyDict_GetItemWithError(st->extension_cache, py_code);
        6265         [ #  # ]:          0 :     if (obj != NULL) {
        6266                 :            :         /* Bingo. */
        6267                 :          0 :         Py_DECREF(py_code);
        6268         [ #  # ]:          0 :         PDATA_APPEND(self->stack, obj, -1);
        6269                 :          0 :         return 0;
        6270                 :            :     }
        6271         [ #  # ]:          0 :     if (PyErr_Occurred()) {
        6272                 :          0 :         Py_DECREF(py_code);
        6273                 :          0 :         return -1;
        6274                 :            :     }
        6275                 :            :
        6276                 :            :     /* Look up the (module_name, class_name) pair. */
        6277                 :          0 :     pair = PyDict_GetItemWithError(st->inverted_registry, py_code);
        6278         [ #  # ]:          0 :     if (pair == NULL) {
        6279                 :          0 :         Py_DECREF(py_code);
        6280         [ #  # ]:          0 :         if (!PyErr_Occurred()) {
        6281                 :          0 :             PyErr_Format(PyExc_ValueError, "unregistered extension "
        6282                 :            :                          "code %ld", code);
        6283                 :            :         }
        6284                 :          0 :         return -1;
        6285                 :            :     }
        6286                 :            :     /* Since the extension registry is manipulable via Python code,
        6287                 :            :      * confirm that pair is really a 2-tuple of strings.
        6288                 :            :      */
        6289   [ #  #  #  # ]:          0 :     if (!PyTuple_Check(pair) || PyTuple_Size(pair) != 2) {
        6290                 :          0 :         goto error;
        6291                 :            :     }
        6292                 :            :
        6293                 :          0 :     module_name = PyTuple_GET_ITEM(pair, 0);
        6294         [ #  # ]:          0 :     if (!PyUnicode_Check(module_name)) {
        6295                 :          0 :         goto error;
        6296                 :            :     }
        6297                 :            :
        6298                 :          0 :     class_name = PyTuple_GET_ITEM(pair, 1);
        6299         [ #  # ]:          0 :     if (!PyUnicode_Check(class_name)) {
        6300                 :          0 :         goto error;
        6301                 :            :     }
        6302                 :            :
        6303                 :            :     /* Load the object. */
        6304                 :          0 :     obj = find_class(self, module_name, class_name);
        6305         [ #  # ]:          0 :     if (obj == NULL) {
        6306                 :          0 :         Py_DECREF(py_code);
        6307                 :          0 :         return -1;
        6308                 :            :     }
        6309                 :            :     /* Cache code -> obj. */
        6310                 :          0 :     code = PyDict_SetItem(st->extension_cache, py_code, obj);
        6311                 :          0 :     Py_DECREF(py_code);
        6312         [ #  # ]:          0 :     if (code < 0) {
        6313                 :          0 :         Py_DECREF(obj);
        6314                 :          0 :         return -1;
        6315                 :            :     }
        6316         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        6317                 :          0 :     return 0;
        6318                 :            :
        6319                 :          0 : error:
        6320                 :          0 :     Py_DECREF(py_code);
        6321                 :          0 :     PyErr_Format(PyExc_ValueError, "_inverted_registry[%ld] "
        6322                 :            :                  "isn't a 2-tuple of strings", code);
        6323                 :          0 :     return -1;
        6324                 :            : }
        6325                 :            :
        6326                 :            : static int
        6327                 :          0 : load_put(UnpicklerObject *self)
        6328                 :            : {
        6329                 :            :     PyObject *key, *value;
        6330                 :            :     Py_ssize_t idx;
        6331                 :            :     Py_ssize_t len;
        6332                 :          0 :     char *s = NULL;
        6333                 :            :
        6334         [ #  # ]:          0 :     if ((len = _Unpickler_Readline(self, &s)) < 0)
        6335                 :          0 :         return -1;
        6336         [ #  # ]:          0 :     if (len < 2)
        6337                 :          0 :         return bad_readline();
        6338         [ #  # ]:          0 :     if (Py_SIZE(self->stack) <= self->stack->fence)
        6339                 :          0 :         return Pdata_stack_underflow(self->stack);
        6340                 :          0 :     value = self->stack->data[Py_SIZE(self->stack) - 1];
        6341                 :            :
        6342                 :          0 :     key = PyLong_FromString(s, NULL, 10);
        6343         [ #  # ]:          0 :     if (key == NULL)
        6344                 :          0 :         return -1;
        6345                 :          0 :     idx = PyLong_AsSsize_t(key);
        6346                 :          0 :     Py_DECREF(key);
        6347         [ #  # ]:          0 :     if (idx < 0) {
        6348         [ #  # ]:          0 :         if (!PyErr_Occurred())
        6349                 :          0 :             PyErr_SetString(PyExc_ValueError,
        6350                 :            :                             "negative PUT argument");
        6351                 :          0 :         return -1;
        6352                 :            :     }
        6353                 :            :
        6354                 :          0 :     return _Unpickler_MemoPut(self, idx, value);
        6355                 :            : }
        6356                 :            :
        6357                 :            : static int
        6358                 :          0 : load_binput(UnpicklerObject *self)
        6359                 :            : {
        6360                 :            :     PyObject *value;
        6361                 :            :     Py_ssize_t idx;
        6362                 :            :     char *s;
        6363                 :            :
        6364   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 1) < 0)
        6365                 :          0 :         return -1;
        6366                 :            :
        6367         [ #  # ]:          0 :     if (Py_SIZE(self->stack) <= self->stack->fence)
        6368                 :          0 :         return Pdata_stack_underflow(self->stack);
        6369                 :          0 :     value = self->stack->data[Py_SIZE(self->stack) - 1];
        6370                 :            :
        6371                 :          0 :     idx = Py_CHARMASK(s[0]);
        6372                 :            :
        6373                 :          0 :     return _Unpickler_MemoPut(self, idx, value);
        6374                 :            : }
        6375                 :            :
        6376                 :            : static int
        6377                 :          0 : load_long_binput(UnpicklerObject *self)
        6378                 :            : {
        6379                 :            :     PyObject *value;
        6380                 :            :     Py_ssize_t idx;
        6381                 :            :     char *s;
        6382                 :            :
        6383   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 4) < 0)
        6384                 :          0 :         return -1;
        6385                 :            :
        6386         [ #  # ]:          0 :     if (Py_SIZE(self->stack) <= self->stack->fence)
        6387                 :          0 :         return Pdata_stack_underflow(self->stack);
        6388                 :          0 :     value = self->stack->data[Py_SIZE(self->stack) - 1];
        6389                 :            :
        6390                 :          0 :     idx = calc_binsize(s, 4);
        6391         [ #  # ]:          0 :     if (idx < 0) {
        6392                 :          0 :         PyErr_SetString(PyExc_ValueError,
        6393                 :            :                         "negative LONG_BINPUT argument");
        6394                 :          0 :         return -1;
        6395                 :            :     }
        6396                 :            :
        6397                 :          0 :     return _Unpickler_MemoPut(self, idx, value);
        6398                 :            : }
        6399                 :            :
        6400                 :            : static int
        6401                 :          0 : load_memoize(UnpicklerObject *self)
        6402                 :            : {
        6403                 :            :     PyObject *value;
        6404                 :            :
        6405         [ #  # ]:          0 :     if (Py_SIZE(self->stack) <= self->stack->fence)
        6406                 :          0 :         return Pdata_stack_underflow(self->stack);
        6407                 :          0 :     value = self->stack->data[Py_SIZE(self->stack) - 1];
        6408                 :            :
        6409                 :          0 :     return _Unpickler_MemoPut(self, self->memo_len, value);
        6410                 :            : }
        6411                 :            :
        6412                 :            : static int
        6413                 :          0 : do_append(UnpicklerObject *self, Py_ssize_t x)
        6414                 :            : {
        6415                 :            :     PyObject *value;
        6416                 :            :     PyObject *slice;
        6417                 :            :     PyObject *list;
        6418                 :            :     PyObject *result;
        6419                 :            :     Py_ssize_t len, i;
        6420                 :            :
        6421                 :          0 :     len = Py_SIZE(self->stack);
        6422   [ #  #  #  # ]:          0 :     if (x > len || x <= self->stack->fence)
        6423                 :          0 :         return Pdata_stack_underflow(self->stack);
        6424         [ #  # ]:          0 :     if (len == x)  /* nothing to do */
        6425                 :          0 :         return 0;
        6426                 :            :
        6427                 :          0 :     list = self->stack->data[x - 1];
        6428                 :            :
        6429         [ #  # ]:          0 :     if (PyList_CheckExact(list)) {
        6430                 :            :         Py_ssize_t list_len;
        6431                 :            :         int ret;
        6432                 :            :
        6433                 :          0 :         slice = Pdata_poplist(self->stack, x);
        6434         [ #  # ]:          0 :         if (!slice)
        6435                 :          0 :             return -1;
        6436                 :          0 :         list_len = PyList_GET_SIZE(list);
        6437                 :          0 :         ret = PyList_SetSlice(list, list_len, list_len, slice);
        6438                 :          0 :         Py_DECREF(slice);
        6439                 :          0 :         return ret;
        6440                 :            :     }
        6441                 :            :     else {
        6442                 :            :         PyObject *extend_func;
        6443                 :            :
        6444         [ #  # ]:          0 :         if (_PyObject_LookupAttr(list, &_Py_ID(extend), &extend_func) < 0) {
        6445                 :          0 :             return -1;
        6446                 :            :         }
        6447         [ #  # ]:          0 :         if (extend_func != NULL) {
        6448                 :          0 :             slice = Pdata_poplist(self->stack, x);
        6449         [ #  # ]:          0 :             if (!slice) {
        6450                 :          0 :                 Py_DECREF(extend_func);
        6451                 :          0 :                 return -1;
        6452                 :            :             }
        6453                 :          0 :             result = _Pickle_FastCall(extend_func, slice);
        6454                 :          0 :             Py_DECREF(extend_func);
        6455         [ #  # ]:          0 :             if (result == NULL)
        6456                 :          0 :                 return -1;
        6457                 :          0 :             Py_DECREF(result);
        6458                 :            :         }
        6459                 :            :         else {
        6460                 :            :             PyObject *append_func;
        6461                 :            :
        6462                 :            :             /* Even if the PEP 307 requires extend() and append() methods,
        6463                 :            :                fall back on append() if the object has no extend() method
        6464                 :            :                for backward compatibility. */
        6465                 :          0 :             append_func = PyObject_GetAttr(list, &_Py_ID(append));
        6466         [ #  # ]:          0 :             if (append_func == NULL)
        6467                 :          0 :                 return -1;
        6468         [ #  # ]:          0 :             for (i = x; i < len; i++) {
        6469                 :          0 :                 value = self->stack->data[i];
        6470                 :          0 :                 result = _Pickle_FastCall(append_func, value);
        6471         [ #  # ]:          0 :                 if (result == NULL) {
        6472                 :          0 :                     Pdata_clear(self->stack, i + 1);
        6473                 :          0 :                     Py_SET_SIZE(self->stack, x);
        6474                 :          0 :                     Py_DECREF(append_func);
        6475                 :          0 :                     return -1;
        6476                 :            :                 }
        6477                 :          0 :                 Py_DECREF(result);
        6478                 :            :             }
        6479                 :          0 :             Py_SET_SIZE(self->stack, x);
        6480                 :          0 :             Py_DECREF(append_func);
        6481                 :            :         }
        6482                 :            :     }
        6483                 :            :
        6484                 :          0 :     return 0;
        6485                 :            : }
        6486                 :            :
        6487                 :            : static int
        6488                 :          0 : load_append(UnpicklerObject *self)
        6489                 :            : {
        6490         [ #  # ]:          0 :     if (Py_SIZE(self->stack) - 1 <= self->stack->fence)
        6491                 :          0 :         return Pdata_stack_underflow(self->stack);
        6492                 :          0 :     return do_append(self, Py_SIZE(self->stack) - 1);
        6493                 :            : }
        6494                 :            :
        6495                 :            : static int
        6496                 :          0 : load_appends(UnpicklerObject *self)
        6497                 :            : {
        6498                 :          0 :     Py_ssize_t i = marker(self);
        6499         [ #  # ]:          0 :     if (i < 0)
        6500                 :          0 :         return -1;
        6501                 :          0 :     return do_append(self, i);
        6502                 :            : }
        6503                 :            :
        6504                 :            : static int
        6505                 :          0 : do_setitems(UnpicklerObject *self, Py_ssize_t x)
        6506                 :            : {
        6507                 :            :     PyObject *value, *key;
        6508                 :            :     PyObject *dict;
        6509                 :            :     Py_ssize_t len, i;
        6510                 :          0 :     int status = 0;
        6511                 :            :
        6512                 :          0 :     len = Py_SIZE(self->stack);
        6513   [ #  #  #  # ]:          0 :     if (x > len || x <= self->stack->fence)
        6514                 :          0 :         return Pdata_stack_underflow(self->stack);
        6515         [ #  # ]:          0 :     if (len == x)  /* nothing to do */
        6516                 :          0 :         return 0;
        6517         [ #  # ]:          0 :     if ((len - x) % 2 != 0) {
        6518                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        6519                 :            :         /* Corrupt or hostile pickle -- we never write one like this. */
        6520                 :          0 :         PyErr_SetString(st->UnpicklingError,
        6521                 :            :                         "odd number of items for SETITEMS");
        6522                 :          0 :         return -1;
        6523                 :            :     }
        6524                 :            :
        6525                 :            :     /* Here, dict does not actually need to be a PyDict; it could be anything
        6526                 :            :        that supports the __setitem__ attribute. */
        6527                 :          0 :     dict = self->stack->data[x - 1];
        6528                 :            :
        6529         [ #  # ]:          0 :     for (i = x + 1; i < len; i += 2) {
        6530                 :          0 :         key = self->stack->data[i - 1];
        6531                 :          0 :         value = self->stack->data[i];
        6532         [ #  # ]:          0 :         if (PyObject_SetItem(dict, key, value) < 0) {
        6533                 :          0 :             status = -1;
        6534                 :          0 :             break;
        6535                 :            :         }
        6536                 :            :     }
        6537                 :            :
        6538                 :          0 :     Pdata_clear(self->stack, x);
        6539                 :          0 :     return status;
        6540                 :            : }
        6541                 :            :
        6542                 :            : static int
        6543                 :          0 : load_setitem(UnpicklerObject *self)
        6544                 :            : {
        6545                 :          0 :     return do_setitems(self, Py_SIZE(self->stack) - 2);
        6546                 :            : }
        6547                 :            :
        6548                 :            : static int
        6549                 :          0 : load_setitems(UnpicklerObject *self)
        6550                 :            : {
        6551                 :          0 :     Py_ssize_t i = marker(self);
        6552         [ #  # ]:          0 :     if (i < 0)
        6553                 :          0 :         return -1;
        6554                 :          0 :     return do_setitems(self, i);
        6555                 :            : }
        6556                 :            :
        6557                 :            : static int
        6558                 :          0 : load_additems(UnpicklerObject *self)
        6559                 :            : {
        6560                 :            :     PyObject *set;
        6561                 :            :     Py_ssize_t mark, len, i;
        6562                 :            :
        6563                 :          0 :     mark =  marker(self);
        6564         [ #  # ]:          0 :     if (mark < 0)
        6565                 :          0 :         return -1;
        6566                 :          0 :     len = Py_SIZE(self->stack);
        6567   [ #  #  #  # ]:          0 :     if (mark > len || mark <= self->stack->fence)
        6568                 :          0 :         return Pdata_stack_underflow(self->stack);
        6569         [ #  # ]:          0 :     if (len == mark)  /* nothing to do */
        6570                 :          0 :         return 0;
        6571                 :            :
        6572                 :          0 :     set = self->stack->data[mark - 1];
        6573                 :            :
        6574   [ #  #  #  # ]:          0 :     if (PySet_Check(set)) {
        6575                 :            :         PyObject *items;
        6576                 :            :         int status;
        6577                 :            :
        6578                 :          0 :         items = Pdata_poptuple(self->stack, mark);
        6579         [ #  # ]:          0 :         if (items == NULL)
        6580                 :          0 :             return -1;
        6581                 :            :
        6582                 :          0 :         status = _PySet_Update(set, items);
        6583                 :          0 :         Py_DECREF(items);
        6584                 :          0 :         return status;
        6585                 :            :     }
        6586                 :            :     else {
        6587                 :            :         PyObject *add_func;
        6588                 :            :
        6589                 :          0 :         add_func = PyObject_GetAttr(set, &_Py_ID(add));
        6590         [ #  # ]:          0 :         if (add_func == NULL)
        6591                 :          0 :             return -1;
        6592         [ #  # ]:          0 :         for (i = mark; i < len; i++) {
        6593                 :            :             PyObject *result;
        6594                 :            :             PyObject *item;
        6595                 :            :
        6596                 :          0 :             item = self->stack->data[i];
        6597                 :          0 :             result = _Pickle_FastCall(add_func, item);
        6598         [ #  # ]:          0 :             if (result == NULL) {
        6599                 :          0 :                 Pdata_clear(self->stack, i + 1);
        6600                 :          0 :                 Py_SET_SIZE(self->stack, mark);
        6601                 :          0 :                 return -1;
        6602                 :            :             }
        6603                 :          0 :             Py_DECREF(result);
        6604                 :            :         }
        6605                 :          0 :         Py_SET_SIZE(self->stack, mark);
        6606                 :            :     }
        6607                 :            :
        6608                 :          0 :     return 0;
        6609                 :            : }
        6610                 :            :
        6611                 :            : static int
        6612                 :          0 : load_build(UnpicklerObject *self)
        6613                 :            : {
        6614                 :            :     PyObject *state, *inst, *slotstate;
        6615                 :            :     PyObject *setstate;
        6616                 :          0 :     int status = 0;
        6617                 :            :
        6618                 :            :     /* Stack is ... instance, state.  We want to leave instance at
        6619                 :            :      * the stack top, possibly mutated via instance.__setstate__(state).
        6620                 :            :      */
        6621         [ #  # ]:          0 :     if (Py_SIZE(self->stack) - 2 < self->stack->fence)
        6622                 :          0 :         return Pdata_stack_underflow(self->stack);
        6623                 :            :
        6624                 :          0 :     PDATA_POP(self->stack, state);
        6625         [ #  # ]:          0 :     if (state == NULL)
        6626                 :          0 :         return -1;
        6627                 :            :
        6628                 :          0 :     inst = self->stack->data[Py_SIZE(self->stack) - 1];
        6629                 :            :
        6630         [ #  # ]:          0 :     if (_PyObject_LookupAttr(inst, &_Py_ID(__setstate__), &setstate) < 0) {
        6631                 :          0 :         Py_DECREF(state);
        6632                 :          0 :         return -1;
        6633                 :            :     }
        6634         [ #  # ]:          0 :     if (setstate != NULL) {
        6635                 :            :         PyObject *result;
        6636                 :            :
        6637                 :            :         /* The explicit __setstate__ is responsible for everything. */
        6638                 :          0 :         result = _Pickle_FastCall(setstate, state);
        6639                 :          0 :         Py_DECREF(setstate);
        6640         [ #  # ]:          0 :         if (result == NULL)
        6641                 :          0 :             return -1;
        6642                 :          0 :         Py_DECREF(result);
        6643                 :          0 :         return 0;
        6644                 :            :     }
        6645                 :            :
        6646                 :            :     /* A default __setstate__.  First see whether state embeds a
        6647                 :            :      * slot state dict too (a proto 2 addition).
        6648                 :            :      */
        6649   [ #  #  #  # ]:          0 :     if (PyTuple_Check(state) && PyTuple_GET_SIZE(state) == 2) {
        6650                 :          0 :         PyObject *tmp = state;
        6651                 :            :
        6652                 :          0 :         state = PyTuple_GET_ITEM(tmp, 0);
        6653                 :          0 :         slotstate = PyTuple_GET_ITEM(tmp, 1);
        6654                 :          0 :         Py_INCREF(state);
        6655                 :          0 :         Py_INCREF(slotstate);
        6656                 :          0 :         Py_DECREF(tmp);
        6657                 :            :     }
        6658                 :            :     else
        6659                 :          0 :         slotstate = NULL;
        6660                 :            :
        6661                 :            :     /* Set inst.__dict__ from the state dict (if any). */
        6662         [ #  # ]:          0 :     if (state != Py_None) {
        6663                 :            :         PyObject *dict;
        6664                 :            :         PyObject *d_key, *d_value;
        6665                 :            :         Py_ssize_t i;
        6666                 :            :
        6667         [ #  # ]:          0 :         if (!PyDict_Check(state)) {
        6668                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        6669                 :          0 :             PyErr_SetString(st->UnpicklingError, "state is not a dictionary");
        6670                 :          0 :             goto error;
        6671                 :            :         }
        6672                 :          0 :         dict = PyObject_GetAttr(inst, &_Py_ID(__dict__));
        6673         [ #  # ]:          0 :         if (dict == NULL)
        6674                 :          0 :             goto error;
        6675                 :            :
        6676                 :          0 :         i = 0;
        6677         [ #  # ]:          0 :         while (PyDict_Next(state, &i, &d_key, &d_value)) {
        6678                 :            :             /* normally the keys for instance attributes are
        6679                 :            :                interned.  we should try to do that here. */
        6680                 :          0 :             Py_INCREF(d_key);
        6681         [ #  # ]:          0 :             if (PyUnicode_CheckExact(d_key))
        6682                 :          0 :                 PyUnicode_InternInPlace(&d_key);
        6683         [ #  # ]:          0 :             if (PyObject_SetItem(dict, d_key, d_value) < 0) {
        6684                 :          0 :                 Py_DECREF(d_key);
        6685                 :          0 :                 goto error;
        6686                 :            :             }
        6687                 :          0 :             Py_DECREF(d_key);
        6688                 :            :         }
        6689                 :          0 :         Py_DECREF(dict);
        6690                 :            :     }
        6691                 :            :
        6692                 :            :     /* Also set instance attributes from the slotstate dict (if any). */
        6693         [ #  # ]:          0 :     if (slotstate != NULL) {
        6694                 :            :         PyObject *d_key, *d_value;
        6695                 :            :         Py_ssize_t i;
        6696                 :            :
        6697         [ #  # ]:          0 :         if (!PyDict_Check(slotstate)) {
        6698                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        6699                 :          0 :             PyErr_SetString(st->UnpicklingError,
        6700                 :            :                             "slot state is not a dictionary");
        6701                 :          0 :             goto error;
        6702                 :            :         }
        6703                 :          0 :         i = 0;
        6704         [ #  # ]:          0 :         while (PyDict_Next(slotstate, &i, &d_key, &d_value)) {
        6705         [ #  # ]:          0 :             if (PyObject_SetAttr(inst, d_key, d_value) < 0)
        6706                 :          0 :                 goto error;
        6707                 :            :         }
        6708                 :            :     }
        6709                 :            :
        6710                 :            :     if (0) {
        6711                 :          0 :   error:
        6712                 :          0 :         status = -1;
        6713                 :            :     }
        6714                 :            :
        6715                 :          0 :     Py_DECREF(state);
        6716                 :          0 :     Py_XDECREF(slotstate);
        6717                 :          0 :     return status;
        6718                 :            : }
        6719                 :            :
        6720                 :            : static int
        6721                 :          0 : load_mark(UnpicklerObject *self)
        6722                 :            : {
        6723                 :            :
        6724                 :            :     /* Note that we split the (pickle.py) stack into two stacks, an
        6725                 :            :      * object stack and a mark stack. Here we push a mark onto the
        6726                 :            :      * mark stack.
        6727                 :            :      */
        6728                 :            :
        6729         [ #  # ]:          0 :     if (self->num_marks >= self->marks_size) {
        6730                 :          0 :         size_t alloc = ((size_t)self->num_marks << 1) + 20;
        6731                 :          0 :         Py_ssize_t *marks_new = self->marks;
        6732         [ #  # ]:          0 :         PyMem_RESIZE(marks_new, Py_ssize_t, alloc);
        6733         [ #  # ]:          0 :         if (marks_new == NULL) {
        6734                 :          0 :             PyErr_NoMemory();
        6735                 :          0 :             return -1;
        6736                 :            :         }
        6737                 :          0 :         self->marks = marks_new;
        6738                 :          0 :         self->marks_size = (Py_ssize_t)alloc;
        6739                 :            :     }
        6740                 :            :
        6741                 :          0 :     self->stack->mark_set = 1;
        6742                 :          0 :     self->marks[self->num_marks++] = self->stack->fence = Py_SIZE(self->stack);
        6743                 :            :
        6744                 :          0 :     return 0;
        6745                 :            : }
        6746                 :            :
        6747                 :            : static int
        6748                 :          0 : load_reduce(UnpicklerObject *self)
        6749                 :            : {
        6750                 :          0 :     PyObject *callable = NULL;
        6751                 :          0 :     PyObject *argtup = NULL;
        6752                 :          0 :     PyObject *obj = NULL;
        6753                 :            :
        6754                 :          0 :     PDATA_POP(self->stack, argtup);
        6755         [ #  # ]:          0 :     if (argtup == NULL)
        6756                 :          0 :         return -1;
        6757                 :          0 :     PDATA_POP(self->stack, callable);
        6758         [ #  # ]:          0 :     if (callable) {
        6759                 :          0 :         obj = PyObject_CallObject(callable, argtup);
        6760                 :          0 :         Py_DECREF(callable);
        6761                 :            :     }
        6762                 :          0 :     Py_DECREF(argtup);
        6763                 :            :
        6764         [ #  # ]:          0 :     if (obj == NULL)
        6765                 :          0 :         return -1;
        6766                 :            :
        6767         [ #  # ]:          0 :     PDATA_PUSH(self->stack, obj, -1);
        6768                 :          0 :     return 0;
        6769                 :            : }
        6770                 :            :
        6771                 :            : /* Just raises an error if we don't know the protocol specified.  PROTO
        6772                 :            :  * is the first opcode for protocols >= 2.
        6773                 :            :  */
        6774                 :            : static int
        6775                 :          0 : load_proto(UnpicklerObject *self)
        6776                 :            : {
        6777                 :            :     char *s;
        6778                 :            :     int i;
        6779                 :            :
        6780   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 1) < 0)
        6781                 :          0 :         return -1;
        6782                 :            :
        6783                 :          0 :     i = (unsigned char)s[0];
        6784         [ #  # ]:          0 :     if (i <= HIGHEST_PROTOCOL) {
        6785                 :          0 :         self->proto = i;
        6786                 :          0 :         return 0;
        6787                 :            :     }
        6788                 :            :
        6789                 :          0 :     PyErr_Format(PyExc_ValueError, "unsupported pickle protocol: %d", i);
        6790                 :          0 :     return -1;
        6791                 :            : }
        6792                 :            :
        6793                 :            : static int
        6794                 :          0 : load_frame(UnpicklerObject *self)
        6795                 :            : {
        6796                 :            :     char *s;
        6797                 :            :     Py_ssize_t frame_len;
        6798                 :            :
        6799   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, 8) < 0)
        6800                 :          0 :         return -1;
        6801                 :            :
        6802                 :          0 :     frame_len = calc_binsize(s, 8);
        6803         [ #  # ]:          0 :     if (frame_len < 0) {
        6804                 :          0 :         PyErr_Format(PyExc_OverflowError,
        6805                 :            :                      "FRAME length exceeds system's maximum of %zd bytes",
        6806                 :            :                      PY_SSIZE_T_MAX);
        6807                 :          0 :         return -1;
        6808                 :            :     }
        6809                 :            :
        6810   [ #  #  #  # ]:          0 :     if (_Unpickler_Read(self, &s, frame_len) < 0)
        6811                 :          0 :         return -1;
        6812                 :            :
        6813                 :            :     /* Rewind to start of frame */
        6814                 :          0 :     self->next_read_idx -= frame_len;
        6815                 :          0 :     return 0;
        6816                 :            : }
        6817                 :            :
        6818                 :            : static PyObject *
        6819                 :          0 : load(UnpicklerObject *self)
        6820                 :            : {
        6821                 :          0 :     PyObject *value = NULL;
        6822                 :          0 :     char *s = NULL;
        6823                 :            :
        6824                 :          0 :     self->num_marks = 0;
        6825                 :          0 :     self->stack->mark_set = 0;
        6826                 :          0 :     self->stack->fence = 0;
        6827                 :          0 :     self->proto = 0;
        6828         [ #  # ]:          0 :     if (Py_SIZE(self->stack))
        6829                 :          0 :         Pdata_clear(self->stack, 0);
        6830                 :            :
        6831                 :            :     /* Convenient macros for the dispatch while-switch loop just below. */
        6832                 :            : #define OP(opcode, load_func) \
        6833                 :            :     case opcode: if (load_func(self) < 0) break; continue;
        6834                 :            :
        6835                 :            : #define OP_ARG(opcode, load_func, arg) \
        6836                 :            :     case opcode: if (load_func(self, (arg)) < 0) break; continue;
        6837                 :            :
        6838                 :            :     while (1) {
        6839   [ #  #  #  # ]:          0 :         if (_Unpickler_Read(self, &s, 1) < 0) {
        6840                 :          0 :             PickleState *st = _Pickle_GetGlobalState();
        6841         [ #  # ]:          0 :             if (PyErr_ExceptionMatches(st->UnpicklingError)) {
        6842                 :          0 :                 PyErr_Format(PyExc_EOFError, "Ran out of input");
        6843                 :            :             }
        6844                 :          0 :             return NULL;
        6845                 :            :         }
        6846                 :            :
        6847   [ #  #  #  #  :          0 :         switch ((enum opcode)s[0]) {
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
              #  #  #  #  #
                 #  #  #  #
                          # ]
        6848         [ #  # ]:          0 :         OP(NONE, load_none)
        6849         [ #  # ]:          0 :         OP(BININT, load_binint)
        6850         [ #  # ]:          0 :         OP(BININT1, load_binint1)
        6851         [ #  # ]:          0 :         OP(BININT2, load_binint2)
        6852         [ #  # ]:          0 :         OP(INT, load_int)
        6853         [ #  # ]:          0 :         OP(LONG, load_long)
        6854         [ #  # ]:          0 :         OP_ARG(LONG1, load_counted_long, 1)
        6855         [ #  # ]:          0 :         OP_ARG(LONG4, load_counted_long, 4)
        6856         [ #  # ]:          0 :         OP(FLOAT, load_float)
        6857         [ #  # ]:          0 :         OP(BINFLOAT, load_binfloat)
        6858         [ #  # ]:          0 :         OP_ARG(SHORT_BINBYTES, load_counted_binbytes, 1)
        6859         [ #  # ]:          0 :         OP_ARG(BINBYTES, load_counted_binbytes, 4)
        6860         [ #  # ]:          0 :         OP_ARG(BINBYTES8, load_counted_binbytes, 8)
        6861         [ #  # ]:          0 :         OP(BYTEARRAY8, load_counted_bytearray)
        6862         [ #  # ]:          0 :         OP(NEXT_BUFFER, load_next_buffer)
        6863         [ #  # ]:          0 :         OP(READONLY_BUFFER, load_readonly_buffer)
        6864         [ #  # ]:          0 :         OP_ARG(SHORT_BINSTRING, load_counted_binstring, 1)
        6865         [ #  # ]:          0 :         OP_ARG(BINSTRING, load_counted_binstring, 4)
        6866         [ #  # ]:          0 :         OP(STRING, load_string)
        6867         [ #  # ]:          0 :         OP(UNICODE, load_unicode)
        6868         [ #  # ]:          0 :         OP_ARG(SHORT_BINUNICODE, load_counted_binunicode, 1)
        6869         [ #  # ]:          0 :         OP_ARG(BINUNICODE, load_counted_binunicode, 4)
        6870         [ #  # ]:          0 :         OP_ARG(BINUNICODE8, load_counted_binunicode, 8)
        6871         [ #  # ]:          0 :         OP_ARG(EMPTY_TUPLE, load_counted_tuple, 0)
        6872         [ #  # ]:          0 :         OP_ARG(TUPLE1, load_counted_tuple, 1)
        6873         [ #  # ]:          0 :         OP_ARG(TUPLE2, load_counted_tuple, 2)
        6874         [ #  # ]:          0 :         OP_ARG(TUPLE3, load_counted_tuple, 3)
        6875         [ #  # ]:          0 :         OP(TUPLE, load_tuple)
        6876         [ #  # ]:          0 :         OP(EMPTY_LIST, load_empty_list)
        6877         [ #  # ]:          0 :         OP(LIST, load_list)
        6878         [ #  # ]:          0 :         OP(EMPTY_DICT, load_empty_dict)
        6879         [ #  # ]:          0 :         OP(DICT, load_dict)
        6880         [ #  # ]:          0 :         OP(EMPTY_SET, load_empty_set)
        6881         [ #  # ]:          0 :         OP(ADDITEMS, load_additems)
        6882         [ #  # ]:          0 :         OP(FROZENSET, load_frozenset)
        6883         [ #  # ]:          0 :         OP(OBJ, load_obj)
        6884         [ #  # ]:          0 :         OP(INST, load_inst)
        6885         [ #  # ]:          0 :         OP_ARG(NEWOBJ, load_newobj, 0)
        6886         [ #  # ]:          0 :         OP_ARG(NEWOBJ_EX, load_newobj, 1)
        6887         [ #  # ]:          0 :         OP(GLOBAL, load_global)
        6888         [ #  # ]:          0 :         OP(STACK_GLOBAL, load_stack_global)
        6889         [ #  # ]:          0 :         OP(APPEND, load_append)
        6890         [ #  # ]:          0 :         OP(APPENDS, load_appends)
        6891         [ #  # ]:          0 :         OP(BUILD, load_build)
        6892         [ #  # ]:          0 :         OP(DUP, load_dup)
        6893         [ #  # ]:          0 :         OP(BINGET, load_binget)
        6894         [ #  # ]:          0 :         OP(LONG_BINGET, load_long_binget)
        6895         [ #  # ]:          0 :         OP(GET, load_get)
        6896         [ #  # ]:          0 :         OP(MARK, load_mark)
        6897         [ #  # ]:          0 :         OP(BINPUT, load_binput)
        6898         [ #  # ]:          0 :         OP(LONG_BINPUT, load_long_binput)
        6899         [ #  # ]:          0 :         OP(PUT, load_put)
        6900         [ #  # ]:          0 :         OP(MEMOIZE, load_memoize)
        6901         [ #  # ]:          0 :         OP(POP, load_pop)
        6902         [ #  # ]:          0 :         OP(POP_MARK, load_pop_mark)
        6903         [ #  # ]:          0 :         OP(SETITEM, load_setitem)
        6904         [ #  # ]:          0 :         OP(SETITEMS, load_setitems)
        6905         [ #  # ]:          0 :         OP(PERSID, load_persid)
        6906         [ #  # ]:          0 :         OP(BINPERSID, load_binpersid)
        6907         [ #  # ]:          0 :         OP(REDUCE, load_reduce)
        6908         [ #  # ]:          0 :         OP(PROTO, load_proto)
        6909         [ #  # ]:          0 :         OP(FRAME, load_frame)
        6910         [ #  # ]:          0 :         OP_ARG(EXT1, load_extension, 1)
        6911         [ #  # ]:          0 :         OP_ARG(EXT2, load_extension, 2)
        6912         [ #  # ]:          0 :         OP_ARG(EXT4, load_extension, 4)
        6913         [ #  # ]:          0 :         OP_ARG(NEWTRUE, load_bool, Py_True)
        6914         [ #  # ]:          0 :         OP_ARG(NEWFALSE, load_bool, Py_False)
        6915                 :            :
        6916                 :          0 :         case STOP:
        6917                 :          0 :             break;
        6918                 :            :
        6919                 :          0 :         default:
        6920                 :            :             {
        6921                 :          0 :                 PickleState *st = _Pickle_GetGlobalState();
        6922                 :          0 :                 unsigned char c = (unsigned char) *s;
        6923   [ #  #  #  #  :          0 :                 if (0x20 <= c && c <= 0x7e && c != '\'' && c != '\\') {
                 #  #  #  # ]
        6924                 :          0 :                     PyErr_Format(st->UnpicklingError,
        6925                 :            :                                  "invalid load key, '%c'.", c);
        6926                 :            :                 }
        6927                 :            :                 else {
        6928                 :          0 :                     PyErr_Format(st->UnpicklingError,
        6929                 :            :                                  "invalid load key, '\\x%02x'.", c);
        6930                 :            :                 }
        6931                 :          0 :                 return NULL;
        6932                 :            :             }
        6933                 :            :         }
        6934                 :            :
        6935                 :          0 :         break;                  /* and we are done! */
        6936                 :            :     }
        6937                 :            :
        6938         [ #  # ]:          0 :     if (PyErr_Occurred()) {
        6939                 :          0 :         return NULL;
        6940                 :            :     }
        6941                 :            :
        6942         [ #  # ]:          0 :     if (_Unpickler_SkipConsumed(self) < 0)
        6943                 :          0 :         return NULL;
        6944                 :            :
        6945                 :          0 :     PDATA_POP(self->stack, value);
        6946                 :          0 :     return value;
        6947                 :            : }
        6948                 :            :
        6949                 :            : /*[clinic input]
        6950                 :            :
        6951                 :            : _pickle.Unpickler.load
        6952                 :            :
        6953                 :            : Load a pickle.
        6954                 :            :
        6955                 :            : Read a pickled object representation from the open file object given
        6956                 :            : in the constructor, and return the reconstituted object hierarchy
        6957                 :            : specified therein.
        6958                 :            : [clinic start generated code]*/
        6959                 :            :
        6960                 :            : static PyObject *
        6961                 :          0 : _pickle_Unpickler_load_impl(UnpicklerObject *self)
        6962                 :            : /*[clinic end generated code: output=fdcc488aad675b14 input=acbb91a42fa9b7b9]*/
        6963                 :            : {
        6964                 :          0 :     UnpicklerObject *unpickler = (UnpicklerObject*)self;
        6965                 :            :
        6966                 :            :     /* Check whether the Unpickler was initialized correctly. This prevents
        6967                 :            :        segfaulting if a subclass overridden __init__ with a function that does
        6968                 :            :        not call Unpickler.__init__(). Here, we simply ensure that self->read
        6969                 :            :        is not NULL. */
        6970         [ #  # ]:          0 :     if (unpickler->read == NULL) {
        6971                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        6972                 :          0 :         PyErr_Format(st->UnpicklingError,
        6973                 :            :                      "Unpickler.__init__() was not called by %s.__init__()",
        6974                 :          0 :                      Py_TYPE(unpickler)->tp_name);
        6975                 :          0 :         return NULL;
        6976                 :            :     }
        6977                 :            :
        6978                 :          0 :     return load(unpickler);
        6979                 :            : }
        6980                 :            :
        6981                 :            : /* The name of find_class() is misleading. In newer pickle protocols, this
        6982                 :            :    function is used for loading any global (i.e., functions), not just
        6983                 :            :    classes. The name is kept only for backward compatibility. */
        6984                 :            :
        6985                 :            : /*[clinic input]
        6986                 :            :
        6987                 :            : _pickle.Unpickler.find_class
        6988                 :            :
        6989                 :            :   module_name: object
        6990                 :            :   global_name: object
        6991                 :            :   /
        6992                 :            :
        6993                 :            : Return an object from a specified module.
        6994                 :            :
        6995                 :            : If necessary, the module will be imported. Subclasses may override
        6996                 :            : this method (e.g. to restrict unpickling of arbitrary classes and
        6997                 :            : functions).
        6998                 :            :
        6999                 :            : This method is called whenever a class or a function object is
        7000                 :            : needed.  Both arguments passed are str objects.
        7001                 :            : [clinic start generated code]*/
        7002                 :            :
        7003                 :            : static PyObject *
        7004                 :          0 : _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
        7005                 :            :                                   PyObject *module_name,
        7006                 :            :                                   PyObject *global_name)
        7007                 :            : /*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/
        7008                 :            : {
        7009                 :            :     PyObject *global;
        7010                 :            :     PyObject *module;
        7011                 :            :
        7012         [ #  # ]:          0 :     if (PySys_Audit("pickle.find_class", "OO",
        7013                 :            :                     module_name, global_name) < 0) {
        7014                 :          0 :         return NULL;
        7015                 :            :     }
        7016                 :            :
        7017                 :            :     /* Try to map the old names used in Python 2.x to the new ones used in
        7018                 :            :        Python 3.x.  We do this only with old pickle protocols and when the
        7019                 :            :        user has not disabled the feature. */
        7020   [ #  #  #  # ]:          0 :     if (self->proto < 3 && self->fix_imports) {
        7021                 :            :         PyObject *key;
        7022                 :            :         PyObject *item;
        7023                 :          0 :         PickleState *st = _Pickle_GetGlobalState();
        7024                 :            :
        7025                 :            :         /* Check if the global (i.e., a function or a class) was renamed
        7026                 :            :            or moved to another module. */
        7027                 :          0 :         key = PyTuple_Pack(2, module_name, global_name);
        7028         [ #  # ]:          0 :         if (key == NULL)
        7029                 :          0 :             return NULL;
        7030                 :          0 :         item = PyDict_GetItemWithError(st->name_mapping_2to3, key);
        7031                 :          0 :         Py_DECREF(key);
        7032         [ #  # ]:          0 :         if (item) {
        7033   [ #  #  #  # ]:          0 :             if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
        7034                 :          0 :                 PyErr_Format(PyExc_RuntimeError,
        7035                 :            :                              "_compat_pickle.NAME_MAPPING values should be "
        7036                 :          0 :                              "2-tuples, not %.200s", Py_TYPE(item)->tp_name);
        7037                 :          0 :                 return NULL;
        7038                 :            :             }
        7039                 :          0 :             module_name = PyTuple_GET_ITEM(item, 0);
        7040                 :          0 :             global_name = PyTuple_GET_ITEM(item, 1);
        7041   [ #  #  #  # ]:          0 :             if (!PyUnicode_Check(module_name) ||
        7042                 :          0 :                 !PyUnicode_Check(global_name)) {
        7043                 :          0 :                 PyErr_Format(PyExc_RuntimeError,
        7044                 :            :                              "_compat_pickle.NAME_MAPPING values should be "
        7045                 :            :                              "pairs of str, not (%.200s, %.200s)",
        7046                 :          0 :                              Py_TYPE(module_name)->tp_name,
        7047                 :          0 :                              Py_TYPE(global_name)->tp_name);
        7048                 :          0 :                 return NULL;
        7049                 :            :             }
        7050                 :            :         }
        7051         [ #  # ]:          0 :         else if (PyErr_Occurred()) {
        7052                 :          0 :             return NULL;
        7053                 :            :         }
        7054                 :            :         else {
        7055                 :            :             /* Check if the module was renamed. */
        7056                 :          0 :             item = PyDict_GetItemWithError(st->import_mapping_2to3, module_name);
        7057         [ #  # ]:          0 :             if (item) {
        7058         [ #  # ]:          0 :                 if (!PyUnicode_Check(item)) {
        7059                 :          0 :                     PyErr_Format(PyExc_RuntimeError,
        7060                 :            :                                 "_compat_pickle.IMPORT_MAPPING values should be "
        7061                 :          0 :                                 "strings, not %.200s", Py_TYPE(item)->tp_name);
        7062                 :          0 :                     return NULL;
        7063                 :            :                 }
        7064                 :          0 :                 module_name = item;
        7065                 :            :             }
        7066         [ #  # ]:          0 :             else if (PyErr_Occurred()) {
        7067                 :          0 :                 return NULL;
        7068                 :            :             }
        7069                 :            :         }
        7070                 :            :     }
        7071                 :            :
        7072                 :            :     /*
        7073                 :            :      * we don't use PyImport_GetModule here, because it can return partially-
        7074                 :            :      * initialised modules, which then cause the getattribute to fail.
        7075                 :            :      */
        7076                 :          0 :     module = PyImport_Import(module_name);
        7077         [ #  # ]:          0 :     if (module == NULL) {
        7078                 :          0 :         return NULL;
        7079                 :            :     }
        7080                 :          0 :     global = getattribute(module, global_name, self->proto >= 4);
        7081                 :          0 :     Py_DECREF(module);
        7082                 :          0 :     return global;
        7083                 :            : }
        7084                 :            :
        7085                 :            : /*[clinic input]
        7086                 :            :
        7087                 :            : _pickle.Unpickler.__sizeof__ -> size_t
        7088                 :            :
        7089                 :            : Returns size in memory, in bytes.
        7090                 :            : [clinic start generated code]*/
        7091                 :            :
        7092                 :            : static size_t
        7093                 :          0 : _pickle_Unpickler___sizeof___impl(UnpicklerObject *self)
        7094                 :            : /*[clinic end generated code: output=4648d84c228196df input=27180b2b6b524012]*/
        7095                 :            : {
        7096                 :          0 :     size_t res = _PyObject_SIZE(Py_TYPE(self));
        7097         [ #  # ]:          0 :     if (self->memo != NULL)
        7098                 :          0 :         res += self->memo_size * sizeof(PyObject *);
        7099         [ #  # ]:          0 :     if (self->marks != NULL)
        7100                 :          0 :         res += (size_t)self->marks_size * sizeof(Py_ssize_t);
        7101         [ #  # ]:          0 :     if (self->input_line != NULL)
        7102                 :          0 :         res += strlen(self->input_line) + 1;
        7103         [ #  # ]:          0 :     if (self->encoding != NULL)
        7104                 :          0 :         res += strlen(self->encoding) + 1;
        7105         [ #  # ]:          0 :     if (self->errors != NULL)
        7106                 :          0 :         res += strlen(self->errors) + 1;
        7107                 :          0 :     return res;
        7108                 :            : }
        7109                 :            :
        7110                 :            : static struct PyMethodDef Unpickler_methods[] = {
        7111                 :            :     _PICKLE_UNPICKLER_LOAD_METHODDEF
        7112                 :            :     _PICKLE_UNPICKLER_FIND_CLASS_METHODDEF
        7113                 :            :     _PICKLE_UNPICKLER___SIZEOF___METHODDEF
        7114                 :            :     {NULL, NULL}                /* sentinel */
        7115                 :            : };
        7116                 :            :
        7117                 :            : static void
        7118                 :          0 : Unpickler_dealloc(UnpicklerObject *self)
        7119                 :            : {
        7120                 :          0 :     PyObject_GC_UnTrack((PyObject *)self);
        7121                 :          0 :     Py_XDECREF(self->readline);
        7122                 :          0 :     Py_XDECREF(self->readinto);
        7123                 :          0 :     Py_XDECREF(self->read);
        7124                 :          0 :     Py_XDECREF(self->peek);
        7125                 :          0 :     Py_XDECREF(self->stack);
        7126                 :          0 :     Py_XDECREF(self->pers_func);
        7127                 :          0 :     Py_XDECREF(self->buffers);
        7128         [ #  # ]:          0 :     if (self->buffer.buf != NULL) {
        7129                 :          0 :         PyBuffer_Release(&self->buffer);
        7130                 :          0 :         self->buffer.buf = NULL;
        7131                 :            :     }
        7132                 :            :
        7133                 :          0 :     _Unpickler_MemoCleanup(self);
        7134                 :          0 :     PyMem_Free(self->marks);
        7135                 :          0 :     PyMem_Free(self->input_line);
        7136                 :          0 :     PyMem_Free(self->encoding);
        7137                 :          0 :     PyMem_Free(self->errors);
        7138                 :            :
        7139                 :          0 :     Py_TYPE(self)->tp_free((PyObject *)self);
        7140                 :          0 : }
        7141                 :            :
        7142                 :            : static int
        7143                 :          0 : Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
        7144                 :            : {
        7145   [ #  #  #  # ]:          0 :     Py_VISIT(self->readline);
        7146   [ #  #  #  # ]:          0 :     Py_VISIT(self->readinto);
        7147   [ #  #  #  # ]:          0 :     Py_VISIT(self->read);
        7148   [ #  #  #  # ]:          0 :     Py_VISIT(self->peek);
        7149   [ #  #  #  # ]:          0 :     Py_VISIT(self->stack);
        7150   [ #  #  #  # ]:          0 :     Py_VISIT(self->pers_func);
        7151   [ #  #  #  # ]:          0 :     Py_VISIT(self->buffers);
        7152                 :          0 :     return 0;
        7153                 :            : }
        7154                 :            :
        7155                 :            : static int
        7156                 :          0 : Unpickler_clear(UnpicklerObject *self)
        7157                 :            : {
        7158         [ #  # ]:          0 :     Py_CLEAR(self->readline);
        7159         [ #  # ]:          0 :     Py_CLEAR(self->readinto);
        7160         [ #  # ]:          0 :     Py_CLEAR(self->read);
        7161         [ #  # ]:          0 :     Py_CLEAR(self->peek);
        7162         [ #  # ]:          0 :     Py_CLEAR(self->stack);
        7163         [ #  # ]:          0 :     Py_CLEAR(self->pers_func);
        7164         [ #  # ]:          0 :     Py_CLEAR(self->buffers);
        7165         [ #  # ]:          0 :     if (self->buffer.buf != NULL) {
        7166                 :          0 :         PyBuffer_Release(&self->buffer);
        7167                 :          0 :         self->buffer.buf = NULL;
        7168                 :            :     }
        7169                 :            :
        7170                 :          0 :     _Unpickler_MemoCleanup(self);
        7171                 :          0 :     PyMem_Free(self->marks);
        7172                 :          0 :     self->marks = NULL;
        7173                 :          0 :     PyMem_Free(self->input_line);
        7174                 :          0 :     self->input_line = NULL;
        7175                 :          0 :     PyMem_Free(self->encoding);
        7176                 :          0 :     self->encoding = NULL;
        7177                 :          0 :     PyMem_Free(self->errors);
        7178                 :          0 :     self->errors = NULL;
        7179                 :            :
        7180                 :          0 :     return 0;
        7181                 :            : }
        7182                 :            :
        7183                 :            : /*[clinic input]
        7184                 :            :
        7185                 :            : _pickle.Unpickler.__init__
        7186                 :            :
        7187                 :            :   file: object
        7188                 :            :   *
        7189                 :            :   fix_imports: bool = True
        7190                 :            :   encoding: str = 'ASCII'
        7191                 :            :   errors: str = 'strict'
        7192                 :            :   buffers: object(c_default="NULL") = ()
        7193                 :            :
        7194                 :            : This takes a binary file for reading a pickle data stream.
        7195                 :            :
        7196                 :            : The protocol version of the pickle is detected automatically, so no
        7197                 :            : protocol argument is needed.  Bytes past the pickled object's
        7198                 :            : representation are ignored.
        7199                 :            :
        7200                 :            : The argument *file* must have two methods, a read() method that takes
        7201                 :            : an integer argument, and a readline() method that requires no
        7202                 :            : arguments.  Both methods should return bytes.  Thus *file* can be a
        7203                 :            : binary file object opened for reading, an io.BytesIO object, or any
        7204                 :            : other custom object that meets this interface.
        7205                 :            :
        7206                 :            : Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
        7207                 :            : which are used to control compatibility support for pickle stream
        7208                 :            : generated by Python 2.  If *fix_imports* is True, pickle will try to
        7209                 :            : map the old Python 2 names to the new names used in Python 3.  The
        7210                 :            : *encoding* and *errors* tell pickle how to decode 8-bit string
        7211                 :            : instances pickled by Python 2; these default to 'ASCII' and 'strict',
        7212                 :            : respectively.  The *encoding* can be 'bytes' to read these 8-bit
        7213                 :            : string instances as bytes objects.
        7214                 :            : [clinic start generated code]*/
        7215                 :            :
        7216                 :            : static int
        7217                 :          0 : _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
        7218                 :            :                                 int fix_imports, const char *encoding,
        7219                 :            :                                 const char *errors, PyObject *buffers)
        7220                 :            : /*[clinic end generated code: output=09f0192649ea3f85 input=ca4c1faea9553121]*/
        7221                 :            : {
        7222                 :            :     /* In case of multiple __init__() calls, clear previous content. */
        7223         [ #  # ]:          0 :     if (self->read != NULL)
        7224                 :          0 :         (void)Unpickler_clear(self);
        7225                 :            :
        7226         [ #  # ]:          0 :     if (_Unpickler_SetInputStream(self, file) < 0)
        7227                 :          0 :         return -1;
        7228                 :            :
        7229         [ #  # ]:          0 :     if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
        7230                 :          0 :         return -1;
        7231                 :            :
        7232         [ #  # ]:          0 :     if (_Unpickler_SetBuffers(self, buffers) < 0)
        7233                 :          0 :         return -1;
        7234                 :            :
        7235                 :          0 :     self->fix_imports = fix_imports;
        7236                 :            :
        7237         [ #  # ]:          0 :     if (init_method_ref((PyObject *)self, &_Py_ID(persistent_load),
        7238                 :            :                         &self->pers_func, &self->pers_func_self) < 0)
        7239                 :            :     {
        7240                 :          0 :         return -1;
        7241                 :            :     }
        7242                 :            :
        7243                 :          0 :     self->stack = (Pdata *)Pdata_New();
        7244         [ #  # ]:          0 :     if (self->stack == NULL)
        7245                 :          0 :         return -1;
        7246                 :            :
        7247                 :          0 :     self->memo_size = 32;
        7248                 :          0 :     self->memo = _Unpickler_NewMemo(self->memo_size);
        7249         [ #  # ]:          0 :     if (self->memo == NULL)
        7250                 :          0 :         return -1;
        7251                 :            :
        7252                 :          0 :     self->proto = 0;
        7253                 :            :
        7254                 :          0 :     return 0;
        7255                 :            : }
        7256                 :            :
        7257                 :            :
        7258                 :            : /* Define a proxy object for the Unpickler's internal memo object. This is to
        7259                 :            :  * avoid breaking code like:
        7260                 :            :  *  unpickler.memo.clear()
        7261                 :            :  * and
        7262                 :            :  *  unpickler.memo = saved_memo
        7263                 :            :  * Is this a good idea? Not really, but we don't want to break code that uses
        7264                 :            :  * it. Note that we don't implement the entire mapping API here. This is
        7265                 :            :  * intentional, as these should be treated as black-box implementation details.
        7266                 :            :  *
        7267                 :            :  * We do, however, have to implement pickling/unpickling support because of
        7268                 :            :  * real-world code like cvs2svn.
        7269                 :            :  */
        7270                 :            :
        7271                 :            : /*[clinic input]
        7272                 :            : _pickle.UnpicklerMemoProxy.clear
        7273                 :            :
        7274                 :            : Remove all items from memo.
        7275                 :            : [clinic start generated code]*/
        7276                 :            :
        7277                 :            : static PyObject *
        7278                 :          0 : _pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self)
        7279                 :            : /*[clinic end generated code: output=d20cd43f4ba1fb1f input=b1df7c52e7afd9bd]*/
        7280                 :            : {
        7281                 :          0 :     _Unpickler_MemoCleanup(self->unpickler);
        7282                 :          0 :     self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size);
        7283         [ #  # ]:          0 :     if (self->unpickler->memo == NULL)
        7284                 :          0 :         return NULL;
        7285                 :          0 :     Py_RETURN_NONE;
        7286                 :            : }
        7287                 :            :
        7288                 :            : /*[clinic input]
        7289                 :            : _pickle.UnpicklerMemoProxy.copy
        7290                 :            :
        7291                 :            : Copy the memo to a new object.
        7292                 :            : [clinic start generated code]*/
        7293                 :            :
        7294                 :            : static PyObject *
        7295                 :          0 : _pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self)
        7296                 :            : /*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
        7297                 :            : {
        7298                 :            :     size_t i;
        7299                 :          0 :     PyObject *new_memo = PyDict_New();
        7300         [ #  # ]:          0 :     if (new_memo == NULL)
        7301                 :          0 :         return NULL;
        7302                 :            :
        7303         [ #  # ]:          0 :     for (i = 0; i < self->unpickler->memo_size; i++) {
        7304                 :            :         int status;
        7305                 :            :         PyObject *key, *value;
        7306                 :            :
        7307                 :          0 :         value = self->unpickler->memo[i];
        7308         [ #  # ]:          0 :         if (value == NULL)
        7309                 :          0 :             continue;
        7310                 :            :
        7311                 :          0 :         key = PyLong_FromSsize_t(i);
        7312         [ #  # ]:          0 :         if (key == NULL)
        7313                 :          0 :             goto error;
        7314                 :          0 :         status = PyDict_SetItem(new_memo, key, value);
        7315                 :          0 :         Py_DECREF(key);
        7316         [ #  # ]:          0 :         if (status < 0)
        7317                 :          0 :             goto error;
        7318                 :            :     }
        7319                 :          0 :     return new_memo;
        7320                 :            :
        7321                 :          0 : error:
        7322                 :          0 :     Py_DECREF(new_memo);
        7323                 :          0 :     return NULL;
        7324                 :            : }
        7325                 :            :
        7326                 :            : /*[clinic input]
        7327                 :            : _pickle.UnpicklerMemoProxy.__reduce__
        7328                 :            :
        7329                 :            : Implement pickling support.
        7330                 :            : [clinic start generated code]*/
        7331                 :            :
        7332                 :            : static PyObject *
        7333                 :          0 : _pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self)
        7334                 :            : /*[clinic end generated code: output=6da34ac048d94cca input=6920862413407199]*/
        7335                 :            : {
        7336                 :            :     PyObject *reduce_value;
        7337                 :            :     PyObject *constructor_args;
        7338                 :          0 :     PyObject *contents = _pickle_UnpicklerMemoProxy_copy_impl(self);
        7339         [ #  # ]:          0 :     if (contents == NULL)
        7340                 :          0 :         return NULL;
        7341                 :            :
        7342                 :          0 :     reduce_value = PyTuple_New(2);
        7343         [ #  # ]:          0 :     if (reduce_value == NULL) {
        7344                 :          0 :         Py_DECREF(contents);
        7345                 :          0 :         return NULL;
        7346                 :            :     }
        7347                 :          0 :     constructor_args = PyTuple_New(1);
        7348         [ #  # ]:          0 :     if (constructor_args == NULL) {
        7349                 :          0 :         Py_DECREF(contents);
        7350                 :          0 :         Py_DECREF(reduce_value);
        7351                 :          0 :         return NULL;
        7352                 :            :     }
        7353                 :          0 :     PyTuple_SET_ITEM(constructor_args, 0, contents);
        7354                 :          0 :     PyTuple_SET_ITEM(reduce_value, 0, Py_NewRef(&PyDict_Type));
        7355                 :          0 :     PyTuple_SET_ITEM(reduce_value, 1, constructor_args);
        7356                 :          0 :     return reduce_value;
        7357                 :            : }
        7358                 :            :
        7359                 :            : static PyMethodDef unpicklerproxy_methods[] = {
        7360                 :            :     _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF
        7361                 :            :     _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF
        7362                 :            :     _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF
        7363                 :            :     {NULL, NULL}    /* sentinel */
        7364                 :            : };
        7365                 :            :
        7366                 :            : static void
        7367                 :          0 : UnpicklerMemoProxy_dealloc(UnpicklerMemoProxyObject *self)
        7368                 :            : {
        7369                 :          0 :     PyObject_GC_UnTrack(self);
        7370                 :          0 :     Py_XDECREF(self->unpickler);
        7371                 :          0 :     PyObject_GC_Del((PyObject *)self);
        7372                 :          0 : }
        7373                 :            :
        7374                 :            : static int
        7375                 :          0 : UnpicklerMemoProxy_traverse(UnpicklerMemoProxyObject *self,
        7376                 :            :                             visitproc visit, void *arg)
        7377                 :            : {
        7378   [ #  #  #  # ]:          0 :     Py_VISIT(self->unpickler);
        7379                 :          0 :     return 0;
        7380                 :            : }
        7381                 :            :
        7382                 :            : static int
        7383                 :          0 : UnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self)
        7384                 :            : {
        7385         [ #  # ]:          0 :     Py_CLEAR(self->unpickler);
        7386                 :          0 :     return 0;
        7387                 :            : }
        7388                 :            :
        7389                 :            : static PyTypeObject UnpicklerMemoProxyType = {
        7390                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        7391                 :            :     "_pickle.UnpicklerMemoProxy",               /*tp_name*/
        7392                 :            :     sizeof(UnpicklerMemoProxyObject),           /*tp_basicsize*/
        7393                 :            :     0,
        7394                 :            :     (destructor)UnpicklerMemoProxy_dealloc,     /* tp_dealloc */
        7395                 :            :     0,                                          /* tp_vectorcall_offset */
        7396                 :            :     0,                                          /* tp_getattr */
        7397                 :            :     0,                                          /* tp_setattr */
        7398                 :            :     0,                                          /* tp_as_async */
        7399                 :            :     0,                                          /* tp_repr */
        7400                 :            :     0,                                          /* tp_as_number */
        7401                 :            :     0,                                          /* tp_as_sequence */
        7402                 :            :     0,                                          /* tp_as_mapping */
        7403                 :            :     PyObject_HashNotImplemented,                /* tp_hash */
        7404                 :            :     0,                                          /* tp_call */
        7405                 :            :     0,                                          /* tp_str */
        7406                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
        7407                 :            :     PyObject_GenericSetAttr,                    /* tp_setattro */
        7408                 :            :     0,                                          /* tp_as_buffer */
        7409                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
        7410                 :            :     0,                                          /* tp_doc */
        7411                 :            :     (traverseproc)UnpicklerMemoProxy_traverse,  /* tp_traverse */
        7412                 :            :     (inquiry)UnpicklerMemoProxy_clear,          /* tp_clear */
        7413                 :            :     0,                                          /* tp_richcompare */
        7414                 :            :     0,                                          /* tp_weaklistoffset */
        7415                 :            :     0,                                          /* tp_iter */
        7416                 :            :     0,                                          /* tp_iternext */
        7417                 :            :     unpicklerproxy_methods,                     /* tp_methods */
        7418                 :            : };
        7419                 :            :
        7420                 :            : static PyObject *
        7421                 :          0 : UnpicklerMemoProxy_New(UnpicklerObject *unpickler)
        7422                 :            : {
        7423                 :            :     UnpicklerMemoProxyObject *self;
        7424                 :            :
        7425                 :          0 :     self = PyObject_GC_New(UnpicklerMemoProxyObject,
        7426                 :            :                            &UnpicklerMemoProxyType);
        7427         [ #  # ]:          0 :     if (self == NULL)
        7428                 :          0 :         return NULL;
        7429                 :          0 :     self->unpickler = (UnpicklerObject*)Py_NewRef(unpickler);
        7430                 :          0 :     PyObject_GC_Track(self);
        7431                 :          0 :     return (PyObject *)self;
        7432                 :            : }
        7433                 :            :
        7434                 :            : /*****************************************************************************/
        7435                 :            :
        7436                 :            :
        7437                 :            : static PyObject *
        7438                 :          0 : Unpickler_get_memo(UnpicklerObject *self, void *Py_UNUSED(ignored))
        7439                 :            : {
        7440                 :          0 :     return UnpicklerMemoProxy_New(self);
        7441                 :            : }
        7442                 :            :
        7443                 :            : static int
        7444                 :          0 : Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
        7445                 :            : {
        7446                 :            :     PyObject **new_memo;
        7447                 :          0 :     size_t new_memo_size = 0;
        7448                 :            :
        7449         [ #  # ]:          0 :     if (obj == NULL) {
        7450                 :          0 :         PyErr_SetString(PyExc_TypeError,
        7451                 :            :                         "attribute deletion is not supported");
        7452                 :          0 :         return -1;
        7453                 :            :     }
        7454                 :            :
        7455         [ #  # ]:          0 :     if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) {
        7456                 :          0 :         UnpicklerObject *unpickler =
        7457                 :            :             ((UnpicklerMemoProxyObject *)obj)->unpickler;
        7458                 :            :
        7459                 :          0 :         new_memo_size = unpickler->memo_size;
        7460                 :          0 :         new_memo = _Unpickler_NewMemo(new_memo_size);
        7461         [ #  # ]:          0 :         if (new_memo == NULL)
        7462                 :          0 :             return -1;
        7463                 :            :
        7464         [ #  # ]:          0 :         for (size_t i = 0; i < new_memo_size; i++) {
        7465                 :          0 :             new_memo[i] = Py_XNewRef(unpickler->memo[i]);
        7466                 :            :         }
        7467                 :            :     }
        7468         [ #  # ]:          0 :     else if (PyDict_Check(obj)) {
        7469                 :          0 :         Py_ssize_t i = 0;
        7470                 :            :         PyObject *key, *value;
        7471                 :            :
        7472                 :          0 :         new_memo_size = PyDict_GET_SIZE(obj);
        7473                 :          0 :         new_memo = _Unpickler_NewMemo(new_memo_size);
        7474         [ #  # ]:          0 :         if (new_memo == NULL)
        7475                 :          0 :             return -1;
        7476                 :            :
        7477         [ #  # ]:          0 :         while (PyDict_Next(obj, &i, &key, &value)) {
        7478                 :            :             Py_ssize_t idx;
        7479         [ #  # ]:          0 :             if (!PyLong_Check(key)) {
        7480                 :          0 :                 PyErr_SetString(PyExc_TypeError,
        7481                 :            :                                 "memo key must be integers");
        7482                 :          0 :                 goto error;
        7483                 :            :             }
        7484                 :          0 :             idx = PyLong_AsSsize_t(key);
        7485   [ #  #  #  # ]:          0 :             if (idx == -1 && PyErr_Occurred())
        7486                 :          0 :                 goto error;
        7487         [ #  # ]:          0 :             if (idx < 0) {
        7488                 :          0 :                 PyErr_SetString(PyExc_ValueError,
        7489                 :            :                                 "memo key must be positive integers.");
        7490                 :          0 :                 goto error;
        7491                 :            :             }
        7492         [ #  # ]:          0 :             if (_Unpickler_MemoPut(self, idx, value) < 0)
        7493                 :          0 :                 goto error;
        7494                 :            :         }
        7495                 :            :     }
        7496                 :            :     else {
        7497                 :          0 :         PyErr_Format(PyExc_TypeError,
        7498                 :            :                      "'memo' attribute must be an UnpicklerMemoProxy object "
        7499                 :          0 :                      "or dict, not %.200s", Py_TYPE(obj)->tp_name);
        7500                 :          0 :         return -1;
        7501                 :            :     }
        7502                 :            :
        7503                 :          0 :     _Unpickler_MemoCleanup(self);
        7504                 :          0 :     self->memo_size = new_memo_size;
        7505                 :          0 :     self->memo = new_memo;
        7506                 :            :
        7507                 :          0 :     return 0;
        7508                 :            :
        7509                 :          0 :   error:
        7510         [ #  # ]:          0 :     if (new_memo_size) {
        7511         [ #  # ]:          0 :         for (size_t i = new_memo_size - 1; i != SIZE_MAX; i--) {
        7512                 :          0 :             Py_XDECREF(new_memo[i]);
        7513                 :            :         }
        7514                 :          0 :         PyMem_Free(new_memo);
        7515                 :            :     }
        7516                 :          0 :     return -1;
        7517                 :            : }
        7518                 :            :
        7519                 :            : static PyObject *
        7520                 :          0 : Unpickler_get_persload(UnpicklerObject *self, void *Py_UNUSED(ignored))
        7521                 :            : {
        7522         [ #  # ]:          0 :     if (self->pers_func == NULL) {
        7523                 :          0 :         PyErr_SetString(PyExc_AttributeError, "persistent_load");
        7524                 :          0 :         return NULL;
        7525                 :            :     }
        7526                 :          0 :     return reconstruct_method(self->pers_func, self->pers_func_self);
        7527                 :            : }
        7528                 :            :
        7529                 :            : static int
        7530                 :          0 : Unpickler_set_persload(UnpicklerObject *self, PyObject *value, void *Py_UNUSED(ignored))
        7531                 :            : {
        7532         [ #  # ]:          0 :     if (value == NULL) {
        7533                 :          0 :         PyErr_SetString(PyExc_TypeError,
        7534                 :            :                         "attribute deletion is not supported");
        7535                 :          0 :         return -1;
        7536                 :            :     }
        7537         [ #  # ]:          0 :     if (!PyCallable_Check(value)) {
        7538                 :          0 :         PyErr_SetString(PyExc_TypeError,
        7539                 :            :                         "persistent_load must be a callable taking "
        7540                 :            :                         "one argument");
        7541                 :          0 :         return -1;
        7542                 :            :     }
        7543                 :            :
        7544                 :          0 :     self->pers_func_self = NULL;
        7545                 :          0 :     Py_XSETREF(self->pers_func, Py_NewRef(value));
        7546                 :            :
        7547                 :          0 :     return 0;
        7548                 :            : }
        7549                 :            :
        7550                 :            : static PyGetSetDef Unpickler_getsets[] = {
        7551                 :            :     {"memo", (getter)Unpickler_get_memo, (setter)Unpickler_set_memo},
        7552                 :            :     {"persistent_load", (getter)Unpickler_get_persload,
        7553                 :            :                         (setter)Unpickler_set_persload},
        7554                 :            :     {NULL}
        7555                 :            : };
        7556                 :            :
        7557                 :            : static PyTypeObject Unpickler_Type = {
        7558                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
        7559                 :            :     "_pickle.Unpickler",                /*tp_name*/
        7560                 :            :     sizeof(UnpicklerObject),            /*tp_basicsize*/
        7561                 :            :     0,                                  /*tp_itemsize*/
        7562                 :            :     (destructor)Unpickler_dealloc,      /*tp_dealloc*/
        7563                 :            :     0,                                  /*tp_vectorcall_offset*/
        7564                 :            :     0,                                  /*tp_getattr*/
        7565                 :            :     0,                                  /*tp_setattr*/
        7566                 :            :     0,                                  /*tp_as_async*/
        7567                 :            :     0,                                  /*tp_repr*/
        7568                 :            :     0,                                  /*tp_as_number*/
        7569                 :            :     0,                                  /*tp_as_sequence*/
        7570                 :            :     0,                                  /*tp_as_mapping*/
        7571                 :            :     0,                                  /*tp_hash*/
        7572                 :            :     0,                                  /*tp_call*/
        7573                 :            :     0,                                  /*tp_str*/
        7574                 :            :     0,                                  /*tp_getattro*/
        7575                 :            :     0,                                  /*tp_setattro*/
        7576                 :            :     0,                                  /*tp_as_buffer*/
        7577                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
        7578                 :            :     _pickle_Unpickler___init____doc__,  /*tp_doc*/
        7579                 :            :     (traverseproc)Unpickler_traverse,   /*tp_traverse*/
        7580                 :            :     (inquiry)Unpickler_clear,           /*tp_clear*/
        7581                 :            :     0,                                  /*tp_richcompare*/
        7582                 :            :     0,                                  /*tp_weaklistoffset*/
        7583                 :            :     0,                                  /*tp_iter*/
        7584                 :            :     0,                                  /*tp_iternext*/
        7585                 :            :     Unpickler_methods,                  /*tp_methods*/
        7586                 :            :     0,                                  /*tp_members*/
        7587                 :            :     Unpickler_getsets,                  /*tp_getset*/
        7588                 :            :     0,                                  /*tp_base*/
        7589                 :            :     0,                                  /*tp_dict*/
        7590                 :            :     0,                                  /*tp_descr_get*/
        7591                 :            :     0,                                  /*tp_descr_set*/
        7592                 :            :     0,                                  /*tp_dictoffset*/
        7593                 :            :     _pickle_Unpickler___init__,         /*tp_init*/
        7594                 :            :     PyType_GenericAlloc,                /*tp_alloc*/
        7595                 :            :     PyType_GenericNew,                  /*tp_new*/
        7596                 :            :     PyObject_GC_Del,                    /*tp_free*/
        7597                 :            :     0,                                  /*tp_is_gc*/
        7598                 :            : };
        7599                 :            :
        7600                 :            : /*[clinic input]
        7601                 :            :
        7602                 :            : _pickle.dump
        7603                 :            :
        7604                 :            :   obj: object
        7605                 :            :   file: object
        7606                 :            :   protocol: object = None
        7607                 :            :   *
        7608                 :            :   fix_imports: bool = True
        7609                 :            :   buffer_callback: object = None
        7610                 :            :
        7611                 :            : Write a pickled representation of obj to the open file object file.
        7612                 :            :
        7613                 :            : This is equivalent to ``Pickler(file, protocol).dump(obj)``, but may
        7614                 :            : be more efficient.
        7615                 :            :
        7616                 :            : The optional *protocol* argument tells the pickler to use the given
        7617                 :            : protocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
        7618                 :            : protocol is 4. It was introduced in Python 3.4, and is incompatible
        7619                 :            : with previous versions.
        7620                 :            :
        7621                 :            : Specifying a negative protocol version selects the highest protocol
        7622                 :            : version supported.  The higher the protocol used, the more recent the
        7623                 :            : version of Python needed to read the pickle produced.
        7624                 :            :
        7625                 :            : The *file* argument must have a write() method that accepts a single
        7626                 :            : bytes argument.  It can thus be a file object opened for binary
        7627                 :            : writing, an io.BytesIO instance, or any other custom object that meets
        7628                 :            : this interface.
        7629                 :            :
        7630                 :            : If *fix_imports* is True and protocol is less than 3, pickle will try
        7631                 :            : to map the new Python 3 names to the old module names used in Python
        7632                 :            : 2, so that the pickle data stream is readable with Python 2.
        7633                 :            :
        7634                 :            : If *buffer_callback* is None (the default), buffer views are serialized
        7635                 :            : into *file* as part of the pickle stream.  It is an error if
        7636                 :            : *buffer_callback* is not None and *protocol* is None or smaller than 5.
        7637                 :            :
        7638                 :            : [clinic start generated code]*/
        7639                 :            :
        7640                 :            : static PyObject *
        7641                 :          0 : _pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file,
        7642                 :            :                   PyObject *protocol, int fix_imports,
        7643                 :            :                   PyObject *buffer_callback)
        7644                 :            : /*[clinic end generated code: output=706186dba996490c input=5ed6653da99cd97c]*/
        7645                 :            : {
        7646                 :          0 :     PicklerObject *pickler = _Pickler_New();
        7647                 :            :
        7648         [ #  # ]:          0 :     if (pickler == NULL)
        7649                 :          0 :         return NULL;
        7650                 :            :
        7651         [ #  # ]:          0 :     if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
        7652                 :          0 :         goto error;
        7653                 :            :
        7654         [ #  # ]:          0 :     if (_Pickler_SetOutputStream(pickler, file) < 0)
        7655                 :          0 :         goto error;
        7656                 :            :
        7657         [ #  # ]:          0 :     if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
        7658                 :          0 :         goto error;
        7659                 :            :
        7660         [ #  # ]:          0 :     if (dump(pickler, obj) < 0)
        7661                 :          0 :         goto error;
        7662                 :            :
        7663         [ #  # ]:          0 :     if (_Pickler_FlushToFile(pickler) < 0)
        7664                 :          0 :         goto error;
        7665                 :            :
        7666                 :          0 :     Py_DECREF(pickler);
        7667                 :          0 :     Py_RETURN_NONE;
        7668                 :            :
        7669                 :          0 :   error:
        7670                 :          0 :     Py_XDECREF(pickler);
        7671                 :          0 :     return NULL;
        7672                 :            : }
        7673                 :            :
        7674                 :            : /*[clinic input]
        7675                 :            :
        7676                 :            : _pickle.dumps
        7677                 :            :
        7678                 :            :   obj: object
        7679                 :            :   protocol: object = None
        7680                 :            :   *
        7681                 :            :   fix_imports: bool = True
        7682                 :            :   buffer_callback: object = None
        7683                 :            :
        7684                 :            : Return the pickled representation of the object as a bytes object.
        7685                 :            :
        7686                 :            : The optional *protocol* argument tells the pickler to use the given
        7687                 :            : protocol; supported protocols are 0, 1, 2, 3, 4 and 5.  The default
        7688                 :            : protocol is 4. It was introduced in Python 3.4, and is incompatible
        7689                 :            : with previous versions.
        7690                 :            :
        7691                 :            : Specifying a negative protocol version selects the highest protocol
        7692                 :            : version supported.  The higher the protocol used, the more recent the
        7693                 :            : version of Python needed to read the pickle produced.
        7694                 :            :
        7695                 :            : If *fix_imports* is True and *protocol* is less than 3, pickle will
        7696                 :            : try to map the new Python 3 names to the old module names used in
        7697                 :            : Python 2, so that the pickle data stream is readable with Python 2.
        7698                 :            :
        7699                 :            : If *buffer_callback* is None (the default), buffer views are serialized
        7700                 :            : into *file* as part of the pickle stream.  It is an error if
        7701                 :            : *buffer_callback* is not None and *protocol* is None or smaller than 5.
        7702                 :            :
        7703                 :            : [clinic start generated code]*/
        7704                 :            :
        7705                 :            : static PyObject *
        7706                 :          0 : _pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol,
        7707                 :            :                    int fix_imports, PyObject *buffer_callback)
        7708                 :            : /*[clinic end generated code: output=fbab0093a5580fdf input=e543272436c6f987]*/
        7709                 :            : {
        7710                 :            :     PyObject *result;
        7711                 :          0 :     PicklerObject *pickler = _Pickler_New();
        7712                 :            :
        7713         [ #  # ]:          0 :     if (pickler == NULL)
        7714                 :          0 :         return NULL;
        7715                 :            :
        7716         [ #  # ]:          0 :     if (_Pickler_SetProtocol(pickler, protocol, fix_imports) < 0)
        7717                 :          0 :         goto error;
        7718                 :            :
        7719         [ #  # ]:          0 :     if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
        7720                 :          0 :         goto error;
        7721                 :            :
        7722         [ #  # ]:          0 :     if (dump(pickler, obj) < 0)
        7723                 :          0 :         goto error;
        7724                 :            :
        7725                 :          0 :     result = _Pickler_GetString(pickler);
        7726                 :          0 :     Py_DECREF(pickler);
        7727                 :          0 :     return result;
        7728                 :            :
        7729                 :          0 :   error:
        7730                 :          0 :     Py_XDECREF(pickler);
        7731                 :          0 :     return NULL;
        7732                 :            : }
        7733                 :            :
        7734                 :            : /*[clinic input]
        7735                 :            :
        7736                 :            : _pickle.load
        7737                 :            :
        7738                 :            :   file: object
        7739                 :            :   *
        7740                 :            :   fix_imports: bool = True
        7741                 :            :   encoding: str = 'ASCII'
        7742                 :            :   errors: str = 'strict'
        7743                 :            :   buffers: object(c_default="NULL") = ()
        7744                 :            :
        7745                 :            : Read and return an object from the pickle data stored in a file.
        7746                 :            :
        7747                 :            : This is equivalent to ``Unpickler(file).load()``, but may be more
        7748                 :            : efficient.
        7749                 :            :
        7750                 :            : The protocol version of the pickle is detected automatically, so no
        7751                 :            : protocol argument is needed.  Bytes past the pickled object's
        7752                 :            : representation are ignored.
        7753                 :            :
        7754                 :            : The argument *file* must have two methods, a read() method that takes
        7755                 :            : an integer argument, and a readline() method that requires no
        7756                 :            : arguments.  Both methods should return bytes.  Thus *file* can be a
        7757                 :            : binary file object opened for reading, an io.BytesIO object, or any
        7758                 :            : other custom object that meets this interface.
        7759                 :            :
        7760                 :            : Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
        7761                 :            : which are used to control compatibility support for pickle stream
        7762                 :            : generated by Python 2.  If *fix_imports* is True, pickle will try to
        7763                 :            : map the old Python 2 names to the new names used in Python 3.  The
        7764                 :            : *encoding* and *errors* tell pickle how to decode 8-bit string
        7765                 :            : instances pickled by Python 2; these default to 'ASCII' and 'strict',
        7766                 :            : respectively.  The *encoding* can be 'bytes' to read these 8-bit
        7767                 :            : string instances as bytes objects.
        7768                 :            : [clinic start generated code]*/
        7769                 :            :
        7770                 :            : static PyObject *
        7771                 :          0 : _pickle_load_impl(PyObject *module, PyObject *file, int fix_imports,
        7772                 :            :                   const char *encoding, const char *errors,
        7773                 :            :                   PyObject *buffers)
        7774                 :            : /*[clinic end generated code: output=250452d141c23e76 input=46c7c31c92f4f371]*/
        7775                 :            : {
        7776                 :            :     PyObject *result;
        7777                 :          0 :     UnpicklerObject *unpickler = _Unpickler_New();
        7778                 :            :
        7779         [ #  # ]:          0 :     if (unpickler == NULL)
        7780                 :          0 :         return NULL;
        7781                 :            :
        7782         [ #  # ]:          0 :     if (_Unpickler_SetInputStream(unpickler, file) < 0)
        7783                 :          0 :         goto error;
        7784                 :            :
        7785         [ #  # ]:          0 :     if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
        7786                 :          0 :         goto error;
        7787                 :            :
        7788         [ #  # ]:          0 :     if (_Unpickler_SetBuffers(unpickler, buffers) < 0)
        7789                 :          0 :         goto error;
        7790                 :            :
        7791                 :          0 :     unpickler->fix_imports = fix_imports;
        7792                 :            :
        7793                 :          0 :     result = load(unpickler);
        7794                 :          0 :     Py_DECREF(unpickler);
        7795                 :          0 :     return result;
        7796                 :            :
        7797                 :          0 :   error:
        7798                 :          0 :     Py_XDECREF(unpickler);
        7799                 :          0 :     return NULL;
        7800                 :            : }
        7801                 :            :
        7802                 :            : /*[clinic input]
        7803                 :            :
        7804                 :            : _pickle.loads
        7805                 :            :
        7806                 :            :   data: object
        7807                 :            :   /
        7808                 :            :   *
        7809                 :            :   fix_imports: bool = True
        7810                 :            :   encoding: str = 'ASCII'
        7811                 :            :   errors: str = 'strict'
        7812                 :            :   buffers: object(c_default="NULL") = ()
        7813                 :            :
        7814                 :            : Read and return an object from the given pickle data.
        7815                 :            :
        7816                 :            : The protocol version of the pickle is detected automatically, so no
        7817                 :            : protocol argument is needed.  Bytes past the pickled object's
        7818                 :            : representation are ignored.
        7819                 :            :
        7820                 :            : Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
        7821                 :            : which are used to control compatibility support for pickle stream
        7822                 :            : generated by Python 2.  If *fix_imports* is True, pickle will try to
        7823                 :            : map the old Python 2 names to the new names used in Python 3.  The
        7824                 :            : *encoding* and *errors* tell pickle how to decode 8-bit string
        7825                 :            : instances pickled by Python 2; these default to 'ASCII' and 'strict',
        7826                 :            : respectively.  The *encoding* can be 'bytes' to read these 8-bit
        7827                 :            : string instances as bytes objects.
        7828                 :            : [clinic start generated code]*/
        7829                 :            :
        7830                 :            : static PyObject *
        7831                 :          0 : _pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports,
        7832                 :            :                    const char *encoding, const char *errors,
        7833                 :            :                    PyObject *buffers)
        7834                 :            : /*[clinic end generated code: output=82ac1e6b588e6d02 input=b3615540d0535087]*/
        7835                 :            : {
        7836                 :            :     PyObject *result;
        7837                 :          0 :     UnpicklerObject *unpickler = _Unpickler_New();
        7838                 :            :
        7839         [ #  # ]:          0 :     if (unpickler == NULL)
        7840                 :          0 :         return NULL;
        7841                 :            :
        7842         [ #  # ]:          0 :     if (_Unpickler_SetStringInput(unpickler, data) < 0)
        7843                 :          0 :         goto error;
        7844                 :            :
        7845         [ #  # ]:          0 :     if (_Unpickler_SetInputEncoding(unpickler, encoding, errors) < 0)
        7846                 :          0 :         goto error;
        7847                 :            :
        7848         [ #  # ]:          0 :     if (_Unpickler_SetBuffers(unpickler, buffers) < 0)
        7849                 :          0 :         goto error;
        7850                 :            :
        7851                 :          0 :     unpickler->fix_imports = fix_imports;
        7852                 :            :
        7853                 :          0 :     result = load(unpickler);
        7854                 :          0 :     Py_DECREF(unpickler);
        7855                 :          0 :     return result;
        7856                 :            :
        7857                 :          0 :   error:
        7858                 :          0 :     Py_XDECREF(unpickler);
        7859                 :          0 :     return NULL;
        7860                 :            : }
        7861                 :            :
        7862                 :            : static struct PyMethodDef pickle_methods[] = {
        7863                 :            :     _PICKLE_DUMP_METHODDEF
        7864                 :            :     _PICKLE_DUMPS_METHODDEF
        7865                 :            :     _PICKLE_LOAD_METHODDEF
        7866                 :            :     _PICKLE_LOADS_METHODDEF
        7867                 :            :     {NULL, NULL} /* sentinel */
        7868                 :            : };
        7869                 :            :
        7870                 :            : static int
        7871                 :          0 : pickle_clear(PyObject *m)
        7872                 :            : {
        7873                 :          0 :     _Pickle_ClearState(_Pickle_GetState(m));
        7874                 :          0 :     return 0;
        7875                 :            : }
        7876                 :            :
        7877                 :            : static void
        7878                 :          1 : pickle_free(PyObject *m)
        7879                 :            : {
        7880                 :          1 :     _Pickle_ClearState(_Pickle_GetState(m));
        7881                 :          1 : }
        7882                 :            :
        7883                 :            : static int
        7884                 :          8 : pickle_traverse(PyObject *m, visitproc visit, void *arg)
        7885                 :            : {
        7886                 :          8 :     PickleState *st = _Pickle_GetState(m);
        7887   [ +  -  -  + ]:          8 :     Py_VISIT(st->PickleError);
        7888   [ +  -  -  + ]:          8 :     Py_VISIT(st->PicklingError);
        7889   [ +  -  -  + ]:          8 :     Py_VISIT(st->UnpicklingError);
        7890   [ +  -  -  + ]:          8 :     Py_VISIT(st->dispatch_table);
        7891   [ +  -  -  + ]:          8 :     Py_VISIT(st->extension_registry);
        7892   [ +  -  -  + ]:          8 :     Py_VISIT(st->extension_cache);
        7893   [ +  -  -  + ]:          8 :     Py_VISIT(st->inverted_registry);
        7894   [ +  -  -  + ]:          8 :     Py_VISIT(st->name_mapping_2to3);
        7895   [ +  -  -  + ]:          8 :     Py_VISIT(st->import_mapping_2to3);
        7896   [ +  -  -  + ]:          8 :     Py_VISIT(st->name_mapping_3to2);
        7897   [ +  -  -  + ]:          8 :     Py_VISIT(st->import_mapping_3to2);
        7898   [ +  -  -  + ]:          8 :     Py_VISIT(st->codecs_encode);
        7899   [ +  -  -  + ]:          8 :     Py_VISIT(st->getattr);
        7900   [ +  -  -  + ]:          8 :     Py_VISIT(st->partial);
        7901                 :          8 :     return 0;
        7902                 :            : }
        7903                 :            :
        7904                 :            : static struct PyModuleDef _picklemodule = {
        7905                 :            :     PyModuleDef_HEAD_INIT,
        7906                 :            :     "_pickle",            /* m_name */
        7907                 :            :     pickle_module_doc,    /* m_doc */
        7908                 :            :     sizeof(PickleState),  /* m_size */
        7909                 :            :     pickle_methods,       /* m_methods */
        7910                 :            :     NULL,                 /* m_reload */
        7911                 :            :     pickle_traverse,      /* m_traverse */
        7912                 :            :     pickle_clear,         /* m_clear */
        7913                 :            :     (freefunc)pickle_free /* m_free */
        7914                 :            : };
        7915                 :            :
        7916                 :            : PyMODINIT_FUNC
        7917                 :          1 : PyInit__pickle(void)
        7918                 :            : {
        7919                 :            :     PyObject *m;
        7920                 :            :     PickleState *st;
        7921                 :            :
        7922                 :          1 :     m = PyState_FindModule(&_picklemodule);
        7923         [ -  + ]:          1 :     if (m) {
        7924                 :          0 :         return Py_NewRef(m);
        7925                 :            :     }
        7926                 :            :
        7927         [ -  + ]:          1 :     if (PyType_Ready(&Pdata_Type) < 0)
        7928                 :          0 :         return NULL;
        7929         [ -  + ]:          1 :     if (PyType_Ready(&PicklerMemoProxyType) < 0)
        7930                 :          0 :         return NULL;
        7931         [ -  + ]:          1 :     if (PyType_Ready(&UnpicklerMemoProxyType) < 0)
        7932                 :          0 :         return NULL;
        7933                 :            :
        7934                 :            :     /* Create the module and add the functions. */
        7935                 :          1 :     m = PyModule_Create(&_picklemodule);
        7936         [ -  + ]:          1 :     if (m == NULL)
        7937                 :          0 :         return NULL;
        7938                 :            :
        7939                 :            :     /* Add types */
        7940         [ -  + ]:          1 :     if (PyModule_AddType(m, &Pickler_Type) < 0) {
        7941                 :          0 :         return NULL;
        7942                 :            :     }
        7943         [ -  + ]:          1 :     if (PyModule_AddType(m, &Unpickler_Type) < 0) {
        7944                 :          0 :         return NULL;
        7945                 :            :     }
        7946         [ -  + ]:          1 :     if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) {
        7947                 :          0 :         return NULL;
        7948                 :            :     }
        7949                 :            :
        7950                 :          1 :     st = _Pickle_GetState(m);
        7951                 :            :
        7952                 :            :     /* Initialize the exceptions. */
        7953                 :          1 :     st->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL);
        7954         [ -  + ]:          1 :     if (st->PickleError == NULL)
        7955                 :          0 :         return NULL;
        7956                 :          1 :     st->PicklingError = \
        7957                 :          1 :         PyErr_NewException("_pickle.PicklingError", st->PickleError, NULL);
        7958         [ -  + ]:          1 :     if (st->PicklingError == NULL)
        7959                 :          0 :         return NULL;
        7960                 :          1 :     st->UnpicklingError = \
        7961                 :          1 :         PyErr_NewException("_pickle.UnpicklingError", st->PickleError, NULL);
        7962         [ -  + ]:          1 :     if (st->UnpicklingError == NULL)
        7963                 :          0 :         return NULL;
        7964                 :            :
        7965         [ -  + ]:          1 :     if (PyModule_AddObjectRef(m, "PickleError", st->PickleError) < 0) {
        7966                 :          0 :         return NULL;
        7967                 :            :     }
        7968         [ -  + ]:          1 :     if (PyModule_AddObjectRef(m, "PicklingError", st->PicklingError) < 0) {
        7969                 :          0 :         return NULL;
        7970                 :            :     }
        7971         [ -  + ]:          1 :     if (PyModule_AddObjectRef(m, "UnpicklingError", st->UnpicklingError) < 0) {
        7972                 :          0 :         return NULL;
        7973                 :            :     }
        7974         [ -  + ]:          1 :     if (_Pickle_InitState(st) < 0)
        7975                 :          0 :         return NULL;
        7976                 :            :
        7977                 :          1 :     return m;
        7978                 :            : }

Generated by: LCOV version 1.14