LCOV - code coverage report
Current view: top level - Modules - _pickle.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 2849 3776 75.5 %
Date: 2022-07-20 13:12:14 Functions: 189 203 93.1 %
Branches: 1775 2671 66.5 %

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

Generated by: LCOV version 1.14