Skip to content

Commit

Permalink
[3.12] gh-105375: Explicitly initialise all {Pickler,Unpickler}Object…
Browse files Browse the repository at this point in the history
… fields (GH-105686) (#105710)

All fields must be explicitly initialised to prevent manipulation of
uninitialised fields in dealloc.

Align initialisation order with the layout of the object structs.

(cherry picked from commit ca3cc4b)

Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
  • Loading branch information
miss-islington and erlend-aasland committed Jun 12, 2023
1 parent 77bdeeb commit 017b959
Showing 1 changed file with 53 additions and 37 deletions.
90 changes: 53 additions & 37 deletions Modules/_pickle.c
Expand Up @@ -1145,42 +1145,49 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
static PicklerObject *
_Pickler_New(PickleState *st)
{
PicklerObject *self;

self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
if (self == NULL)
PyMemoTable *memo = PyMemoTable_New();
if (memo == NULL) {
return NULL;
}

const Py_ssize_t max_output_len = WRITE_BUF_SIZE;
PyObject *output_buffer = PyBytes_FromStringAndSize(NULL, max_output_len);
if (output_buffer == NULL) {
goto error;
}

PicklerObject *self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
if (self == NULL) {
goto error;
}

self->memo = memo;
self->pers_func = NULL;
self->pers_func_self = NULL;
self->dispatch_table = NULL;
self->buffer_callback = NULL;
self->reducer_override = NULL;
self->write = NULL;
self->output_buffer = output_buffer;
self->output_len = 0;
self->max_output_len = max_output_len;
self->proto = 0;
self->bin = 0;
self->framing = 0;
self->frame_start = -1;
self->buf_size = 0;
self->fast = 0;
self->fast_nesting = 0;
self->fix_imports = 0;
self->fast_memo = NULL;
self->max_output_len = WRITE_BUF_SIZE;
self->output_len = 0;
self->reducer_override = NULL;

self->memo = PyMemoTable_New();
if (self->memo == NULL) {
Py_DECREF(self);
return NULL;
}
self->output_buffer = PyBytes_FromStringAndSize(NULL,
self->max_output_len);
if (self->output_buffer == NULL) {
Py_DECREF(self);
return NULL;
}
self->buffer_callback = NULL;

PyObject_GC_Track(self);
return self;

error:
PyMem_Free(memo);
Py_XDECREF(output_buffer);
return NULL;
}

static int
Expand Down Expand Up @@ -1628,14 +1635,31 @@ _Unpickler_MemoCleanup(UnpicklerObject *self)
static UnpicklerObject *
_Unpickler_New(PyObject *module)
{
UnpicklerObject *self;
const int MEMO_SIZE = 32;
PyObject **memo = _Unpickler_NewMemo(MEMO_SIZE);
if (memo == NULL) {
return NULL;
}

PickleState *st = _Pickle_GetState(module);
PyObject *stack = Pdata_New(st);
if (stack == NULL) {
goto error;
}

self = PyObject_GC_New(UnpicklerObject, st->Unpickler_Type);
if (self == NULL)
return NULL;
UnpicklerObject *self = PyObject_GC_New(UnpicklerObject,
st->Unpickler_Type);
if (self == NULL) {
goto error;
}

self->stack = (Pdata *)stack;
self->memo = memo;
self->memo_size = MEMO_SIZE;
self->memo_len = 0;
self->pers_func = NULL;
self->pers_func_self = NULL;
memset(&self->buffer, 0, sizeof(Py_buffer));
self->input_buffer = NULL;
self->input_line = NULL;
self->input_len = 0;
Expand All @@ -1653,22 +1677,14 @@ _Unpickler_New(PyObject *module)
self->marks_size = 0;
self->proto = 0;
self->fix_imports = 0;
memset(&self->buffer, 0, sizeof(Py_buffer));
self->memo_size = 32;
self->memo_len = 0;
self->memo = _Unpickler_NewMemo(self->memo_size);
if (self->memo == NULL) {
Py_DECREF(self);
return NULL;
}
self->stack = (Pdata *)Pdata_New(st);
if (self->stack == NULL) {
Py_DECREF(self);
return NULL;
}

PyObject_GC_Track(self);
return self;

error:
PyMem_Free(memo);
Py_XDECREF(stack);
return NULL;
}

/* Returns -1 (with an exception set) on failure, 0 on success. This may
Expand Down

0 comments on commit 017b959

Please sign in to comment.