From d5a8288482cd484db0adcd91baa9fb5a6c861521 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 9 Jun 2023 19:09:53 +0200 Subject: [PATCH] [3.11] gh-105375: Improve _pickle error handling (#105475) (cherry picked from commit 89aac6f6b7b3af046ec137121c90732289e79efc) Error handling was deferred in some cases, which could potentially lead to exceptions being overwritten. Co-authored-by: Erlend E. Aasland --- ...-06-08-08-58-36.gh-issue-105375.bTcqS9.rst | 1 + Modules/_pickle.c | 39 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst diff --git a/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst b/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst new file mode 100644 index 00000000000000..3030477c8245b5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-08-08-58-36.gh-issue-105375.bTcqS9.rst @@ -0,0 +1 @@ +Fix bugs in :mod:`pickle` where exceptions could be overwritten. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 721079c91f5f2c..ddabc201a59f89 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1139,10 +1139,13 @@ _Pickler_New(void) 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->memo == NULL || self->output_buffer == NULL) { + if (self->output_buffer == NULL) { Py_DECREF(self); return NULL; } @@ -1627,9 +1630,12 @@ _Unpickler_New(void) 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(); - - if (self->memo == NULL || self->stack == NULL) { + if (self->stack == NULL) { Py_DECREF(self); return NULL; } @@ -4833,11 +4839,12 @@ _pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self) PyObject *key, *value; key = PyLong_FromVoidPtr(entry.me_key); + if (key == NULL) { + goto error; + } value = Py_BuildValue("nO", entry.me_value, entry.me_key); - - if (key == NULL || value == NULL) { - Py_XDECREF(key); - Py_XDECREF(value); + if (value == NULL) { + Py_DECREF(key); goto error; } status = PyDict_SetItem(new_memo, key, value); @@ -6033,13 +6040,21 @@ load_stack_global(UnpicklerObject *self) PyObject *global_name; PDATA_POP(self->stack, global_name); + if (global_name == NULL) { + return -1; + } PDATA_POP(self->stack, module_name); - if (module_name == NULL || !PyUnicode_CheckExact(module_name) || - global_name == NULL || !PyUnicode_CheckExact(global_name)) { + if (module_name == NULL) { + Py_DECREF(global_name); + return -1; + } + if (!PyUnicode_CheckExact(module_name) || + !PyUnicode_CheckExact(global_name)) + { PickleState *st = _Pickle_GetGlobalState(); PyErr_SetString(st->UnpicklingError, "STACK_GLOBAL requires str"); - Py_XDECREF(global_name); - Py_XDECREF(module_name); + Py_DECREF(global_name); + Py_DECREF(module_name); return -1; } global = find_class(self, module_name, global_name);