[Python-checkins] [3.12] gh-105375: Explicitly initialise all {Pickler, Unpickler}Object fields (GH-105686) (#105710)

erlend-aasland webhook-mailer at python.org
Mon Jun 12 18:12:24 EDT 2023


https://github.com/python/cpython/commit/017b9595d4060521f93804d5dd555b6cd6585578
commit: 017b9595d4060521f93804d5dd555b6cd6585578
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-06-12T22:12:17Z
summary:

[3.12] gh-105375: Explicitly initialise all {Pickler,Unpickler}Object 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 ca3cc4b95d66f7527ebe0ba4cdb1907082d9bfc8)

Co-authored-by: Erlend E. Aasland <erlend.aasland at protonmail.com>

files:
M Modules/_pickle.c

diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index d6a273b1044e..688bccbab6b4 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -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
@@ -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;
@@ -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



More information about the Python-checkins mailing list