openwrt-packages/lang/python/python3/patches/026-bpo-41288-Fix-a-crash-i...

112 lines
4.1 KiB
Diff

From 6463cf07fef7a923a743fcaf312150c45fd81b64 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 13 Jul 2020 11:18:04 -0700
Subject: [PATCH] bpo-41288: Fix a crash in unpickling invalid NEWOBJ_EX.
(GH-21458) (GH-21462)
Automerge-Triggered-By: @tiran
(cherry picked from commit 4f309abf55f0e6f8950ac13d6ec83c22b8d47bf8)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
---
Lib/test/pickletester.py | 18 ++++++++++++
.../2020-07-13-15-06-35.bpo-41288.8mn5P-.rst | 2 ++
Modules/_pickle.c | 29 ++++++++++++++-----
3 files changed, 41 insertions(+), 8 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2020-07-13-15-06-35.bpo-41288.8mn5P-.rst
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 764057a866411..c2648a3c44115 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -994,6 +994,24 @@ def test_compat_unpickle(self):
self.assertIs(type(unpickled), collections.UserDict)
self.assertEqual(unpickled, collections.UserDict({1: 2}))
+ def test_bad_reduce(self):
+ self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
+ self.check_unpickling_error(TypeError, b'N)R.')
+ self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
+
+ def test_bad_newobj(self):
+ error = (pickle.UnpicklingError, TypeError)
+ self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
+ self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
+ self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
+
+ def test_bad_newobj_ex(self):
+ error = (pickle.UnpicklingError, TypeError)
+ self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
+ self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
+ self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
+ self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
+
def test_bad_stack(self):
badpickles = [
b'.', # STOP
diff --git a/Misc/NEWS.d/next/Library/2020-07-13-15-06-35.bpo-41288.8mn5P-.rst b/Misc/NEWS.d/next/Library/2020-07-13-15-06-35.bpo-41288.8mn5P-.rst
new file mode 100644
index 0000000000000..3c3adbabf16ff
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-13-15-06-35.bpo-41288.8mn5P-.rst
@@ -0,0 +1,2 @@
+Unpickling invalid NEWOBJ_EX opcode with the C implementation raises now
+UnpicklingError instead of crashing.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 41b8fa7b3c290..bcf98e2f52648 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -5423,23 +5423,30 @@ load_newobj_ex(UnpicklerObject *self)
}
if (!PyType_Check(cls)) {
- Py_DECREF(kwargs);
- Py_DECREF(args);
PyErr_Format(st->UnpicklingError,
"NEWOBJ_EX class argument must be a type, not %.200s",
Py_TYPE(cls)->tp_name);
- Py_DECREF(cls);
- return -1;
+ goto error;
}
if (((PyTypeObject *)cls)->tp_new == NULL) {
- Py_DECREF(kwargs);
- Py_DECREF(args);
- Py_DECREF(cls);
PyErr_SetString(st->UnpicklingError,
"NEWOBJ_EX class argument doesn't have __new__");
- return -1;
+ goto error;
+ }
+ if (!PyTuple_Check(args)) {
+ PyErr_Format(st->UnpicklingError,
+ "NEWOBJ_EX args argument must be a tuple, not %.200s",
+ Py_TYPE(args)->tp_name);
+ goto error;
+ }
+ if (!PyDict_Check(kwargs)) {
+ PyErr_Format(st->UnpicklingError,
+ "NEWOBJ_EX kwargs argument must be a dict, not %.200s",
+ Py_TYPE(kwargs)->tp_name);
+ goto error;
}
+
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
Py_DECREF(kwargs);
Py_DECREF(args);
@@ -5449,6 +5456,12 @@ load_newobj_ex(UnpicklerObject *self)
}
PDATA_PUSH(self->stack, obj, -1);
return 0;
+
+error:
+ Py_DECREF(kwargs);
+ Py_DECREF(args);
+ Py_DECREF(cls);
+ return -1;
}
static int