Skip to content

Commit ca3cc4b

Browse files
gh-105375: Explicitly initialise all {Pickler,Unpickler}Object fields (#105686)
All fields must be explicitly initialised to prevent manipulation of uninitialised fields in dealloc. Align initialisation order with the layout of the object structs.
1 parent f0fb782 commit ca3cc4b

File tree

1 file changed

+53
-37
lines changed

1 file changed

+53
-37
lines changed

Modules/_pickle.c

+53-37
Original file line numberDiff line numberDiff line change
@@ -1145,42 +1145,49 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len)
11451145
static PicklerObject *
11461146
_Pickler_New(PickleState *st)
11471147
{
1148-
PicklerObject *self;
1149-
1150-
self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
1151-
if (self == NULL)
1148+
PyMemoTable *memo = PyMemoTable_New();
1149+
if (memo == NULL) {
11521150
return NULL;
1151+
}
1152+
1153+
const Py_ssize_t max_output_len = WRITE_BUF_SIZE;
1154+
PyObject *output_buffer = PyBytes_FromStringAndSize(NULL, max_output_len);
1155+
if (output_buffer == NULL) {
1156+
goto error;
1157+
}
11531158

1159+
PicklerObject *self = PyObject_GC_New(PicklerObject, st->Pickler_Type);
1160+
if (self == NULL) {
1161+
goto error;
1162+
}
1163+
1164+
self->memo = memo;
11541165
self->pers_func = NULL;
1166+
self->pers_func_self = NULL;
11551167
self->dispatch_table = NULL;
1156-
self->buffer_callback = NULL;
1168+
self->reducer_override = NULL;
11571169
self->write = NULL;
1170+
self->output_buffer = output_buffer;
1171+
self->output_len = 0;
1172+
self->max_output_len = max_output_len;
11581173
self->proto = 0;
11591174
self->bin = 0;
11601175
self->framing = 0;
11611176
self->frame_start = -1;
1177+
self->buf_size = 0;
11621178
self->fast = 0;
11631179
self->fast_nesting = 0;
11641180
self->fix_imports = 0;
11651181
self->fast_memo = NULL;
1166-
self->max_output_len = WRITE_BUF_SIZE;
1167-
self->output_len = 0;
1168-
self->reducer_override = NULL;
1169-
1170-
self->memo = PyMemoTable_New();
1171-
if (self->memo == NULL) {
1172-
Py_DECREF(self);
1173-
return NULL;
1174-
}
1175-
self->output_buffer = PyBytes_FromStringAndSize(NULL,
1176-
self->max_output_len);
1177-
if (self->output_buffer == NULL) {
1178-
Py_DECREF(self);
1179-
return NULL;
1180-
}
1182+
self->buffer_callback = NULL;
11811183

11821184
PyObject_GC_Track(self);
11831185
return self;
1186+
1187+
error:
1188+
PyMem_Free(memo);
1189+
Py_XDECREF(output_buffer);
1190+
return NULL;
11841191
}
11851192

11861193
static int
@@ -1628,14 +1635,31 @@ _Unpickler_MemoCleanup(UnpicklerObject *self)
16281635
static UnpicklerObject *
16291636
_Unpickler_New(PyObject *module)
16301637
{
1631-
UnpicklerObject *self;
1638+
const int MEMO_SIZE = 32;
1639+
PyObject **memo = _Unpickler_NewMemo(MEMO_SIZE);
1640+
if (memo == NULL) {
1641+
return NULL;
1642+
}
1643+
16321644
PickleState *st = _Pickle_GetState(module);
1645+
PyObject *stack = Pdata_New(st);
1646+
if (stack == NULL) {
1647+
goto error;
1648+
}
16331649

1634-
self = PyObject_GC_New(UnpicklerObject, st->Unpickler_Type);
1635-
if (self == NULL)
1636-
return NULL;
1650+
UnpicklerObject *self = PyObject_GC_New(UnpicklerObject,
1651+
st->Unpickler_Type);
1652+
if (self == NULL) {
1653+
goto error;
1654+
}
16371655

1656+
self->stack = (Pdata *)stack;
1657+
self->memo = memo;
1658+
self->memo_size = MEMO_SIZE;
1659+
self->memo_len = 0;
16381660
self->pers_func = NULL;
1661+
self->pers_func_self = NULL;
1662+
memset(&self->buffer, 0, sizeof(Py_buffer));
16391663
self->input_buffer = NULL;
16401664
self->input_line = NULL;
16411665
self->input_len = 0;
@@ -1653,22 +1677,14 @@ _Unpickler_New(PyObject *module)
16531677
self->marks_size = 0;
16541678
self->proto = 0;
16551679
self->fix_imports = 0;
1656-
memset(&self->buffer, 0, sizeof(Py_buffer));
1657-
self->memo_size = 32;
1658-
self->memo_len = 0;
1659-
self->memo = _Unpickler_NewMemo(self->memo_size);
1660-
if (self->memo == NULL) {
1661-
Py_DECREF(self);
1662-
return NULL;
1663-
}
1664-
self->stack = (Pdata *)Pdata_New(st);
1665-
if (self->stack == NULL) {
1666-
Py_DECREF(self);
1667-
return NULL;
1668-
}
16691680

16701681
PyObject_GC_Track(self);
16711682
return self;
1683+
1684+
error:
1685+
PyMem_Free(memo);
1686+
Py_XDECREF(stack);
1687+
return NULL;
16721688
}
16731689

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

0 commit comments

Comments
 (0)