From 78dc9de1416bfb1c7b35ef29230e2024dc0dc3f5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 9 Jun 2023 19:09:53 +0200 Subject: [PATCH] [3.12] 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 bf7ecae0cc0e50..d6a273b1044e44 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1168,10 +1168,13 @@ _Pickler_New(PickleState *st) 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; } @@ -1654,9 +1657,12 @@ _Unpickler_New(PyObject *module) 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->memo == NULL || self->stack == NULL) { + if (self->stack == NULL) { Py_DECREF(self); return NULL; } @@ -4834,11 +4840,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); @@ -5994,12 +6001,20 @@ load_stack_global(PickleState *st, UnpicklerObject *self) PyObject *global_name; PDATA_POP(st, self->stack, global_name); + if (global_name == NULL) { + return -1; + } PDATA_POP(st, 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)) + { 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);