From f8e15c1f693127f11327ee0f80334019b0990c5e Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Fri, 22 Nov 2019 10:53:03 +0100 Subject: [PATCH] bpo-38876: Raise pickle.UnpicklingError when loading an item from memo for invalid input The previous code was raising a `KeyError` for both the Python and C implementation. This was caused by the specified index of an invalid input which did not exist in the memo structure, where the pickle stores what objects it has seen. The malformed input would have caused either a `BINGET` or `LONG_BINGET` load from the memo, leading to a `KeyError` as the determined index was bogus. --- Lib/pickle.py | 18 +++++++++++++++--- Lib/test/pickletester.py | 4 +++- .../2019-11-22-10-58-58.bpo-38876.qqy1Vp.rst | 9 +++++++++ Modules/_pickle.c | 12 ++++++++---- 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-11-22-10-58-58.bpo-38876.qqy1Vp.rst diff --git a/Lib/pickle.py b/Lib/pickle.py index 71aa57d500ecce..01d41422aa4a68 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1604,17 +1604,29 @@ def load_dup(self): def load_get(self): i = int(self.readline()[:-1]) - self.append(self.memo[i]) + try: + self.append(self.memo[i]) + except KeyError: + msg = f'Memo value not found at index {i}' + raise UnpicklingError(msg) from None dispatch[GET[0]] = load_get def load_binget(self): i = self.read(1)[0] - self.append(self.memo[i]) + try: + self.append(self.memo[i]) + except KeyError as exc: + msg = f'Memo value not found at index {i}' + raise UnpicklingError(msg) from None dispatch[BINGET[0]] = load_binget def load_long_binget(self): i, = unpack('UnpicklingError, "Memo value not found at index %ld", idx); + } Py_DECREF(key); return -1; } @@ -6201,7 +6203,8 @@ load_binget(UnpicklerObject *self) if (value == NULL) { PyObject *key = PyLong_FromSsize_t(idx); if (key != NULL) { - PyErr_SetObject(PyExc_KeyError, key); + PickleState *st = _Pickle_GetGlobalState(); + PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx); Py_DECREF(key); } return -1; @@ -6227,7 +6230,8 @@ load_long_binget(UnpicklerObject *self) if (value == NULL) { PyObject *key = PyLong_FromSsize_t(idx); if (key != NULL) { - PyErr_SetObject(PyExc_KeyError, key); + PickleState *st = _Pickle_GetGlobalState(); + PyErr_Format(st->UnpicklingError, "Memo value not found at index %ld", idx); Py_DECREF(key); } return -1;