diff --git a/Lib/pickle.py b/Lib/pickle.py index 729c215514ad24..fe984476fed346 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1322,12 +1322,18 @@ def load(self): if not key: raise EOFError assert isinstance(key, bytes_types) - dispatch[key[0]](self) + try: + dispatch[key[0]](self) + except KeyError: + raise UnpicklingError( + f"invalid load key, '\\x{key[0]:02x}'.") except _Stop as stopinst: return stopinst.value # Return a list of items pushed in the stack after last MARK instruction. def pop_mark(self): + if not self.metastack: + raise UnpicklingError("could not find MARK") items = self.stack self.stack = self.metastack.pop() self.append = self.stack.append diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index e2384b33345a45..d1afcb5a0cc591 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -55,7 +55,7 @@ class PyPickleTests(AbstractPickleModuleTests, unittest.TestCase): class PyUnpicklerTests(AbstractUnpickleTests, unittest.TestCase): unpickler = pickle._Unpickler - bad_stack_errors = (IndexError,) + bad_stack_errors = (pickle.UnpicklingError, IndexError) truncated_errors = (pickle.UnpicklingError, EOFError, AttributeError, ValueError, struct.error, IndexError, ImportError) diff --git a/Misc/NEWS.d/next/Library/2025-11-19-15-23-30.gh-issue-141749.QRBf7O.rst b/Misc/NEWS.d/next/Library/2025-11-19-15-23-30.gh-issue-141749.QRBf7O.rst new file mode 100644 index 00000000000000..85d38eeb682f3a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-11-19-15-23-30.gh-issue-141749.QRBf7O.rst @@ -0,0 +1 @@ +Pure python pickle.py error handling is more consistent with the c implementation, raising UnpicklingError exceptions for invalid pickle data instead of KeyError or IndexError.