Skip to content

Commit 04b76ec

Browse files
[3.12] gh-105375: Improve _pickle error handling (#105475) (#105584)
(cherry picked from commit 89aac6f) Error handling was deferred in some cases, which could potentially lead to exceptions being overwritten.
1 parent 6540493 commit 04b76ec

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bugs in :mod:`pickle` where exceptions could be overwritten.

Modules/_pickle.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,10 +1168,13 @@ _Pickler_New(PickleState *st)
11681168
self->reducer_override = NULL;
11691169

11701170
self->memo = PyMemoTable_New();
1171+
if (self->memo == NULL) {
1172+
Py_DECREF(self);
1173+
return NULL;
1174+
}
11711175
self->output_buffer = PyBytes_FromStringAndSize(NULL,
11721176
self->max_output_len);
1173-
1174-
if (self->memo == NULL || self->output_buffer == NULL) {
1177+
if (self->output_buffer == NULL) {
11751178
Py_DECREF(self);
11761179
return NULL;
11771180
}
@@ -1654,9 +1657,12 @@ _Unpickler_New(PyObject *module)
16541657
self->memo_size = 32;
16551658
self->memo_len = 0;
16561659
self->memo = _Unpickler_NewMemo(self->memo_size);
1660+
if (self->memo == NULL) {
1661+
Py_DECREF(self);
1662+
return NULL;
1663+
}
16571664
self->stack = (Pdata *)Pdata_New(st);
1658-
1659-
if (self->memo == NULL || self->stack == NULL) {
1665+
if (self->stack == NULL) {
16601666
Py_DECREF(self);
16611667
return NULL;
16621668
}
@@ -4834,11 +4840,12 @@ _pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
48344840
PyObject *key, *value;
48354841

48364842
key = PyLong_FromVoidPtr(entry.me_key);
4843+
if (key == NULL) {
4844+
goto error;
4845+
}
48374846
value = Py_BuildValue("nO", entry.me_value, entry.me_key);
4838-
4839-
if (key == NULL || value == NULL) {
4840-
Py_XDECREF(key);
4841-
Py_XDECREF(value);
4847+
if (value == NULL) {
4848+
Py_DECREF(key);
48424849
goto error;
48434850
}
48444851
status = PyDict_SetItem(new_memo, key, value);
@@ -5994,12 +6001,20 @@ load_stack_global(PickleState *st, UnpicklerObject *self)
59946001
PyObject *global_name;
59956002

59966003
PDATA_POP(st, self->stack, global_name);
6004+
if (global_name == NULL) {
6005+
return -1;
6006+
}
59976007
PDATA_POP(st, self->stack, module_name);
5998-
if (module_name == NULL || !PyUnicode_CheckExact(module_name) ||
5999-
global_name == NULL || !PyUnicode_CheckExact(global_name)) {
6008+
if (module_name == NULL) {
6009+
Py_DECREF(global_name);
6010+
return -1;
6011+
}
6012+
if (!PyUnicode_CheckExact(module_name) ||
6013+
!PyUnicode_CheckExact(global_name))
6014+
{
60006015
PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str");
6001-
Py_XDECREF(global_name);
6002-
Py_XDECREF(module_name);
6016+
Py_DECREF(global_name);
6017+
Py_DECREF(module_name);
60036018
return -1;
60046019
}
60056020
global = find_class(self, module_name, global_name);

0 commit comments

Comments
 (0)