summaryrefslogtreecommitdiffstats
path: root/Modules/_pickle.c
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2023-04-04 10:08:54 (GMT)
committerGitHub <noreply@github.com>2023-04-04 10:08:54 (GMT)
commitc00dcf0e381a090f7e905f887a98bbf63c88af5a (patch)
tree2ad93745bec78762b4559b4c28b63df0fd86514d /Modules/_pickle.c
parent810d365b5eb2cf3043957ca2971f6e7a7cd87d0d (diff)
downloadcpython-c00dcf0e381a090f7e905f887a98bbf63c88af5a.zip
cpython-c00dcf0e381a090f7e905f887a98bbf63c88af5a.tar.gz
cpython-c00dcf0e381a090f7e905f887a98bbf63c88af5a.tar.bz2
gh-103092: Isolate `_pickle` module (#102982)
Co-authored-by: Mohamed Koubaa <koubaa.m@gmail.com> Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r--Modules/_pickle.c1262
1 files changed, 609 insertions, 653 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index a26732a..360c791 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -22,12 +22,12 @@ PyDoc_STRVAR(pickle_module_doc,
/*[clinic input]
module _pickle
-class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
-class _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" "&PicklerMemoProxyType"
-class _pickle.Unpickler "UnpicklerObject *" "&Unpickler_Type"
-class _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" "&UnpicklerMemoProxyType"
+class _pickle.Pickler "PicklerObject *" ""
+class _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" ""
+class _pickle.Unpickler "UnpicklerObject *" ""
+class _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" ""
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b3e113468a58e6c]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b6d7191ab6466cda]*/
/* Bump HIGHEST_PROTOCOL when new opcodes are added to the pickle protocol.
Bump DEFAULT_PROTOCOL only when the oldest still supported version of Python
@@ -192,24 +192,41 @@ typedef struct {
/* functools.partial, used for implementing __newobj_ex__ with protocols
2 and 3 */
PyObject *partial;
+
+ /* Types */
+ PyTypeObject *Pickler_Type;
+ PyTypeObject *Unpickler_Type;
+ PyTypeObject *Pdata_Type;
+ PyTypeObject *PicklerMemoProxyType;
+ PyTypeObject *UnpicklerMemoProxyType;
} PickleState;
/* Forward declaration of the _pickle module definition. */
static struct PyModuleDef _picklemodule;
/* Given a module object, get its per-module state. */
-static PickleState *
+static inline PickleState *
_Pickle_GetState(PyObject *module)
{
- return (PickleState *)_PyModule_GetState(module);
+ void *state = _PyModule_GetState(module);
+ assert(state != NULL);
+ return (PickleState *)state;
+}
+
+static inline PickleState *
+_Pickle_GetStateByClass(PyTypeObject *cls)
+{
+ void *state = _PyType_GetModuleState(cls);
+ assert(state != NULL);
+ return (PickleState *)state;
}
-/* Find the module instance imported in the currently running sub-interpreter
- and get its state. */
-static PickleState *
-_Pickle_GetGlobalState(void)
+static inline PickleState *
+_Pickle_FindStateByType(PyTypeObject *tp)
{
- return _Pickle_GetState(PyState_FindModule(&_picklemodule));
+ PyObject *module = PyType_GetModuleByDef(tp, &_picklemodule);
+ assert(module != NULL);
+ return _Pickle_GetState(module);
}
/* Clear the given pickle module state. */
@@ -230,6 +247,11 @@ _Pickle_ClearState(PickleState *st)
Py_CLEAR(st->codecs_encode);
Py_CLEAR(st->getattr);
Py_CLEAR(st->partial);
+ Py_CLEAR(st->Pickler_Type);
+ Py_CLEAR(st->Unpickler_Type);
+ Py_CLEAR(st->Pdata_Type);
+ Py_CLEAR(st->PicklerMemoProxyType);
+ Py_CLEAR(st->UnpicklerMemoProxyType);
}
/* Initialize the given pickle module state. */
@@ -439,39 +461,58 @@ typedef struct {
Py_ssize_t allocated; /* number of slots in data allocated */
} Pdata;
+static int
+Pdata_traverse(Pdata *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ return 0;
+}
+
static void
Pdata_dealloc(Pdata *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
Py_ssize_t i = Py_SIZE(self);
while (--i >= 0) {
Py_DECREF(self->data[i]);
}
PyMem_Free(self->data);
- PyObject_Free(self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
-static PyTypeObject Pdata_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_pickle.Pdata", /*tp_name*/
- sizeof(Pdata), /*tp_basicsize*/
- sizeof(PyObject *), /*tp_itemsize*/
- (destructor)Pdata_dealloc, /*tp_dealloc*/
+static PyType_Slot pdata_slots[] = {
+ {Py_tp_dealloc, Pdata_dealloc},
+ {Py_tp_traverse, Pdata_traverse},
+ {0, NULL},
+};
+
+static PyType_Spec pdata_spec = {
+ .name = "_pickle.Pdata",
+ .basicsize = sizeof(Pdata),
+ .itemsize = sizeof(PyObject *),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = pdata_slots,
};
static PyObject *
-Pdata_New(void)
+Pdata_New(PickleState *state)
{
Pdata *self;
- if (!(self = PyObject_New(Pdata, &Pdata_Type)))
+ if (!(self = PyObject_GC_New(Pdata, state->Pdata_Type)))
return NULL;
Py_SET_SIZE(self, 0);
self->mark_set = 0;
self->fence = 0;
self->allocated = 8;
self->data = PyMem_Malloc(self->allocated * sizeof(PyObject *));
- if (self->data)
+ if (self->data) {
+ PyObject_GC_Track(self);
return (PyObject *)self;
+ }
Py_DECREF(self);
return PyErr_NoMemory();
}
@@ -522,9 +563,8 @@ Pdata_grow(Pdata *self)
}
static int
-Pdata_stack_underflow(Pdata *self)
+Pdata_stack_underflow(PickleState *st, Pdata *self)
{
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
self->mark_set ?
"unexpected MARK found" :
@@ -537,16 +577,16 @@ Pdata_stack_underflow(Pdata *self)
* is raised and V is set to NULL.
*/
static PyObject *
-Pdata_pop(Pdata *self)
+Pdata_pop(PickleState *state, Pdata *self)
{
if (Py_SIZE(self) <= self->fence) {
- Pdata_stack_underflow(self);
+ Pdata_stack_underflow(state, self);
return NULL;
}
Py_SET_SIZE(self, Py_SIZE(self) - 1);
return self->data[Py_SIZE(self)];
}
-#define PDATA_POP(D, V) do { (V) = Pdata_pop((D)); } while (0)
+#define PDATA_POP(S, D, V) do { (V) = Pdata_pop(S, (D)); } while (0)
static int
Pdata_push(Pdata *self, PyObject *obj)
@@ -569,13 +609,13 @@ Pdata_push(Pdata *self, PyObject *obj)
if (Pdata_push((D), (O)) < 0) return (ER); } while(0)
static PyObject *
-Pdata_poptuple(Pdata *self, Py_ssize_t start)
+Pdata_poptuple(PickleState *state, Pdata *self, Py_ssize_t start)
{
PyObject *tuple;
Py_ssize_t len, i, j;
if (start < self->fence) {
- Pdata_stack_underflow(self);
+ Pdata_stack_underflow(state, self);
return NULL;
}
len = Py_SIZE(self) - start;
@@ -710,10 +750,8 @@ typedef struct {
} UnpicklerMemoProxyObject;
/* Forward declarations */
-static int save(PicklerObject *, PyObject *, int);
-static int save_reduce(PicklerObject *, PyObject *, PyObject *);
-static PyTypeObject Pickler_Type;
-static PyTypeObject Unpickler_Type;
+static int save(PickleState *state, PicklerObject *, PyObject *, int);
+static int save_reduce(PickleState *, PicklerObject *, PyObject *, PyObject *);
#include "clinic/_pickle.c.h"
@@ -1105,11 +1143,11 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
}
static PicklerObject *
-_Pickler_New(void)
+_Pickler_New(PickleState *st)
{
PicklerObject *self;
- self = PyObject_GC_New(PicklerObject, &Pickler_Type);
+ self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
if (self == NULL)
return NULL;
@@ -1220,9 +1258,8 @@ _Unpickler_SetStringInput(UnpicklerObject *self, PyObject *input)
}
static int
-bad_readline(void)
+bad_readline(PickleState *st)
{
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "pickle data was truncated");
return -1;
}
@@ -1317,13 +1354,12 @@ _Unpickler_ReadFromFile(UnpicklerObject *self, Py_ssize_t n)
/* Don't call it directly: use _Unpickler_Read() */
static Py_ssize_t
-_Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n)
+_Unpickler_ReadImpl(UnpicklerObject *self, PickleState *st, char **s, Py_ssize_t n)
{
Py_ssize_t num_read;
*s = NULL;
if (self->next_read_idx > PY_SSIZE_T_MAX - n) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"read would overflow (invalid bytecode)");
return -1;
@@ -1333,14 +1369,14 @@ _Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n)
assert(self->next_read_idx + n > self->input_len);
if (!self->read)
- return bad_readline();
+ return bad_readline(st);
/* Extend the buffer to satisfy desired size */
num_read = _Unpickler_ReadFromFile(self, n);
if (num_read < 0)
return -1;
if (num_read < n)
- return bad_readline();
+ return bad_readline(st);
*s = self->input_buffer;
self->next_read_idx = n;
return n;
@@ -1355,7 +1391,8 @@ _Unpickler_ReadImpl(UnpicklerObject *self, char **s, Py_ssize_t n)
* _Unpickler_Read() is recommended in most cases.
*/
static Py_ssize_t
-_Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
+_Unpickler_ReadInto(PickleState *state, UnpicklerObject *self, char *buf,
+ Py_ssize_t n)
{
assert(n != READ_WHOLE_LINE);
@@ -1376,7 +1413,7 @@ _Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
/* Read from file */
if (!self->read) {
/* We're unpickling memory, this means the input is truncated */
- return bad_readline();
+ return bad_readline(state);
}
if (_Unpickler_SkipConsumed(self) < 0) {
return -1;
@@ -1403,7 +1440,7 @@ _Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
Py_ssize_t read_size = PyBytes_GET_SIZE(data);
if (read_size < n) {
Py_DECREF(data);
- return bad_readline();
+ return bad_readline(state);
}
memcpy(buf, PyBytes_AS_STRING(data), n);
Py_DECREF(data);
@@ -1430,7 +1467,7 @@ _Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
return -1;
}
if (read_size < n) {
- return bad_readline();
+ return bad_readline(state);
}
return n;
}
@@ -1448,12 +1485,12 @@ _Unpickler_ReadInto(UnpicklerObject *self, char *buf, Py_ssize_t n)
Returns -1 (with an exception set) on failure. On success, return the
number of chars read. */
-#define _Unpickler_Read(self, s, n) \
+#define _Unpickler_Read(self, state, s, n) \
(((n) <= (self)->input_len - (self)->next_read_idx) \
? (*(s) = (self)->input_buffer + (self)->next_read_idx, \
(self)->next_read_idx += (n), \
(n)) \
- : _Unpickler_ReadImpl(self, (s), (n)))
+ : _Unpickler_ReadImpl(self, state, (s), (n)))
static Py_ssize_t
_Unpickler_CopyLine(UnpicklerObject *self, char *line, Py_ssize_t len,
@@ -1477,7 +1514,7 @@ _Unpickler_CopyLine(UnpicklerObject *self, char *line, Py_ssize_t len,
Returns the number of chars read, or -1 on failure. */
static Py_ssize_t
-_Unpickler_Readline(UnpicklerObject *self, char **result)
+_Unpickler_Readline(PickleState *state, UnpicklerObject *self, char **result)
{
Py_ssize_t i, num_read;
@@ -1490,13 +1527,13 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
}
}
if (!self->read)
- return bad_readline();
+ return bad_readline(state);
num_read = _Unpickler_ReadFromFile(self, READ_WHOLE_LINE);
if (num_read < 0)
return -1;
if (num_read == 0 || self->input_buffer[num_read - 1] != '\n')
- return bad_readline();
+ return bad_readline(state);
self->next_read_idx = num_read;
return _Unpickler_CopyLine(self, self->input_buffer, num_read, result);
}
@@ -1586,11 +1623,12 @@ _Unpickler_MemoCleanup(UnpicklerObject *self)
}
static UnpicklerObject *
-_Unpickler_New(void)
+_Unpickler_New(PyObject *module)
{
UnpicklerObject *self;
+ PickleState *st = _Pickle_GetState(module);
- self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type);
+ self = PyObject_GC_New(UnpicklerObject, st->Unpickler_Type);
if (self == NULL)
return NULL;
@@ -1616,7 +1654,7 @@ _Unpickler_New(void)
self->memo_size = 32;
self->memo_len = 0;
self->memo = _Unpickler_NewMemo(self->memo_size);
- self->stack = (Pdata *)Pdata_New();
+ self->stack = (Pdata *)Pdata_New(st);
if (self->memo == NULL || self->stack == NULL) {
Py_DECREF(self);
@@ -1695,7 +1733,7 @@ _Unpickler_SetBuffers(UnpicklerObject *self, PyObject *buffers)
/* Generate a GET opcode for an object stored in the memo. */
static int
-memo_get(PicklerObject *self, PyObject *key)
+memo_get(PickleState *st, PicklerObject *self, PyObject *key)
{
Py_ssize_t *value;
char pdata[30];
@@ -1728,7 +1766,6 @@ memo_get(PicklerObject *self, PyObject *key)
len = 5;
}
else { /* unlikely */
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->PicklingError,
"memo id too large for LONG_BINGET");
return -1;
@@ -1744,7 +1781,7 @@ memo_get(PicklerObject *self, PyObject *key)
/* Store an object in the memo, assign it a new unique ID based on the number
of objects currently stored in the memo and generate a PUT opcode. */
static int
-memo_put(PicklerObject *self, PyObject *obj)
+memo_put(PickleState *st, PicklerObject *self, PyObject *obj)
{
char pdata[30];
Py_ssize_t len;
@@ -1785,7 +1822,6 @@ memo_put(PicklerObject *self, PyObject *obj)
len = 5;
}
else { /* unlikely */
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->PicklingError,
"memo id too large for LONG_BINPUT");
return -1;
@@ -2338,8 +2374,8 @@ _Pickler_write_bytes(PicklerObject *self,
}
static int
-_save_bytes_data(PicklerObject *self, PyObject *obj, const char *data,
- Py_ssize_t size)
+_save_bytes_data(PickleState *st, PicklerObject *self, PyObject *obj,
+ const char *data, Py_ssize_t size)
{
assert(self->proto >= 3);
@@ -2378,7 +2414,7 @@ _save_bytes_data(PicklerObject *self, PyObject *obj, const char *data,
return -1;
}
- if (memo_put(self, obj) < 0) {
+ if (memo_put(st, self, obj) < 0) {
return -1;
}
@@ -2386,7 +2422,7 @@ _save_bytes_data(PicklerObject *self, PyObject *obj, const char *data,
}
static int
-save_bytes(PicklerObject *self, PyObject *obj)
+save_bytes(PickleState *st, PicklerObject *self, PyObject *obj)
{
if (self->proto < 3) {
/* Older pickle protocols do not have an opcode for pickling bytes
@@ -2407,7 +2443,6 @@ save_bytes(PicklerObject *self, PyObject *obj)
reduce_value = Py_BuildValue("(O())", (PyObject*)&PyBytes_Type);
}
else {
- PickleState *st = _Pickle_GetGlobalState();
PyObject *unicode_str =
PyUnicode_DecodeLatin1(PyBytes_AS_STRING(obj),
PyBytes_GET_SIZE(obj),
@@ -2425,19 +2460,19 @@ save_bytes(PicklerObject *self, PyObject *obj)
return -1;
/* save_reduce() will memoize the object automatically. */
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(st, self, reduce_value, obj);
Py_DECREF(reduce_value);
return status;
}
else {
- return _save_bytes_data(self, obj, PyBytes_AS_STRING(obj),
+ return _save_bytes_data(st, self, obj, PyBytes_AS_STRING(obj),
PyBytes_GET_SIZE(obj));
}
}
static int
-_save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data,
- Py_ssize_t size)
+_save_bytearray_data(PickleState *state, PicklerObject *self, PyObject *obj,
+ const char *data, Py_ssize_t size)
{
assert(self->proto >= 5);
@@ -2455,7 +2490,7 @@ _save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data,
return -1;
}
- if (memo_put(self, obj) < 0) {
+ if (memo_put(state, self, obj) < 0) {
return -1;
}
@@ -2463,7 +2498,7 @@ _save_bytearray_data(PicklerObject *self, PyObject *obj, const char *data,
}
static int
-save_bytearray(PicklerObject *self, PyObject *obj)
+save_bytearray(PickleState *state, PicklerObject *self, PyObject *obj)
{
if (self->proto < 5) {
/* Older pickle protocols do not have an opcode for pickling
@@ -2488,21 +2523,21 @@ save_bytearray(PicklerObject *self, PyObject *obj)
return -1;
/* save_reduce() will memoize the object automatically. */
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(state, self, reduce_value, obj);
Py_DECREF(reduce_value);
return status;
}
else {
- return _save_bytearray_data(self, obj, PyByteArray_AS_STRING(obj),
+ return _save_bytearray_data(state, self, obj,
+ PyByteArray_AS_STRING(obj),
PyByteArray_GET_SIZE(obj));
}
}
static int
-save_picklebuffer(PicklerObject *self, PyObject *obj)
+save_picklebuffer(PickleState *st, PicklerObject *self, PyObject *obj)
{
if (self->proto < 5) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->PicklingError,
"PickleBuffer can only pickled with protocol >= 5");
return -1;
@@ -2512,7 +2547,6 @@ save_picklebuffer(PicklerObject *self, PyObject *obj)
return -1;
}
if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->PicklingError,
"PickleBuffer can not be pickled when "
"pointing to a non-contiguous buffer");
@@ -2533,11 +2567,11 @@ save_picklebuffer(PicklerObject *self, PyObject *obj)
if (in_band) {
/* Write data in-band */
if (view->readonly) {
- return _save_bytes_data(self, obj, (const char*) view->buf,
+ return _save_bytes_data(st, self, obj, (const char *)view->buf,
view->len);
}
else {
- return _save_bytearray_data(self, obj, (const char*) view->buf,
+ return _save_bytearray_data(st, self, obj, (const char *)view->buf,
view->len);
}
}
@@ -2692,7 +2726,7 @@ write_unicode_binary(PicklerObject *self, PyObject *obj)
}
static int
-save_unicode(PicklerObject *self, PyObject *obj)
+save_unicode(PickleState *state, PicklerObject *self, PyObject *obj)
{
if (self->bin) {
if (write_unicode_binary(self, obj) < 0)
@@ -2722,7 +2756,7 @@ save_unicode(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, "\n", 1) < 0)
return -1;
}
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
return -1;
return 0;
@@ -2730,7 +2764,8 @@ save_unicode(PicklerObject *self, PyObject *obj)
/* A helper for save_tuple. Push the len elements in tuple t on the stack. */
static int
-store_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len)
+store_tuple_elements(PickleState *state, PicklerObject *self, PyObject *t,
+ Py_ssize_t len)
{
Py_ssize_t i;
@@ -2741,7 +2776,7 @@ store_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len)
if (element == NULL)
return -1;
- if (save(self, element, 0) < 0)
+ if (save(state, self, element, 0) < 0)
return -1;
}
@@ -2755,7 +2790,7 @@ store_tuple_elements(PicklerObject *self, PyObject *t, Py_ssize_t len)
* magic so that it works in all cases. IOW, this is a long routine.
*/
static int
-save_tuple(PicklerObject *self, PyObject *obj)
+save_tuple(PickleState *state, PicklerObject *self, PyObject *obj)
{
Py_ssize_t len, i;
@@ -2792,7 +2827,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
*/
if (len <= 3 && self->proto >= 2) {
/* Use TUPLE{1,2,3} opcodes. */
- if (store_tuple_elements(self, obj, len) < 0)
+ if (store_tuple_elements(state, self, obj, len) < 0)
return -1;
if (PyMemoTable_Get(self->memo, obj)) {
@@ -2801,7 +2836,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, &pop_op, 1) < 0)
return -1;
/* fetch from memo */
- if (memo_get(self, obj) < 0)
+ if (memo_get(state, self, obj) < 0)
return -1;
return 0;
@@ -2819,7 +2854,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, &mark_op, 1) < 0)
return -1;
- if (store_tuple_elements(self, obj, len) < 0)
+ if (store_tuple_elements(state, self, obj, len) < 0)
return -1;
if (PyMemoTable_Get(self->memo, obj)) {
@@ -2837,7 +2872,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
return -1;
}
/* fetch from memo */
- if (memo_get(self, obj) < 0)
+ if (memo_get(state, self, obj) < 0)
return -1;
return 0;
@@ -2848,7 +2883,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
}
memoize:
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
return -1;
return 0;
@@ -2861,7 +2896,7 @@ save_tuple(PicklerObject *self, PyObject *obj)
* Returns 0 on success, <0 on error.
*/
static int
-batch_list(PicklerObject *self, PyObject *iter)
+batch_list(PickleState *state, PicklerObject *self, PyObject *iter)
{
PyObject *obj = NULL;
PyObject *firstitem = NULL;
@@ -2887,7 +2922,7 @@ batch_list(PicklerObject *self, PyObject *iter)
return -1;
break;
}
- i = save(self, obj, 0);
+ i = save(state, self, obj, 0);
Py_DECREF(obj);
if (i < 0)
return -1;
@@ -2916,7 +2951,7 @@ batch_list(PicklerObject *self, PyObject *iter)
goto error;
/* Only one item to write */
- if (save(self, firstitem, 0) < 0)
+ if (save(state, self, firstitem, 0) < 0)
goto error;
if (_Pickler_Write(self, &append_op, 1) < 0)
goto error;
@@ -2930,14 +2965,14 @@ batch_list(PicklerObject *self, PyObject *iter)
if (_Pickler_Write(self, &mark_op, 1) < 0)
goto error;
- if (save(self, firstitem, 0) < 0)
+ if (save(state, self, firstitem, 0) < 0)
goto error;
Py_CLEAR(firstitem);
n = 1;
/* Fetch and save up to BATCHSIZE items */
while (obj) {
- if (save(self, obj, 0) < 0)
+ if (save(state, self, obj, 0) < 0)
goto error;
Py_CLEAR(obj);
n += 1;
@@ -2977,7 +3012,7 @@ batch_list(PicklerObject *self, PyObject *iter)
* Note that this only works for protocols > 0.
*/
static int
-batch_list_exact(PicklerObject *self, PyObject *obj)
+batch_list_exact(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *item = NULL;
Py_ssize_t this_batch, total;
@@ -2993,7 +3028,7 @@ batch_list_exact(PicklerObject *self, PyObject *obj)
if (PyList_GET_SIZE(obj) == 1) {
item = PyList_GET_ITEM(obj, 0);
Py_INCREF(item);
- int err = save(self, item, 0);
+ int err = save(state, self, item, 0);
Py_DECREF(item);
if (err < 0)
return -1;
@@ -3011,7 +3046,7 @@ batch_list_exact(PicklerObject *self, PyObject *obj)
while (total < PyList_GET_SIZE(obj)) {
item = PyList_GET_ITEM(obj, total);
Py_INCREF(item);
- int err = save(self, item, 0);
+ int err = save(state, self, item, 0);
Py_DECREF(item);
if (err < 0)
return -1;
@@ -3028,7 +3063,7 @@ batch_list_exact(PicklerObject *self, PyObject *obj)
}
static int
-save_list(PicklerObject *self, PyObject *obj)
+save_list(PickleState *state, PicklerObject *self, PyObject *obj)
{
char header[3];
Py_ssize_t len;
@@ -3055,7 +3090,7 @@ save_list(PicklerObject *self, PyObject *obj)
if ((len = PyList_Size(obj)) < 0)
goto error;
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
goto error;
if (len != 0) {
@@ -3063,7 +3098,7 @@ save_list(PicklerObject *self, PyObject *obj)
if (PyList_CheckExact(obj) && self->proto > 0) {
if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error;
- status = batch_list_exact(self, obj);
+ status = batch_list_exact(state, self, obj);
_Py_LeaveRecursiveCall();
} else {
PyObject *iter = PyObject_GetIter(obj);
@@ -3074,7 +3109,7 @@ save_list(PicklerObject *self, PyObject *obj)
Py_DECREF(iter);
goto error;
}
- status = batch_list(self, iter);
+ status = batch_list(state, self, iter);
_Py_LeaveRecursiveCall();
Py_DECREF(iter);
}
@@ -3102,7 +3137,7 @@ save_list(PicklerObject *self, PyObject *obj)
* ugly to bear.
*/
static int
-batch_dict(PicklerObject *self, PyObject *iter)
+batch_dict(PickleState *state, PicklerObject *self, PyObject *iter)
{
PyObject *obj = NULL;
PyObject *firstitem = NULL;
@@ -3128,9 +3163,9 @@ batch_dict(PicklerObject *self, PyObject *iter)
"iterator must return 2-tuples");
return -1;
}
- i = save(self, PyTuple_GET_ITEM(obj, 0), 0);
+ i = save(state, self, PyTuple_GET_ITEM(obj, 0), 0);
if (i >= 0)
- i = save(self, PyTuple_GET_ITEM(obj, 1), 0);
+ i = save(state, self, PyTuple_GET_ITEM(obj, 1), 0);
Py_DECREF(obj);
if (i < 0)
return -1;
@@ -3164,9 +3199,9 @@ batch_dict(PicklerObject *self, PyObject *iter)
goto error;
/* Only one item to write */
- if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
+ if (save(state, self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
goto error;
- if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
+ if (save(state, self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
goto error;
if (_Pickler_Write(self, &setitem_op, 1) < 0)
goto error;
@@ -3180,9 +3215,9 @@ batch_dict(PicklerObject *self, PyObject *iter)
if (_Pickler_Write(self, &mark_op, 1) < 0)
goto error;
- if (save(self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
+ if (save(state, self, PyTuple_GET_ITEM(firstitem, 0), 0) < 0)
goto error;
- if (save(self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
+ if (save(state, self, PyTuple_GET_ITEM(firstitem, 1), 0) < 0)
goto error;
Py_CLEAR(firstitem);
n = 1;
@@ -3194,8 +3229,8 @@ batch_dict(PicklerObject *self, PyObject *iter)
"iterator must return 2-tuples");
goto error;
}
- if (save(self, PyTuple_GET_ITEM(obj, 0), 0) < 0 ||
- save(self, PyTuple_GET_ITEM(obj, 1), 0) < 0)
+ if (save(state, self, PyTuple_GET_ITEM(obj, 0), 0) < 0 ||
+ save(state, self, PyTuple_GET_ITEM(obj, 1), 0) < 0)
goto error;
Py_CLEAR(obj);
n += 1;
@@ -3233,7 +3268,7 @@ batch_dict(PicklerObject *self, PyObject *iter)
* Note that this currently doesn't work for protocol 0.
*/
static int
-batch_dict_exact(PicklerObject *self, PyObject *obj)
+batch_dict_exact(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *key = NULL, *value = NULL;
int i;
@@ -3253,10 +3288,10 @@ batch_dict_exact(PicklerObject *self, PyObject *obj)
PyDict_Next(obj, &ppos, &key, &value);
Py_INCREF(key);
Py_INCREF(value);
- if (save(self, key, 0) < 0) {
+ if (save(state, self, key, 0) < 0) {
goto error;
}
- if (save(self, value, 0) < 0) {
+ if (save(state, self, value, 0) < 0) {
goto error;
}
Py_CLEAR(key);
@@ -3274,10 +3309,10 @@ batch_dict_exact(PicklerObject *self, PyObject *obj)
while (PyDict_Next(obj, &ppos, &key, &value)) {
Py_INCREF(key);
Py_INCREF(value);
- if (save(self, key, 0) < 0) {
+ if (save(state, self, key, 0) < 0) {
goto error;
}
- if (save(self, value, 0) < 0) {
+ if (save(state, self, value, 0) < 0) {
goto error;
}
Py_CLEAR(key);
@@ -3303,7 +3338,7 @@ error:
}
static int
-save_dict(PicklerObject *self, PyObject *obj)
+save_dict(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *items, *iter;
char header[3];
@@ -3328,7 +3363,7 @@ save_dict(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, header, len) < 0)
goto error;
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
goto error;
if (PyDict_GET_SIZE(obj)) {
@@ -3338,7 +3373,7 @@ save_dict(PicklerObject *self, PyObject *obj)
not a dict subclass. */
if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error;
- status = batch_dict_exact(self, obj);
+ status = batch_dict_exact(state, self, obj);
_Py_LeaveRecursiveCall();
} else {
items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items));
@@ -3352,7 +3387,7 @@ save_dict(PicklerObject *self, PyObject *obj)
Py_DECREF(iter);
goto error;
}
- status = batch_dict(self, iter);
+ status = batch_dict(state, self, iter);
_Py_LeaveRecursiveCall();
Py_DECREF(iter);
}
@@ -3370,7 +3405,7 @@ save_dict(PicklerObject *self, PyObject *obj)
}
static int
-save_set(PicklerObject *self, PyObject *obj)
+save_set(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *item;
int i;
@@ -3396,7 +3431,7 @@ save_set(PicklerObject *self, PyObject *obj)
return -1;
}
/* save_reduce() will memoize the object automatically. */
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(state, self, reduce_value, obj);
Py_DECREF(reduce_value);
return status;
}
@@ -3404,7 +3439,7 @@ save_set(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, &empty_set_op, 1) < 0)
return -1;
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
return -1;
set_size = PySet_GET_SIZE(obj);
@@ -3418,7 +3453,7 @@ save_set(PicklerObject *self, PyObject *obj)
return -1;
while (_PySet_NextEntry(obj, &ppos, &item, &hash)) {
Py_INCREF(item);
- int err = save(self, item, 0);
+ int err = save(state, self, item, 0);
Py_CLEAR(item);
if (err < 0)
return -1;
@@ -3439,7 +3474,7 @@ save_set(PicklerObject *self, PyObject *obj)
}
static int
-save_frozenset(PicklerObject *self, PyObject *obj)
+save_frozenset(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *iter;
@@ -3465,7 +3500,7 @@ save_frozenset(PicklerObject *self, PyObject *obj)
return -1;
}
/* save_reduce() will memoize the object automatically. */
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(state, self, reduce_value, obj);
Py_DECREF(reduce_value);
return status;
}
@@ -3488,7 +3523,7 @@ save_frozenset(PicklerObject *self, PyObject *obj)
}
break;
}
- if (save(self, item, 0) < 0) {
+ if (save(state, self, item, 0) < 0) {
Py_DECREF(item);
Py_DECREF(iter);
return -1;
@@ -3505,25 +3540,24 @@ save_frozenset(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, &pop_mark_op, 1) < 0)
return -1;
- if (memo_get(self, obj) < 0)
+ if (memo_get(state, self, obj) < 0)
return -1;
return 0;
}
if (_Pickler_Write(self, &frozenset_op, 1) < 0)
return -1;
- if (memo_put(self, obj) < 0)
+ if (memo_put(state, self, obj) < 0)
return -1;
return 0;
}
static int
-fix_imports(PyObject **module_name, PyObject **global_name)
+fix_imports(PickleState *st, PyObject **module_name, PyObject **global_name)
{
PyObject *key;
PyObject *item;
- PickleState *st = _Pickle_GetGlobalState();
key = PyTuple_Pack(2, *module_name, *global_name);
if (key == NULL)
@@ -3582,7 +3616,8 @@ fix_imports(PyObject **module_name, PyObject **global_name)
}
static int
-save_global(PicklerObject *self, PyObject *obj, PyObject *name)
+save_global(PickleState *st, PicklerObject *self, PyObject *obj,
+ PyObject *name)
{
PyObject *global_name = NULL;
PyObject *module_name = NULL;
@@ -3591,7 +3626,6 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
PyObject *dotted_path = NULL;
PyObject *lastname = NULL;
PyObject *cls;
- PickleState *st = _Pickle_GetGlobalState();
int status = 0;
const char global_op = GLOBAL;
@@ -3727,21 +3761,20 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
if (self->proto >= 4) {
const char stack_global_op = STACK_GLOBAL;
- if (save(self, module_name, 0) < 0)
+ if (save(st, self, module_name, 0) < 0)
goto error;
- if (save(self, global_name, 0) < 0)
+ if (save(st, self, global_name, 0) < 0)
goto error;
if (_Pickler_Write(self, &stack_global_op, 1) < 0)
goto error;
}
else if (parent != module) {
- PickleState *st = _Pickle_GetGlobalState();
PyObject *reduce_value = Py_BuildValue("(O(OO))",
st->getattr, parent, lastname);
if (reduce_value == NULL)
goto error;
- status = save_reduce(self, reduce_value, NULL);
+ status = save_reduce(st, self, reduce_value, NULL);
Py_DECREF(reduce_value);
if (status < 0)
goto error;
@@ -3759,7 +3792,7 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
/* For protocol < 3 and if the user didn't request against doing
so, we convert module names to the old 2.x module names. */
if (self->proto < 3 && self->fix_imports) {
- if (fix_imports(&module_name, &global_name) < 0) {
+ if (fix_imports(st, &module_name, &global_name) < 0) {
goto error;
}
}
@@ -3813,7 +3846,7 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
goto error;
}
/* Memoize the object. */
- if (memo_put(self, obj) < 0)
+ if (memo_put(st, self, obj) < 0)
goto error;
}
@@ -3832,7 +3865,8 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
}
static int
-save_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton)
+save_singleton_type(PickleState *state, PicklerObject *self, PyObject *obj,
+ PyObject *singleton)
{
PyObject *reduce_value;
int status;
@@ -3841,28 +3875,28 @@ save_singleton_type(PicklerObject *self, PyObject *obj, PyObject *singleton)
if (reduce_value == NULL) {
return -1;
}
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(state, self, reduce_value, obj);
Py_DECREF(reduce_value);
return status;
}
static int
-save_type(PicklerObject *self, PyObject *obj)
+save_type(PickleState *state, PicklerObject *self, PyObject *obj)
{
if (obj == (PyObject *)&_PyNone_Type) {
- return save_singleton_type(self, obj, Py_None);
+ return save_singleton_type(state, self, obj, Py_None);
}
else if (obj == (PyObject *)&PyEllipsis_Type) {
- return save_singleton_type(self, obj, Py_Ellipsis);
+ return save_singleton_type(state, self, obj, Py_Ellipsis);
}
else if (obj == (PyObject *)&_PyNotImplemented_Type) {
- return save_singleton_type(self, obj, Py_NotImplemented);
+ return save_singleton_type(state, self, obj, Py_NotImplemented);
}
- return save_global(self, obj, NULL);
+ return save_global(state, self, obj, NULL);
}
static int
-save_pers(PicklerObject *self, PyObject *obj)
+save_pers(PickleState *state, PicklerObject *self, PyObject *obj)
{
PyObject *pid = NULL;
int status = 0;
@@ -3876,7 +3910,7 @@ save_pers(PicklerObject *self, PyObject *obj)
if (pid != Py_None) {
if (self->bin) {
- if (save(self, pid, 1) < 0 ||
+ if (save(state, self, pid, 1) < 0 ||
_Pickler_Write(self, &binpersid_op, 1) < 0)
goto error;
}
@@ -3890,7 +3924,7 @@ save_pers(PicklerObject *self, PyObject *obj)
/* XXX: Should it check whether the pid contains embedded
newlines? */
if (!PyUnicode_IS_ASCII(pid_str)) {
- PyErr_SetString(_Pickle_GetGlobalState()->PicklingError,
+ PyErr_SetString(state->PicklingError,
"persistent IDs in protocol 0 must be "
"ASCII strings");
Py_DECREF(pid_str);
@@ -3933,7 +3967,8 @@ get_class(PyObject *obj)
* appropriate __reduce__ method for obj.
*/
static int
-save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
+save_reduce(PickleState *st, PicklerObject *self, PyObject *args,
+ PyObject *obj)
{
PyObject *callable;
PyObject *argtup;
@@ -3941,7 +3976,6 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
PyObject *listitems = Py_None;
PyObject *dictitems = Py_None;
PyObject *state_setter = Py_None;
- PickleState *st = _Pickle_GetGlobalState();
Py_ssize_t size;
int use_newobj = 0, use_newobj_ex = 0;
@@ -4053,9 +4087,9 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
}
if (self->proto >= 4) {
- if (save(self, cls, 0) < 0 ||
- save(self, args, 0) < 0 ||
- save(self, kwargs, 0) < 0 ||
+ if (save(st, self, cls, 0) < 0 ||
+ save(st, self, args, 0) < 0 ||
+ save(st, self, kwargs, 0) < 0 ||
_Pickler_Write(self, &newobj_ex_op, 1) < 0) {
return -1;
}
@@ -4092,8 +4126,8 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
return -1;
}
- if (save(self, callable, 0) < 0 ||
- save(self, newargs, 0) < 0 ||
+ if (save(st, self, callable, 0) < 0 ||
+ save(st, self, newargs, 0) < 0 ||
_Pickler_Write(self, &reduce_op, 1) < 0) {
Py_DECREF(newargs);
Py_DECREF(callable);
@@ -4163,14 +4197,15 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
function. */
/* Save the class and its __new__ arguments. */
- if (save(self, cls, 0) < 0)
+ if (save(st, self, cls, 0) < 0) {
return -1;
+ }
newargtup = PyTuple_GetSlice(argtup, 1, PyTuple_GET_SIZE(argtup));
if (newargtup == NULL)
return -1;
- p = save(self, newargtup, 0);
+ p = save(st, self, newargtup, 0);
Py_DECREF(newargtup);
if (p < 0)
return -1;
@@ -4180,8 +4215,8 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
return -1;
}
else { /* Not using NEWOBJ. */
- if (save(self, callable, 0) < 0 ||
- save(self, argtup, 0) < 0 ||
+ if (save(st, self, callable, 0) < 0 ||
+ save(st, self, argtup, 0) < 0 ||
_Pickler_Write(self, &reduce_op, 1) < 0)
return -1;
}
@@ -4199,24 +4234,24 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
if (_Pickler_Write(self, &pop_op, 1) < 0)
return -1;
- if (memo_get(self, obj) < 0)
+ if (memo_get(st, self, obj) < 0)
return -1;
return 0;
}
- else if (memo_put(self, obj) < 0)
+ else if (memo_put(st, self, obj) < 0)
return -1;
}
- if (listitems && batch_list(self, listitems) < 0)
+ if (listitems && batch_list(st, self, listitems) < 0)
return -1;
- if (dictitems && batch_dict(self, dictitems) < 0)
+ if (dictitems && batch_dict(st, self, dictitems) < 0)
return -1;
if (state) {
if (state_setter == NULL) {
- if (save(self, state, 0) < 0 ||
+ if (save(st, self, state, 0) < 0 ||
_Pickler_Write(self, &build_op, 1) < 0)
return -1;
}
@@ -4233,8 +4268,8 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
const char tupletwo_op = TUPLE2;
const char pop_op = POP;
- if (save(self, state_setter, 0) < 0 ||
- save(self, obj, 0) < 0 || save(self, state, 0) < 0 ||
+ if (save(st, self, state_setter, 0) < 0 ||
+ save(st, self, obj, 0) < 0 || save(st, self, state, 0) < 0 ||
_Pickler_Write(self, &tupletwo_op, 1) < 0 ||
_Pickler_Write(self, &reduce_op, 1) < 0 ||
_Pickler_Write(self, &pop_op, 1) < 0)
@@ -4245,7 +4280,7 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
}
static int
-save(PicklerObject *self, PyObject *obj, int pers_save)
+save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save)
{
PyTypeObject *type;
PyObject *reduce_func = NULL;
@@ -4263,7 +4298,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
0 if it did nothing successfully;
1 if a persistent id was saved.
*/
- if ((status = save_pers(self, obj)) != 0)
+ if ((status = save_pers(st, self, obj)) != 0)
return status;
}
@@ -4293,14 +4328,14 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
a GET (or BINGET) opcode, instead of pickling the object
once again. */
if (PyMemoTable_Get(self->memo, obj)) {
- return memo_get(self, obj);
+ return memo_get(st, self, obj);
}
if (type == &PyBytes_Type) {
- return save_bytes(self, obj);
+ return save_bytes(st, self, obj);
}
else if (type == &PyUnicode_Type) {
- return save_unicode(self, obj);
+ return save_unicode(st, self, obj);
}
/* We're only calling _Py_EnterRecursiveCall here so that atomic
@@ -4310,31 +4345,31 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
}
if (type == &PyDict_Type) {
- status = save_dict(self, obj);
+ status = save_dict(st, self, obj);
goto done;
}
else if (type == &PySet_Type) {
- status = save_set(self, obj);
+ status = save_set(st, self, obj);
goto done;
}
else if (type == &PyFrozenSet_Type) {
- status = save_frozenset(self, obj);
+ status = save_frozenset(st, self, obj);
goto done;
}
else if (type == &PyList_Type) {
- status = save_list(self, obj);
+ status = save_list(st, self, obj);
goto done;
}
else if (type == &PyTuple_Type) {
- status = save_tuple(self, obj);
+ status = save_tuple(st, self, obj);
goto done;
}
else if (type == &PyByteArray_Type) {
- status = save_bytearray(self, obj);
+ status = save_bytearray(st, self, obj);
goto done;
}
else if (type == &PyPickleBuffer_Type) {
- status = save_picklebuffer(self, obj);
+ status = save_picklebuffer(st, self, obj);
goto done;
}
@@ -4354,11 +4389,11 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
}
if (type == &PyType_Type) {
- status = save_type(self, obj);
+ status = save_type(st, self, obj);
goto done;
}
else if (type == &PyFunction_Type) {
- status = save_global(self, obj, NULL);
+ status = save_global(st, self, obj, NULL);
goto done;
}
@@ -4369,7 +4404,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
* __reduce_ex__ method, or the object's __reduce__ method.
*/
if (self->dispatch_table == NULL) {
- PickleState *st = _Pickle_GetGlobalState();
reduce_func = PyDict_GetItemWithError(st->dispatch_table,
(PyObject *)type);
if (reduce_func == NULL) {
@@ -4396,7 +4430,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
reduce_value = _Pickle_FastCall(reduce_func, Py_NewRef(obj));
}
else if (PyType_IsSubtype(type, &PyType_Type)) {
- status = save_global(self, obj, NULL);
+ status = save_global(st, self, obj, NULL);
goto done;
}
else {
@@ -4428,7 +4462,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
reduce_value = PyObject_CallNoArgs(reduce_func);
}
else {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->PicklingError,
"can't pickle '%.200s' object: %R",
type->tp_name, obj);
@@ -4442,18 +4475,17 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
reduce:
if (PyUnicode_Check(reduce_value)) {
- status = save_global(self, obj, reduce_value);
+ status = save_global(st, self, obj, reduce_value);
goto done;
}
if (!PyTuple_Check(reduce_value)) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->PicklingError,
"__reduce__ must return a string or tuple");
goto error;
}
- status = save_reduce(self, reduce_value, obj);
+ status = save_reduce(st, self, reduce_value, obj);
if (0) {
error:
@@ -4469,7 +4501,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
}
static int
-dump(PicklerObject *self, PyObject *obj)
+dump(PickleState *state, PicklerObject *self, PyObject *obj)
{
const char stop_op = STOP;
int status = -1;
@@ -4499,7 +4531,7 @@ dump(PicklerObject *self, PyObject *obj)
self->framing = 1;
}
- if (save(self, obj, 0) < 0 ||
+ if (save(state, self, obj, 0) < 0 ||
_Pickler_Write(self, &stop_op, 1) < 0 ||
_Pickler_CommitFrame(self) < 0)
goto error;
@@ -4546,6 +4578,7 @@ _pickle_Pickler_clear_memo_impl(PicklerObject *self)
_pickle.Pickler.dump
+ cls: defining_class
obj: object
/
@@ -4553,14 +4586,15 @@ Write a pickled representation of the given object to the open file.
[clinic start generated code]*/
static PyObject *
-_pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
-/*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/
+_pickle_Pickler_dump_impl(PicklerObject *self, PyTypeObject *cls,
+ PyObject *obj)
+/*[clinic end generated code: output=952cf7f68b1445bb input=f949d84151983594]*/
{
+ PickleState *st = _Pickle_GetStateByClass(cls);
/* Check whether the Pickler was initialized correctly (issue3664).
Developers often forget to call __init__() in their subclasses, which
would trigger a segfault without this check. */
if (self->write == NULL) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->PicklingError,
"Pickler.__init__() was not called by %s.__init__()",
Py_TYPE(self)->tp_name);
@@ -4570,7 +4604,7 @@ _pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
if (_Pickler_ClearBuffer(self) < 0)
return NULL;
- if (dump(self, obj) < 0)
+ if (dump(st, self, obj) < 0)
return NULL;
if (_Pickler_FlushToFile(self) < 0)
@@ -4612,36 +4646,6 @@ static struct PyMethodDef Pickler_methods[] = {
{NULL, NULL} /* sentinel */
};
-static void
-Pickler_dealloc(PicklerObject *self)
-{
- PyObject_GC_UnTrack(self);
-
- Py_XDECREF(self->output_buffer);
- Py_XDECREF(self->write);
- Py_XDECREF(self->pers_func);
- Py_XDECREF(self->dispatch_table);
- Py_XDECREF(self->fast_memo);
- Py_XDECREF(self->reducer_override);
- Py_XDECREF(self->buffer_callback);
-
- PyMemoTable_Del(self->memo);
-
- Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static int
-Pickler_traverse(PicklerObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->write);
- Py_VISIT(self->pers_func);
- Py_VISIT(self->dispatch_table);
- Py_VISIT(self->fast_memo);
- Py_VISIT(self->reducer_override);
- Py_VISIT(self->buffer_callback);
- return 0;
-}
-
static int
Pickler_clear(PicklerObject *self)
{
@@ -4661,6 +4665,29 @@ Pickler_clear(PicklerObject *self)
return 0;
}
+static void
+Pickler_dealloc(PicklerObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack(self);
+ (void)Pickler_clear(self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
+}
+
+static int
+Pickler_traverse(PicklerObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ Py_VISIT(self->write);
+ Py_VISIT(self->pers_func);
+ Py_VISIT(self->dispatch_table);
+ Py_VISIT(self->fast_memo);
+ Py_VISIT(self->reducer_override);
+ Py_VISIT(self->buffer_callback);
+ return 0;
+}
+
/*[clinic input]
@@ -4870,15 +4897,18 @@ static PyMethodDef picklerproxy_methods[] = {
static void
PicklerMemoProxy_dealloc(PicklerMemoProxyObject *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- Py_XDECREF(self->pickler);
- PyObject_GC_Del((PyObject *)self);
+ Py_CLEAR(self->pickler);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static int
PicklerMemoProxy_traverse(PicklerMemoProxyObject *self,
visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->pickler);
return 0;
}
@@ -4890,43 +4920,29 @@ PicklerMemoProxy_clear(PicklerMemoProxyObject *self)
return 0;
}
-static PyTypeObject PicklerMemoProxyType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_pickle.PicklerMemoProxy", /*tp_name*/
- sizeof(PicklerMemoProxyObject), /*tp_basicsize*/
- 0,
- (destructor)PicklerMemoProxy_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- PyObject_HashNotImplemented, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- 0, /* tp_doc */
- (traverseproc)PicklerMemoProxy_traverse, /* tp_traverse */
- (inquiry)PicklerMemoProxy_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- picklerproxy_methods, /* tp_methods */
+static PyType_Slot memoproxy_slots[] = {
+ {Py_tp_dealloc, PicklerMemoProxy_dealloc},
+ {Py_tp_traverse, PicklerMemoProxy_traverse},
+ {Py_tp_clear, PicklerMemoProxy_clear},
+ {Py_tp_methods, picklerproxy_methods},
+ {Py_tp_hash, PyObject_HashNotImplemented},
+ {0, NULL},
+};
+
+static PyType_Spec memoproxy_spec = {
+ .name = "_pickle.PicklerMemoProxy",
+ .basicsize = sizeof(PicklerMemoProxyObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = memoproxy_slots,
};
static PyObject *
PicklerMemoProxy_New(PicklerObject *pickler)
{
PicklerMemoProxyObject *self;
-
- self = PyObject_GC_New(PicklerMemoProxyObject, &PicklerMemoProxyType);
+ PickleState *st = _Pickle_FindStateByType(Py_TYPE(pickler));
+ self = PyObject_GC_New(PicklerMemoProxyObject, st->PicklerMemoProxyType);
if (self == NULL)
return NULL;
self->pickler = (PicklerObject*)Py_NewRef(pickler);
@@ -4953,7 +4969,8 @@ Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored))
return -1;
}
- if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) {
+ PickleState *st = _Pickle_FindStateByType(Py_TYPE(self));
+ if (Py_IS_TYPE(obj, st->PicklerMemoProxyType)) {
PicklerObject *pickler =
((PicklerMemoProxyObject *)obj)->pickler;
@@ -5049,47 +5066,27 @@ static PyGetSetDef Pickler_getsets[] = {
{NULL}
};
-static PyTypeObject Pickler_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_pickle.Pickler" , /*tp_name*/
- sizeof(PicklerObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Pickler_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- _pickle_Pickler___init____doc__, /*tp_doc*/
- (traverseproc)Pickler_traverse, /*tp_traverse*/
- (inquiry)Pickler_clear, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- Pickler_methods, /*tp_methods*/
- Pickler_members, /*tp_members*/
- Pickler_getsets, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- _pickle_Pickler___init__, /*tp_init*/
- PyType_GenericAlloc, /*tp_alloc*/
- PyType_GenericNew, /*tp_new*/
- PyObject_GC_Del, /*tp_free*/
- 0, /*tp_is_gc*/
+static PyType_Slot pickler_type_slots[] = {
+ {Py_tp_dealloc, Pickler_dealloc},
+ {Py_tp_methods, Pickler_methods},
+ {Py_tp_members, Pickler_members},
+ {Py_tp_getset, Pickler_getsets},
+ {Py_tp_clear, Pickler_clear},
+ {Py_tp_doc, (char*)_pickle_Pickler___init____doc__},
+ {Py_tp_traverse, Pickler_traverse},
+ {Py_tp_init, _pickle_Pickler___init__},
+ {Py_tp_new, PyType_GenericNew},
+ {Py_tp_alloc, PyType_GenericAlloc},
+ {Py_tp_free, PyObject_GC_Del},
+ {0, NULL},
+};
+
+static PyType_Spec pickler_type_spec = {
+ .name = "_pickle.Pickler",
+ .basicsize = sizeof(PicklerObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = pickler_type_slots,
};
/* Temporary helper for calling self.find_class().
@@ -5107,17 +5104,14 @@ find_class(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
}
static Py_ssize_t
-marker(UnpicklerObject *self)
+marker(PickleState *st, UnpicklerObject *self)
{
- Py_ssize_t mark;
-
if (self->num_marks < 1) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "could not find MARK");
return -1;
}
- mark = self->marks[--self->num_marks];
+ Py_ssize_t mark = self->marks[--self->num_marks];
self->stack->mark_set = self->num_marks != 0;
self->stack->fence = self->num_marks ?
self->marks[self->num_marks - 1] : 0;
@@ -5125,24 +5119,24 @@ marker(UnpicklerObject *self)
}
static int
-load_none(UnpicklerObject *self)
+load_none(PickleState *state, UnpicklerObject *self)
{
PDATA_APPEND(self->stack, Py_None, -1);
return 0;
}
static int
-load_int(UnpicklerObject *self)
+load_int(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
char *endptr, *s;
Py_ssize_t len;
long x;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
errno = 0;
/* XXX: Should the base argument of strtol() be explicitly set to 10?
@@ -5177,7 +5171,7 @@ load_int(UnpicklerObject *self)
}
static int
-load_bool(UnpicklerObject *self, PyObject *boolean)
+load_bool(PickleState *state, UnpicklerObject *self, PyObject *boolean)
{
assert(boolean == Py_True || boolean == Py_False);
PDATA_APPEND(self->stack, boolean, -1);
@@ -5257,49 +5251,46 @@ load_binintx(UnpicklerObject *self, char *s, int size)
}
static int
-load_binint(UnpicklerObject *self)
+load_binint(PickleState *state, UnpicklerObject *self)
{
char *s;
-
- if (_Unpickler_Read(self, &s, 4) < 0)
+ if (_Unpickler_Read(self, state, &s, 4) < 0)
return -1;
return load_binintx(self, s, 4);
}
static int
-load_binint1(UnpicklerObject *self)
+load_binint1(PickleState *state, UnpicklerObject *self)
{
char *s;
-
- if (_Unpickler_Read(self, &s, 1) < 0)
+ if (_Unpickler_Read(self, state, &s, 1) < 0)
return -1;
return load_binintx(self, s, 1);
}
static int
-load_binint2(UnpicklerObject *self)
+load_binint2(PickleState *state, UnpicklerObject *self)
{
char *s;
-
- if (_Unpickler_Read(self, &s, 2) < 0)
+ if (_Unpickler_Read(self, state, &s, 2) < 0)
return -1;
return load_binintx(self, s, 2);
}
static int
-load_long(UnpicklerObject *self)
+load_long(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
char *s = NULL;
Py_ssize_t len;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
/* s[len-2] will usually be 'L' (and s[len-1] is '\n'); we need to remove
the 'L' before calling PyLong_FromString. In order to maintain
@@ -5320,19 +5311,18 @@ load_long(UnpicklerObject *self)
* data following.
*/
static int
-load_counted_long(UnpicklerObject *self, int size)
+load_counted_long(PickleState *st, UnpicklerObject *self, int size)
{
PyObject *value;
char *nbytes;
char *pdata;
assert(size == 1 || size == 4);
- if (_Unpickler_Read(self, &nbytes, size) < 0)
+ if (_Unpickler_Read(self, st, &nbytes, size) < 0)
return -1;
size = calc_binint(nbytes, size);
if (size < 0) {
- PickleState *st = _Pickle_GetGlobalState();
/* Corrupt or hostile pickle -- we never write one like this */
PyErr_SetString(st->UnpicklingError,
"LONG pickle has negative byte count");
@@ -5343,7 +5333,7 @@ load_counted_long(UnpicklerObject *self, int size)
value = PyLong_FromLong(0L);
else {
/* Read the raw little-endian bytes and convert. */
- if (_Unpickler_Read(self, &pdata, size) < 0)
+ if (_Unpickler_Read(self, st, &pdata, size) < 0)
return -1;
value = _PyLong_FromByteArray((unsigned char *)pdata, (size_t)size,
1 /* little endian */ , 1 /* signed */ );
@@ -5355,17 +5345,17 @@ load_counted_long(UnpicklerObject *self, int size)
}
static int
-load_float(UnpicklerObject *self)
+load_float(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
char *endptr, *s;
Py_ssize_t len;
double d;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
errno = 0;
d = PyOS_string_to_double(s, &endptr, PyExc_OverflowError);
@@ -5384,13 +5374,13 @@ load_float(UnpicklerObject *self)
}
static int
-load_binfloat(UnpicklerObject *self)
+load_binfloat(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
double x;
char *s;
- if (_Unpickler_Read(self, &s, 8) < 0)
+ if (_Unpickler_Read(self, state, &s, 8) < 0)
return -1;
x = PyFloat_Unpack8(s, 0);
@@ -5405,14 +5395,14 @@ load_binfloat(UnpicklerObject *self)
}
static int
-load_string(UnpicklerObject *self)
+load_string(PickleState *st, UnpicklerObject *self)
{
PyObject *bytes;
PyObject *obj;
Py_ssize_t len;
char *s, *p;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(st, self, &s)) < 0)
return -1;
/* Strip the newline */
len--;
@@ -5422,7 +5412,6 @@ load_string(UnpicklerObject *self)
len -= 2;
}
else {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"the STRING opcode argument must be quoted");
return -1;
@@ -5453,25 +5442,24 @@ load_string(UnpicklerObject *self)
}
static int
-load_counted_binstring(UnpicklerObject *self, int nbytes)
+load_counted_binstring(PickleState *st, UnpicklerObject *self, int nbytes)
{
PyObject *obj;
Py_ssize_t size;
char *s;
- if (_Unpickler_Read(self, &s, nbytes) < 0)
+ if (_Unpickler_Read(self, st, &s, nbytes) < 0)
return -1;
size = calc_binsize(s, nbytes);
if (size < 0) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError,
"BINSTRING exceeds system's maximum size of %zd bytes",
PY_SSIZE_T_MAX);
return -1;
}
- if (_Unpickler_Read(self, &s, size) < 0)
+ if (_Unpickler_Read(self, st, &s, size) < 0)
return -1;
/* Convert Python 2.x strings to bytes if the *encoding* given to the
@@ -5491,13 +5479,13 @@ load_counted_binstring(UnpicklerObject *self, int nbytes)
}
static int
-load_counted_binbytes(UnpicklerObject *self, int nbytes)
+load_counted_binbytes(PickleState *state, UnpicklerObject *self, int nbytes)
{
PyObject *bytes;
Py_ssize_t size;
char *s;
- if (_Unpickler_Read(self, &s, nbytes) < 0)
+ if (_Unpickler_Read(self, state, &s, nbytes) < 0)
return -1;
size = calc_binsize(s, nbytes);
@@ -5511,7 +5499,7 @@ load_counted_binbytes(UnpicklerObject *self, int nbytes)
bytes = PyBytes_FromStringAndSize(NULL, size);
if (bytes == NULL)
return -1;
- if (_Unpickler_ReadInto(self, PyBytes_AS_STRING(bytes), size) < 0) {
+ if (_Unpickler_ReadInto(state, self, PyBytes_AS_STRING(bytes), size) < 0) {
Py_DECREF(bytes);
return -1;
}
@@ -5521,13 +5509,13 @@ load_counted_binbytes(UnpicklerObject *self, int nbytes)
}
static int
-load_counted_bytearray(UnpicklerObject *self)
+load_counted_bytearray(PickleState *state, UnpicklerObject *self)
{
PyObject *bytearray;
Py_ssize_t size;
char *s;
- if (_Unpickler_Read(self, &s, 8) < 0) {
+ if (_Unpickler_Read(self, state, &s, 8) < 0) {
return -1;
}
@@ -5543,7 +5531,8 @@ load_counted_bytearray(UnpicklerObject *self)
if (bytearray == NULL) {
return -1;
}
- if (_Unpickler_ReadInto(self, PyByteArray_AS_STRING(bytearray), size) < 0) {
+ char *str = PyByteArray_AS_STRING(bytearray);
+ if (_Unpickler_ReadInto(state, self, str, size) < 0) {
Py_DECREF(bytearray);
return -1;
}
@@ -5553,10 +5542,9 @@ load_counted_bytearray(UnpicklerObject *self)
}
static int
-load_next_buffer(UnpicklerObject *self)
+load_next_buffer(PickleState *st, UnpicklerObject *self)
{
if (self->buffers == NULL) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"pickle stream refers to out-of-band data "
"but no *buffers* argument was given");
@@ -5565,7 +5553,6 @@ load_next_buffer(UnpicklerObject *self)
PyObject *buf = PyIter_Next(self->buffers);
if (buf == NULL) {
if (!PyErr_Occurred()) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"not enough out-of-band buffers");
}
@@ -5577,11 +5564,11 @@ load_next_buffer(UnpicklerObject *self)
}
static int
-load_readonly_buffer(UnpicklerObject *self)
+load_readonly_buffer(PickleState *state, UnpicklerObject *self)
{
Py_ssize_t len = Py_SIZE(self->stack);
if (len <= self->stack->fence) {
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
}
PyObject *obj = self->stack->data[len - 1];
@@ -5603,16 +5590,16 @@ load_readonly_buffer(UnpicklerObject *self)
}
static int
-load_unicode(UnpicklerObject *self)
+load_unicode(PickleState *state, UnpicklerObject *self)
{
PyObject *str;
Py_ssize_t len;
char *s = NULL;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 1)
- return bad_readline();
+ return bad_readline(state);
str = PyUnicode_DecodeRawUnicodeEscape(s, len - 1, NULL);
if (str == NULL)
@@ -5623,13 +5610,13 @@ load_unicode(UnpicklerObject *self)
}
static int
-load_counted_binunicode(UnpicklerObject *self, int nbytes)
+load_counted_binunicode(PickleState *state, UnpicklerObject *self, int nbytes)
{
PyObject *str;
Py_ssize_t size;
char *s;
- if (_Unpickler_Read(self, &s, nbytes) < 0)
+ if (_Unpickler_Read(self, state, &s, nbytes) < 0)
return -1;
size = calc_binsize(s, nbytes);
@@ -5640,7 +5627,7 @@ load_counted_binunicode(UnpicklerObject *self, int nbytes)
return -1;
}
- if (_Unpickler_Read(self, &s, size) < 0)
+ if (_Unpickler_Read(self, state, &s, size) < 0)
return -1;
str = PyUnicode_DecodeUTF8(s, size, "surrogatepass");
@@ -5652,14 +5639,14 @@ load_counted_binunicode(UnpicklerObject *self, int nbytes)
}
static int
-load_counted_tuple(UnpicklerObject *self, Py_ssize_t len)
+load_counted_tuple(PickleState *state, UnpicklerObject *self, Py_ssize_t len)
{
PyObject *tuple;
if (Py_SIZE(self->stack) < len)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
- tuple = Pdata_poptuple(self->stack, Py_SIZE(self->stack) - len);
+ tuple = Pdata_poptuple(state, self->stack, Py_SIZE(self->stack) - len);
if (tuple == NULL)
return -1;
PDATA_PUSH(self->stack, tuple, -1);
@@ -5667,18 +5654,18 @@ load_counted_tuple(UnpicklerObject *self, Py_ssize_t len)
}
static int
-load_tuple(UnpicklerObject *self)
+load_tuple(PickleState *state, UnpicklerObject *self)
{
Py_ssize_t i;
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
- return load_counted_tuple(self, Py_SIZE(self->stack) - i);
+ return load_counted_tuple(state, self, Py_SIZE(self->stack) - i);
}
static int
-load_empty_list(UnpicklerObject *self)
+load_empty_list(PickleState *state, UnpicklerObject *self)
{
PyObject *list;
@@ -5689,7 +5676,7 @@ load_empty_list(UnpicklerObject *self)
}
static int
-load_empty_dict(UnpicklerObject *self)
+load_empty_dict(PickleState *state, UnpicklerObject *self)
{
PyObject *dict;
@@ -5700,7 +5687,7 @@ load_empty_dict(UnpicklerObject *self)
}
static int
-load_empty_set(UnpicklerObject *self)
+load_empty_set(PickleState *state, UnpicklerObject *self)
{
PyObject *set;
@@ -5711,12 +5698,12 @@ load_empty_set(UnpicklerObject *self)
}
static int
-load_list(UnpicklerObject *self)
+load_list(PickleState *state, UnpicklerObject *self)
{
PyObject *list;
Py_ssize_t i;
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
list = Pdata_poplist(self->stack, i);
@@ -5727,12 +5714,12 @@ load_list(UnpicklerObject *self)
}
static int
-load_dict(UnpicklerObject *self)
+load_dict(PickleState *st, UnpicklerObject *self)
{
PyObject *dict, *key, *value;
Py_ssize_t i, j, k;
- if ((i = marker(self)) < 0)
+ if ((i = marker(st, self)) < 0)
return -1;
j = Py_SIZE(self->stack);
@@ -5740,7 +5727,6 @@ load_dict(UnpicklerObject *self)
return -1;
if ((j - i) % 2 != 0) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "odd number of items for DICT");
Py_DECREF(dict);
return -1;
@@ -5760,16 +5746,16 @@ load_dict(UnpicklerObject *self)
}
static int
-load_frozenset(UnpicklerObject *self)
+load_frozenset(PickleState *state, UnpicklerObject *self)
{
PyObject *items;
PyObject *frozenset;
Py_ssize_t i;
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
- items = Pdata_poptuple(self->stack, i);
+ items = Pdata_poptuple(state, self->stack, i);
if (items == NULL)
return -1;
@@ -5803,22 +5789,22 @@ instantiate(PyObject *cls, PyObject *args)
}
static int
-load_obj(UnpicklerObject *self)
+load_obj(PickleState *state, UnpicklerObject *self)
{
PyObject *cls, *args, *obj = NULL;
Py_ssize_t i;
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
if (Py_SIZE(self->stack) - i < 1)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
- args = Pdata_poptuple(self->stack, i + 1);
+ args = Pdata_poptuple(state, self->stack, i + 1);
if (args == NULL)
return -1;
- PDATA_POP(self->stack, cls);
+ PDATA_POP(state, self->stack, cls);
if (cls) {
obj = instantiate(cls, args);
Py_DECREF(cls);
@@ -5832,7 +5818,7 @@ load_obj(UnpicklerObject *self)
}
static int
-load_inst(UnpicklerObject *self)
+load_inst(PickleState *state, UnpicklerObject *self)
{
PyObject *cls = NULL;
PyObject *args = NULL;
@@ -5843,12 +5829,12 @@ load_inst(UnpicklerObject *self)
Py_ssize_t i;
char *s;
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
/* Here it is safe to use PyUnicode_DecodeASCII(), even though non-ASCII
identifiers are permitted in Python 3.0, since the INST opcode is only
@@ -5857,10 +5843,10 @@ load_inst(UnpicklerObject *self)
if (module_name == NULL)
return -1;
- if ((len = _Unpickler_Readline(self, &s)) >= 0) {
+ if ((len = _Unpickler_Readline(state, self, &s)) >= 0) {
if (len < 2) {
Py_DECREF(module_name);
- return bad_readline();
+ return bad_readline(state);
}
class_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
if (class_name != NULL) {
@@ -5873,7 +5859,7 @@ load_inst(UnpicklerObject *self)
if (cls == NULL)
return -1;
- if ((args = Pdata_poptuple(self->stack, i)) != NULL) {
+ if ((args = Pdata_poptuple(state, self->stack, i)) != NULL) {
obj = instantiate(cls, args);
Py_DECREF(args);
}
@@ -5887,16 +5873,16 @@ load_inst(UnpicklerObject *self)
}
static void
-newobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg)
+newobj_unpickling_error(PickleState *st, const char *msg, int use_kwargs,
+ PyObject *arg)
{
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError, msg,
use_kwargs ? "NEWOBJ_EX" : "NEWOBJ",
Py_TYPE(arg)->tp_name);
}
static int
-load_newobj(UnpicklerObject *self, int use_kwargs)
+load_newobj(PickleState *state, UnpicklerObject *self, int use_kwargs)
{
PyObject *cls, *args, *kwargs = NULL;
PyObject *obj;
@@ -5905,17 +5891,17 @@ load_newobj(UnpicklerObject *self, int use_kwargs)
* cls.__new__(cls, *args, **kwargs).
*/
if (use_kwargs) {
- PDATA_POP(self->stack, kwargs);
+ PDATA_POP(state, self->stack, kwargs);
if (kwargs == NULL) {
return -1;
}
}
- PDATA_POP(self->stack, args);
+ PDATA_POP(state, self->stack, args);
if (args == NULL) {
Py_XDECREF(kwargs);
return -1;
}
- PDATA_POP(self->stack, cls);
+ PDATA_POP(state, self->stack, cls);
if (cls == NULL) {
Py_XDECREF(kwargs);
Py_DECREF(args);
@@ -5923,22 +5909,26 @@ load_newobj(UnpicklerObject *self, int use_kwargs)
}
if (!PyType_Check(cls)) {
- newobj_unpickling_error("%s class argument must be a type, not %.200s",
+ newobj_unpickling_error(state,
+ "%s class argument must be a type, not %.200s",
use_kwargs, cls);
goto error;
}
if (((PyTypeObject *)cls)->tp_new == NULL) {
- newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__",
+ newobj_unpickling_error(state,
+ "%s class argument '%.200s' doesn't have __new__",
use_kwargs, cls);
goto error;
}
if (!PyTuple_Check(args)) {
- newobj_unpickling_error("%s args argument must be a tuple, not %.200s",
+ newobj_unpickling_error(state,
+ "%s args argument must be a tuple, not %.200s",
use_kwargs, args);
goto error;
}
if (use_kwargs && !PyDict_Check(kwargs)) {
- newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s",
+ newobj_unpickling_error(state,
+ "%s kwargs argument must be a dict, not %.200s",
use_kwargs, kwargs);
goto error;
}
@@ -5961,7 +5951,7 @@ error:
}
static int
-load_global(UnpicklerObject *self)
+load_global(PickleState *state, UnpicklerObject *self)
{
PyObject *global = NULL;
PyObject *module_name;
@@ -5969,18 +5959,18 @@ load_global(UnpicklerObject *self)
Py_ssize_t len;
char *s;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
module_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
if (!module_name)
return -1;
- if ((len = _Unpickler_Readline(self, &s)) >= 0) {
+ if ((len = _Unpickler_Readline(state, self, &s)) >= 0) {
if (len < 2) {
Py_DECREF(module_name);
- return bad_readline();
+ return bad_readline(state);
}
global_name = PyUnicode_DecodeUTF8(s, len - 1, "strict");
if (global_name) {
@@ -5997,17 +5987,16 @@ load_global(UnpicklerObject *self)
}
static int
-load_stack_global(UnpicklerObject *self)
+load_stack_global(PickleState *st, UnpicklerObject *self)
{
PyObject *global;
PyObject *module_name;
PyObject *global_name;
- PDATA_POP(self->stack, global_name);
- PDATA_POP(self->stack, module_name);
+ PDATA_POP(st, self->stack, global_name);
+ PDATA_POP(st, self->stack, module_name);
if (module_name == NULL || !PyUnicode_CheckExact(module_name) ||
global_name == NULL || !PyUnicode_CheckExact(global_name)) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str");
Py_XDECREF(global_name);
Py_XDECREF(module_name);
@@ -6023,22 +6012,22 @@ load_stack_global(UnpicklerObject *self)
}
static int
-load_persid(UnpicklerObject *self)
+load_persid(PickleState *st, UnpicklerObject *self)
{
PyObject *pid, *obj;
Py_ssize_t len;
char *s;
if (self->pers_func) {
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(st, self, &s)) < 0)
return -1;
if (len < 1)
- return bad_readline();
+ return bad_readline(st);
pid = PyUnicode_DecodeASCII(s, len - 1, "strict");
if (pid == NULL) {
if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
- PyErr_SetString(_Pickle_GetGlobalState()->UnpicklingError,
+ PyErr_SetString(st->UnpicklingError,
"persistent IDs in protocol 0 must be "
"ASCII strings");
}
@@ -6054,7 +6043,6 @@ load_persid(UnpicklerObject *self)
return 0;
}
else {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"A load persistent id instruction was encountered, "
"but no persistent_load function was specified.");
@@ -6063,12 +6051,12 @@ load_persid(UnpicklerObject *self)
}
static int
-load_binpersid(UnpicklerObject *self)
+load_binpersid(PickleState *st, UnpicklerObject *self)
{
PyObject *pid, *obj;
if (self->pers_func) {
- PDATA_POP(self->stack, pid);
+ PDATA_POP(st, self->stack, pid);
if (pid == NULL)
return -1;
@@ -6081,7 +6069,6 @@ load_binpersid(UnpicklerObject *self)
return 0;
}
else {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"A load persistent id instruction was encountered, "
"but no persistent_load function was specified.");
@@ -6090,7 +6077,7 @@ load_binpersid(UnpicklerObject *self)
}
static int
-load_pop(UnpicklerObject *self)
+load_pop(PickleState *state, UnpicklerObject *self)
{
Py_ssize_t len = Py_SIZE(self->stack);
@@ -6107,7 +6094,7 @@ load_pop(UnpicklerObject *self)
self->stack->fence = self->num_marks ?
self->marks[self->num_marks - 1] : 0;
} else if (len <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
else {
len--;
Py_DECREF(self->stack->data[len]);
@@ -6117,11 +6104,10 @@ load_pop(UnpicklerObject *self)
}
static int
-load_pop_mark(UnpicklerObject *self)
+load_pop_mark(PickleState *state, UnpicklerObject *self)
{
Py_ssize_t i;
-
- if ((i = marker(self)) < 0)
+ if ((i = marker(state, self)) < 0)
return -1;
Pdata_clear(self->stack, i);
@@ -6130,30 +6116,30 @@ load_pop_mark(UnpicklerObject *self)
}
static int
-load_dup(UnpicklerObject *self)
+load_dup(PickleState *state, UnpicklerObject *self)
{
PyObject *last;
Py_ssize_t len = Py_SIZE(self->stack);
if (len <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
last = self->stack->data[len - 1];
PDATA_APPEND(self->stack, last, -1);
return 0;
}
static int
-load_get(UnpicklerObject *self)
+load_get(PickleState *st, UnpicklerObject *self)
{
PyObject *key, *value;
Py_ssize_t idx;
Py_ssize_t len;
char *s;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(st, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(st);
key = PyLong_FromString(s, NULL, 10);
if (key == NULL)
@@ -6167,7 +6153,6 @@ load_get(UnpicklerObject *self)
value = _Unpickler_MemoGet(self, idx);
if (value == NULL) {
if (!PyErr_Occurred()) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
}
Py_DECREF(key);
@@ -6180,13 +6165,13 @@ load_get(UnpicklerObject *self)
}
static int
-load_binget(UnpicklerObject *self)
+load_binget(PickleState *st, UnpicklerObject *self)
{
PyObject *value;
Py_ssize_t idx;
char *s;
- if (_Unpickler_Read(self, &s, 1) < 0)
+ if (_Unpickler_Read(self, st, &s, 1) < 0)
return -1;
idx = Py_CHARMASK(s[0]);
@@ -6195,7 +6180,6 @@ load_binget(UnpicklerObject *self)
if (value == NULL) {
PyObject *key = PyLong_FromSsize_t(idx);
if (key != NULL) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
Py_DECREF(key);
}
@@ -6207,13 +6191,13 @@ load_binget(UnpicklerObject *self)
}
static int
-load_long_binget(UnpicklerObject *self)
+load_long_binget(PickleState *st, UnpicklerObject *self)
{
PyObject *value;
Py_ssize_t idx;
char *s;
- if (_Unpickler_Read(self, &s, 4) < 0)
+ if (_Unpickler_Read(self, st, &s, 4) < 0)
return -1;
idx = calc_binsize(s, 4);
@@ -6222,7 +6206,6 @@ load_long_binget(UnpicklerObject *self)
if (value == NULL) {
PyObject *key = PyLong_FromSsize_t(idx);
if (key != NULL) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx);
Py_DECREF(key);
}
@@ -6237,7 +6220,7 @@ load_long_binget(UnpicklerObject *self)
* the number of bytes following the opcode, holding the index (code) value.
*/
static int
-load_extension(UnpicklerObject *self, int nbytes)
+load_extension(PickleState *st, UnpicklerObject *self, int nbytes)
{
char *codebytes; /* the nbytes bytes after the opcode */
long code; /* calc_binint returns long */
@@ -6245,10 +6228,9 @@ load_extension(UnpicklerObject *self, int nbytes)
PyObject *obj; /* the object to push */
PyObject *pair; /* (module_name, class_name) */
PyObject *module_name, *class_name;
- PickleState *st = _Pickle_GetGlobalState();
assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
- if (_Unpickler_Read(self, &codebytes, nbytes) < 0)
+ if (_Unpickler_Read(self, st, &codebytes, nbytes) < 0)
return -1;
code = calc_binint(codebytes, nbytes);
if (code <= 0) { /* note that 0 is forbidden */
@@ -6324,19 +6306,19 @@ error:
}
static int
-load_put(UnpicklerObject *self)
+load_put(PickleState *state, UnpicklerObject *self)
{
PyObject *key, *value;
Py_ssize_t idx;
Py_ssize_t len;
char *s = NULL;
- if ((len = _Unpickler_Readline(self, &s)) < 0)
+ if ((len = _Unpickler_Readline(state, self, &s)) < 0)
return -1;
if (len < 2)
- return bad_readline();
+ return bad_readline(state);
if (Py_SIZE(self->stack) <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
value = self->stack->data[Py_SIZE(self->stack) - 1];
key = PyLong_FromString(s, NULL, 10);
@@ -6355,17 +6337,17 @@ load_put(UnpicklerObject *self)
}
static int
-load_binput(UnpicklerObject *self)
+load_binput(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
Py_ssize_t idx;
char *s;
- if (_Unpickler_Read(self, &s, 1) < 0)
+ if (_Unpickler_Read(self, state, &s, 1) < 0)
return -1;
if (Py_SIZE(self->stack) <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
value = self->stack->data[Py_SIZE(self->stack) - 1];
idx = Py_CHARMASK(s[0]);
@@ -6374,17 +6356,17 @@ load_binput(UnpicklerObject *self)
}
static int
-load_long_binput(UnpicklerObject *self)
+load_long_binput(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
Py_ssize_t idx;
char *s;
- if (_Unpickler_Read(self, &s, 4) < 0)
+ if (_Unpickler_Read(self, state, &s, 4) < 0)
return -1;
if (Py_SIZE(self->stack) <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
value = self->stack->data[Py_SIZE(self->stack) - 1];
idx = calc_binsize(s, 4);
@@ -6398,19 +6380,19 @@ load_long_binput(UnpicklerObject *self)
}
static int
-load_memoize(UnpicklerObject *self)
+load_memoize(PickleState *state, UnpicklerObject *self)
{
PyObject *value;
if (Py_SIZE(self->stack) <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
value = self->stack->data[Py_SIZE(self->stack) - 1];
return _Unpickler_MemoPut(self, self->memo_len, value);
}
static int
-do_append(UnpicklerObject *self, Py_ssize_t x)
+do_append(PickleState *state, UnpicklerObject *self, Py_ssize_t x)
{
PyObject *value;
PyObject *slice;
@@ -6420,7 +6402,7 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
len = Py_SIZE(self->stack);
if (x > len || x <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
if (len == x) /* nothing to do */
return 0;
@@ -6485,24 +6467,24 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
}
static int
-load_append(UnpicklerObject *self)
+load_append(PickleState *state, UnpicklerObject *self)
{
if (Py_SIZE(self->stack) - 1 <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
- return do_append(self, Py_SIZE(self->stack) - 1);
+ return Pdata_stack_underflow(state, self->stack);
+ return do_append(state, self, Py_SIZE(self->stack) - 1);
}
static int
-load_appends(UnpicklerObject *self)
+load_appends(PickleState *state, UnpicklerObject *self)
{
- Py_ssize_t i = marker(self);
+ Py_ssize_t i = marker(state, self);
if (i < 0)
return -1;
- return do_append(self, i);
+ return do_append(state, self, i);
}
static int
-do_setitems(UnpicklerObject *self, Py_ssize_t x)
+do_setitems(PickleState *st, UnpicklerObject *self, Py_ssize_t x)
{
PyObject *value, *key;
PyObject *dict;
@@ -6511,11 +6493,10 @@ do_setitems(UnpicklerObject *self, Py_ssize_t x)
len = Py_SIZE(self->stack);
if (x > len || x <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(st, self->stack);
if (len == x) /* nothing to do */
return 0;
if ((len - x) % 2 != 0) {
- PickleState *st = _Pickle_GetGlobalState();
/* Corrupt or hostile pickle -- we never write one like this. */
PyErr_SetString(st->UnpicklingError,
"odd number of items for SETITEMS");
@@ -6540,32 +6521,32 @@ do_setitems(UnpicklerObject *self, Py_ssize_t x)
}
static int
-load_setitem(UnpicklerObject *self)
+load_setitem(PickleState *state, UnpicklerObject *self)
{
- return do_setitems(self, Py_SIZE(self->stack) - 2);
+ return do_setitems(state, self, Py_SIZE(self->stack) - 2);
}
static int
-load_setitems(UnpicklerObject *self)
+load_setitems(PickleState *state, UnpicklerObject *self)
{
- Py_ssize_t i = marker(self);
+ Py_ssize_t i = marker(state, self);
if (i < 0)
return -1;
- return do_setitems(self, i);
+ return do_setitems(state, self, i);
}
static int
-load_additems(UnpicklerObject *self)
+load_additems(PickleState *state, UnpicklerObject *self)
{
PyObject *set;
Py_ssize_t mark, len, i;
- mark = marker(self);
+ mark = marker(state, self);
if (mark < 0)
return -1;
len = Py_SIZE(self->stack);
if (mark > len || mark <= self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(state, self->stack);
if (len == mark) /* nothing to do */
return 0;
@@ -6575,7 +6556,7 @@ load_additems(UnpicklerObject *self)
PyObject *items;
int status;
- items = Pdata_poptuple(self->stack, mark);
+ items = Pdata_poptuple(state, self->stack, mark);
if (items == NULL)
return -1;
@@ -6609,9 +6590,9 @@ load_additems(UnpicklerObject *self)
}
static int
-load_build(UnpicklerObject *self)
+load_build(PickleState *st, UnpicklerObject *self)
{
- PyObject *state, *inst, *slotstate;
+ PyObject *inst, *slotstate;
PyObject *setstate;
int status = 0;
@@ -6619,9 +6600,10 @@ load_build(UnpicklerObject *self)
* the stack top, possibly mutated via instance.__setstate__(state).
*/
if (Py_SIZE(self->stack) - 2 < self->stack->fence)
- return Pdata_stack_underflow(self->stack);
+ return Pdata_stack_underflow(st, self->stack);
- PDATA_POP(self->stack, state);
+ PyObject *state;
+ PDATA_POP(st, self->stack, state);
if (state == NULL)
return -1;
@@ -6665,7 +6647,6 @@ load_build(UnpicklerObject *self)
Py_ssize_t i;
if (!PyDict_Check(state)) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "state is not a dictionary");
goto error;
}
@@ -6695,7 +6676,6 @@ load_build(UnpicklerObject *self)
Py_ssize_t i;
if (!PyDict_Check(slotstate)) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError,
"slot state is not a dictionary");
goto error;
@@ -6718,7 +6698,7 @@ load_build(UnpicklerObject *self)
}
static int
-load_mark(UnpicklerObject *self)
+load_mark(PickleState *state, UnpicklerObject *self)
{
/* Note that we split the (pickle.py) stack into two stacks, an
@@ -6745,16 +6725,16 @@ load_mark(UnpicklerObject *self)
}
static int
-load_reduce(UnpicklerObject *self)
+load_reduce(PickleState *state, UnpicklerObject *self)
{
PyObject *callable = NULL;
PyObject *argtup = NULL;
PyObject *obj = NULL;
- PDATA_POP(self->stack, argtup);
+ PDATA_POP(state, self->stack, argtup);
if (argtup == NULL)
return -1;
- PDATA_POP(self->stack, callable);
+ PDATA_POP(state, self->stack, callable);
if (callable) {
obj = PyObject_CallObject(callable, argtup);
Py_DECREF(callable);
@@ -6772,12 +6752,12 @@ load_reduce(UnpicklerObject *self)
* is the first opcode for protocols >= 2.
*/
static int
-load_proto(UnpicklerObject *self)
+load_proto(PickleState *state, UnpicklerObject *self)
{
char *s;
int i;
- if (_Unpickler_Read(self, &s, 1) < 0)
+ if (_Unpickler_Read(self, state, &s, 1) < 0)
return -1;
i = (unsigned char)s[0];
@@ -6791,12 +6771,12 @@ load_proto(UnpicklerObject *self)
}
static int
-load_frame(UnpicklerObject *self)
+load_frame(PickleState *state, UnpicklerObject *self)
{
char *s;
Py_ssize_t frame_len;
- if (_Unpickler_Read(self, &s, 8) < 0)
+ if (_Unpickler_Read(self, state, &s, 8) < 0)
return -1;
frame_len = calc_binsize(s, 8);
@@ -6807,7 +6787,7 @@ load_frame(UnpicklerObject *self)
return -1;
}
- if (_Unpickler_Read(self, &s, frame_len) < 0)
+ if (_Unpickler_Read(self, state, &s, frame_len) < 0)
return -1;
/* Rewind to start of frame */
@@ -6816,7 +6796,7 @@ load_frame(UnpicklerObject *self)
}
static PyObject *
-load(UnpicklerObject *self)
+load(PickleState *st, UnpicklerObject *self)
{
PyObject *value = NULL;
char *s = NULL;
@@ -6830,14 +6810,13 @@ load(UnpicklerObject *self)
/* Convenient macros for the dispatch while-switch loop just below. */
#define OP(opcode, load_func) \
- case opcode: if (load_func(self) < 0) break; continue;
+ case opcode: if (load_func(st, self) < 0) break; continue;
#define OP_ARG(opcode, load_func, arg) \
- case opcode: if (load_func(self, (arg)) < 0) break; continue;
+ case opcode: if (load_func(st, self, (arg)) < 0) break; continue;
while (1) {
- if (_Unpickler_Read(self, &s, 1) < 0) {
- PickleState *st = _Pickle_GetGlobalState();
+ if (_Unpickler_Read(self, st, &s, 1) < 0) {
if (PyErr_ExceptionMatches(st->UnpicklingError)) {
PyErr_Format(PyExc_EOFError, "Ran out of input");
}
@@ -6918,7 +6897,6 @@ load(UnpicklerObject *self)
default:
{
- PickleState *st = _Pickle_GetGlobalState();
unsigned char c = (unsigned char) *s;
if (0x20 <= c && c <= 0x7e && c != '\'' && c != '\\') {
PyErr_Format(st->UnpicklingError,
@@ -6942,7 +6920,7 @@ load(UnpicklerObject *self)
if (_Unpickler_SkipConsumed(self) < 0)
return NULL;
- PDATA_POP(self->stack, value);
+ PDATA_POP(st, self->stack, value);
return value;
}
@@ -6950,6 +6928,8 @@ load(UnpicklerObject *self)
_pickle.Unpickler.load
+ cls: defining_class
+
Load a pickle.
Read a pickled object representation from the open file object given
@@ -6958,24 +6938,25 @@ specified therein.
[clinic start generated code]*/
static PyObject *
-_pickle_Unpickler_load_impl(UnpicklerObject *self)
-/*[clinic end generated code: output=fdcc488aad675b14 input=acbb91a42fa9b7b9]*/
+_pickle_Unpickler_load_impl(UnpicklerObject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=cc88168f608e3007 input=f5d2f87e61d5f07f]*/
{
UnpicklerObject *unpickler = (UnpicklerObject*)self;
+ PickleState *st = _Pickle_GetStateByClass(cls);
+
/* Check whether the Unpickler was initialized correctly. This prevents
segfaulting if a subclass overridden __init__ with a function that does
not call Unpickler.__init__(). Here, we simply ensure that self->read
is not NULL. */
if (unpickler->read == NULL) {
- PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->UnpicklingError,
"Unpickler.__init__() was not called by %s.__init__()",
Py_TYPE(unpickler)->tp_name);
return NULL;
}
- return load(unpickler);
+ return load(st, unpickler);
}
/* The name of find_class() is misleading. In newer pickle protocols, this
@@ -6986,6 +6967,7 @@ _pickle_Unpickler_load_impl(UnpicklerObject *self)
_pickle.Unpickler.find_class
+ cls: defining_class
module_name: object
global_name: object
/
@@ -7001,10 +6983,10 @@ needed. Both arguments passed are str objects.
[clinic start generated code]*/
static PyObject *
-_pickle_Unpickler_find_class_impl(UnpicklerObject *self,
+_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyTypeObject *cls,
PyObject *module_name,
PyObject *global_name)
-/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/
+/*[clinic end generated code: output=99577948abb0be81 input=9577745719219fc7]*/
{
PyObject *global;
PyObject *module;
@@ -7020,7 +7002,7 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
if (self->proto < 3 && self->fix_imports) {
PyObject *key;
PyObject *item;
- PickleState *st = _Pickle_GetGlobalState();
+ PickleState *st = _Pickle_GetStateByClass(cls);
/* Check if the global (i.e., a function or a class) was renamed
or moved to another module. */
@@ -7114,44 +7096,6 @@ static struct PyMethodDef Unpickler_methods[] = {
{NULL, NULL} /* sentinel */
};
-static void
-Unpickler_dealloc(UnpicklerObject *self)
-{
- PyObject_GC_UnTrack((PyObject *)self);
- Py_XDECREF(self->readline);
- Py_XDECREF(self->readinto);
- Py_XDECREF(self->read);
- Py_XDECREF(self->peek);
- Py_XDECREF(self->stack);
- Py_XDECREF(self->pers_func);
- Py_XDECREF(self->buffers);
- if (self->buffer.buf != NULL) {
- PyBuffer_Release(&self->buffer);
- self->buffer.buf = NULL;
- }
-
- _Unpickler_MemoCleanup(self);
- PyMem_Free(self->marks);
- PyMem_Free(self->input_line);
- PyMem_Free(self->encoding);
- PyMem_Free(self->errors);
-
- Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static int
-Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->readline);
- Py_VISIT(self->readinto);
- Py_VISIT(self->read);
- Py_VISIT(self->peek);
- Py_VISIT(self->stack);
- Py_VISIT(self->pers_func);
- Py_VISIT(self->buffers);
- return 0;
-}
-
static int
Unpickler_clear(UnpicklerObject *self)
{
@@ -7180,6 +7124,30 @@ Unpickler_clear(UnpicklerObject *self)
return 0;
}
+static void
+Unpickler_dealloc(UnpicklerObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_GC_UnTrack((PyObject *)self);
+ (void)Unpickler_clear(self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
+}
+
+static int
+Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(self));
+ Py_VISIT(self->readline);
+ Py_VISIT(self->readinto);
+ Py_VISIT(self->read);
+ Py_VISIT(self->peek);
+ Py_VISIT(self->stack);
+ Py_VISIT(self->pers_func);
+ Py_VISIT(self->buffers);
+ return 0;
+}
+
/*[clinic input]
_pickle.Unpickler.__init__
@@ -7240,7 +7208,9 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
return -1;
}
- self->stack = (Pdata *)Pdata_New();
+ PyTypeObject *tp = Py_TYPE(self);
+ PickleState *state = _Pickle_FindStateByType(tp);
+ self->stack = (Pdata *)Pdata_New(state);
if (self->stack == NULL)
return -1;
@@ -7366,15 +7336,18 @@ static PyMethodDef unpicklerproxy_methods[] = {
static void
UnpicklerMemoProxy_dealloc(UnpicklerMemoProxyObject *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- Py_XDECREF(self->unpickler);
- PyObject_GC_Del((PyObject *)self);
+ Py_CLEAR(self->unpickler);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static int
UnpicklerMemoProxy_traverse(UnpicklerMemoProxyObject *self,
visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->unpickler);
return 0;
}
@@ -7386,44 +7359,30 @@ UnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self)
return 0;
}
-static PyTypeObject UnpicklerMemoProxyType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_pickle.UnpicklerMemoProxy", /*tp_name*/
- sizeof(UnpicklerMemoProxyObject), /*tp_basicsize*/
- 0,
- (destructor)UnpicklerMemoProxy_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- PyObject_HashNotImplemented, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- 0, /* tp_doc */
- (traverseproc)UnpicklerMemoProxy_traverse, /* tp_traverse */
- (inquiry)UnpicklerMemoProxy_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- unpicklerproxy_methods, /* tp_methods */
+static PyType_Slot unpickler_memoproxy_slots[] = {
+ {Py_tp_dealloc, UnpicklerMemoProxy_dealloc},
+ {Py_tp_traverse, UnpicklerMemoProxy_traverse},
+ {Py_tp_clear, UnpicklerMemoProxy_clear},
+ {Py_tp_methods, unpicklerproxy_methods},
+ {Py_tp_hash, PyObject_HashNotImplemented},
+ {0, NULL},
+};
+
+static PyType_Spec unpickler_memoproxy_spec = {
+ .name = "_pickle.UnpicklerMemoProxy",
+ .basicsize = sizeof(UnpicklerMemoProxyObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = unpickler_memoproxy_slots,
};
static PyObject *
UnpicklerMemoProxy_New(UnpicklerObject *unpickler)
{
+ PickleState *state = _Pickle_FindStateByType(Py_TYPE(unpickler));
UnpicklerMemoProxyObject *self;
-
self = PyObject_GC_New(UnpicklerMemoProxyObject,
- &UnpicklerMemoProxyType);
+ state->UnpicklerMemoProxyType);
if (self == NULL)
return NULL;
self->unpickler = (UnpicklerObject*)Py_NewRef(unpickler);
@@ -7452,7 +7411,8 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored
return -1;
}
- if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) {
+ PickleState *state = _Pickle_FindStateByType(Py_TYPE(self));
+ if (Py_IS_TYPE(obj, state->UnpicklerMemoProxyType)) {
UnpicklerObject *unpickler =
((UnpicklerMemoProxyObject *)obj)->unpickler;
@@ -7554,47 +7514,26 @@ static PyGetSetDef Unpickler_getsets[] = {
{NULL}
};
-static PyTypeObject Unpickler_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_pickle.Unpickler", /*tp_name*/
- sizeof(UnpicklerObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)Unpickler_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- _pickle_Unpickler___init____doc__, /*tp_doc*/
- (traverseproc)Unpickler_traverse, /*tp_traverse*/
- (inquiry)Unpickler_clear, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- Unpickler_methods, /*tp_methods*/
- 0, /*tp_members*/
- Unpickler_getsets, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- _pickle_Unpickler___init__, /*tp_init*/
- PyType_GenericAlloc, /*tp_alloc*/
- PyType_GenericNew, /*tp_new*/
- PyObject_GC_Del, /*tp_free*/
- 0, /*tp_is_gc*/
+static PyType_Slot unpickler_type_slots[] = {
+ {Py_tp_dealloc, Unpickler_dealloc},
+ {Py_tp_doc, (char *)_pickle_Unpickler___init____doc__},
+ {Py_tp_traverse, Unpickler_traverse},
+ {Py_tp_clear, Unpickler_clear},
+ {Py_tp_methods, Unpickler_methods},
+ {Py_tp_getset, Unpickler_getsets},
+ {Py_tp_init, _pickle_Unpickler___init__},
+ {Py_tp_alloc, PyType_GenericAlloc},
+ {Py_tp_new, PyType_GenericNew},
+ {Py_tp_free, PyObject_GC_Del},
+ {0, NULL},
+};
+
+static PyType_Spec unpickler_type_spec = {
+ .name = "_pickle.Unpickler",
+ .basicsize = sizeof(UnpicklerObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = unpickler_type_slots,
};
/*[clinic input]
@@ -7643,7 +7582,8 @@ _pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file,
PyObject *buffer_callback)
/*[clinic end generated code: output=706186dba996490c input=5ed6653da99cd97c]*/
{
- PicklerObject *pickler = _Pickler_New();
+ PickleState *state = _Pickle_GetState(module);
+ PicklerObject *pickler = _Pickler_New(state);
if (pickler == NULL)
return NULL;
@@ -7657,7 +7597,7 @@ _pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file,
if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
goto error;
- if (dump(pickler, obj) < 0)
+ if (dump(state, pickler, obj) < 0)
goto error;
if (_Pickler_FlushToFile(pickler) < 0)
@@ -7708,7 +7648,8 @@ _pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol,
/*[clinic end generated code: output=fbab0093a5580fdf input=e543272436c6f987]*/
{
PyObject *result;
- PicklerObject *pickler = _Pickler_New();
+ PickleState *state = _Pickle_GetState(module);
+ PicklerObject *pickler = _Pickler_New(state);
if (pickler == NULL)
return NULL;
@@ -7719,7 +7660,7 @@ _pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol,
if (_Pickler_SetBufferCallback(pickler, buffer_callback) < 0)
goto error;
- if (dump(pickler, obj) < 0)
+ if (dump(state, pickler, obj) < 0)
goto error;
result = _Pickler_GetString(pickler);
@@ -7774,7 +7715,7 @@ _pickle_load_impl(PyObject *module, PyObject *file, int fix_imports,
/*[clinic end generated code: output=250452d141c23e76 input=46c7c31c92f4f371]*/
{
PyObject *result;
- UnpicklerObject *unpickler = _Unpickler_New();
+ UnpicklerObject *unpickler = _Unpickler_New(module);
if (unpickler == NULL)
return NULL;
@@ -7790,7 +7731,8 @@ _pickle_load_impl(PyObject *module, PyObject *file, int fix_imports,
unpickler->fix_imports = fix_imports;
- result = load(unpickler);
+ PickleState *state = _Pickle_GetState(module);
+ result = load(state, unpickler);
Py_DECREF(unpickler);
return result;
@@ -7834,7 +7776,7 @@ _pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports,
/*[clinic end generated code: output=82ac1e6b588e6d02 input=b3615540d0535087]*/
{
PyObject *result;
- UnpicklerObject *unpickler = _Unpickler_New();
+ UnpicklerObject *unpickler = _Unpickler_New(module);
if (unpickler == NULL)
return NULL;
@@ -7850,7 +7792,8 @@ _pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports,
unpickler->fix_imports = fix_imports;
- result = load(unpickler);
+ PickleState *state = _Pickle_GetState(module);
+ result = load(state, unpickler);
Py_DECREF(unpickler);
return result;
@@ -7898,81 +7841,94 @@ pickle_traverse(PyObject *m, visitproc visit, void *arg)
Py_VISIT(st->codecs_encode);
Py_VISIT(st->getattr);
Py_VISIT(st->partial);
+ Py_VISIT(st->Pickler_Type);
+ Py_VISIT(st->Unpickler_Type);
+ Py_VISIT(st->Pdata_Type);
+ Py_VISIT(st->PicklerMemoProxyType);
+ Py_VISIT(st->UnpicklerMemoProxyType);
return 0;
}
-static struct PyModuleDef _picklemodule = {
- PyModuleDef_HEAD_INIT,
- "_pickle", /* m_name */
- pickle_module_doc, /* m_doc */
- sizeof(PickleState), /* m_size */
- pickle_methods, /* m_methods */
- NULL, /* m_reload */
- pickle_traverse, /* m_traverse */
- pickle_clear, /* m_clear */
- (freefunc)pickle_free /* m_free */
-};
-
-PyMODINIT_FUNC
-PyInit__pickle(void)
+static int
+_pickle_exec(PyObject *m)
{
- PyObject *m;
- PickleState *st;
+ PickleState *st = _Pickle_GetState(m);
- m = PyState_FindModule(&_picklemodule);
- if (m) {
- return Py_NewRef(m);
- }
+#define CREATE_TYPE(mod, type, spec) \
+ do { \
+ type = (PyTypeObject *)PyType_FromMetaclass(NULL, mod, spec, NULL); \
+ if (type == NULL) { \
+ return -1; \
+ } \
+ } while (0)
- if (PyType_Ready(&Pdata_Type) < 0)
- return NULL;
- if (PyType_Ready(&PicklerMemoProxyType) < 0)
- return NULL;
- if (PyType_Ready(&UnpicklerMemoProxyType) < 0)
- return NULL;
+ CREATE_TYPE(m, st->Pdata_Type, &pdata_spec);
+ CREATE_TYPE(m, st->PicklerMemoProxyType, &memoproxy_spec);
+ CREATE_TYPE(m, st->UnpicklerMemoProxyType, &unpickler_memoproxy_spec);
+ CREATE_TYPE(m, st->Pickler_Type, &pickler_type_spec);
+ CREATE_TYPE(m, st->Unpickler_Type, &unpickler_type_spec);
- /* Create the module and add the functions. */
- m = PyModule_Create(&_picklemodule);
- if (m == NULL)
- return NULL;
+#undef CREATE_TYPE
/* Add types */
- if (PyModule_AddType(m, &Pickler_Type) < 0) {
- return NULL;
+ if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) {
+ return -1;
}
- if (PyModule_AddType(m, &Unpickler_Type) < 0) {
- return NULL;
+ if (PyModule_AddType(m, st->Pickler_Type) < 0) {
+ return -1;
}
- if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) {
- return NULL;
+ if (PyModule_AddType(m, st->Unpickler_Type) < 0) {
+ return -1;
}
- st = _Pickle_GetState(m);
-
/* Initialize the exceptions. */
st->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL);
if (st->PickleError == NULL)
- return NULL;
+ return -1;
st->PicklingError = \
PyErr_NewException("_pickle.PicklingError", st->PickleError, NULL);
if (st->PicklingError == NULL)
- return NULL;
+ return -1;
st->UnpicklingError = \
PyErr_NewException("_pickle.UnpicklingError", st->PickleError, NULL);
if (st->UnpicklingError == NULL)
- return NULL;
+ return -1;
if (PyModule_AddObjectRef(m, "PickleError", st->PickleError) < 0) {
- return NULL;
+ return -1;
}
if (PyModule_AddObjectRef(m, "PicklingError", st->PicklingError) < 0) {
- return NULL;
+ return -1;
}
if (PyModule_AddObjectRef(m, "UnpicklingError", st->UnpicklingError) < 0) {
- return NULL;
+ return -1;
}
+
if (_Pickle_InitState(st) < 0)
- return NULL;
+ return -1;
- return m;
+ return 0;
+}
+
+static PyModuleDef_Slot pickle_slots[] = {
+ {Py_mod_exec, _pickle_exec},
+ {0, NULL},
+};
+
+static struct PyModuleDef _picklemodule = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_pickle",
+ .m_doc = pickle_module_doc,
+ .m_size = sizeof(PickleState),
+ .m_methods = pickle_methods,
+ .m_slots = pickle_slots,
+ .m_traverse = pickle_traverse,
+ .m_clear = pickle_clear,
+ .m_free = (freefunc)pickle_free,
+};
+
+PyMODINIT_FUNC
+PyInit__pickle(void)
+{
+ return PyModuleDef_Init(&_picklemodule);
}