Skip to content

Commit 6463cf0

Browse files
bpo-41288: Fix a crash in unpickling invalid NEWOBJ_EX. (GH-21458) (GH-21462)
Automerge-Triggered-By: @tiran (cherry picked from commit 4f309ab) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 46cbf61 commit 6463cf0

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

Lib/test/pickletester.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,24 @@ def test_compat_unpickle(self):
994994
self.assertIs(type(unpickled), collections.UserDict)
995995
self.assertEqual(unpickled, collections.UserDict({1: 2}))
996996

997+
def test_bad_reduce(self):
998+
self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
999+
self.check_unpickling_error(TypeError, b'N)R.')
1000+
self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
1001+
1002+
def test_bad_newobj(self):
1003+
error = (pickle.UnpicklingError, TypeError)
1004+
self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
1005+
self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
1006+
self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
1007+
1008+
def test_bad_newobj_ex(self):
1009+
error = (pickle.UnpicklingError, TypeError)
1010+
self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
1011+
self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
1012+
self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
1013+
self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
1014+
9971015
def test_bad_stack(self):
9981016
badpickles = [
9991017
b'.', # STOP
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Unpickling invalid NEWOBJ_EX opcode with the C implementation raises now
2+
UnpicklingError instead of crashing.

Modules/_pickle.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5423,23 +5423,30 @@ load_newobj_ex(UnpicklerObject *self)
54235423
}
54245424

54255425
if (!PyType_Check(cls)) {
5426-
Py_DECREF(kwargs);
5427-
Py_DECREF(args);
54285426
PyErr_Format(st->UnpicklingError,
54295427
"NEWOBJ_EX class argument must be a type, not %.200s",
54305428
Py_TYPE(cls)->tp_name);
5431-
Py_DECREF(cls);
5432-
return -1;
5429+
goto error;
54335430
}
54345431

54355432
if (((PyTypeObject *)cls)->tp_new == NULL) {
5436-
Py_DECREF(kwargs);
5437-
Py_DECREF(args);
5438-
Py_DECREF(cls);
54395433
PyErr_SetString(st->UnpicklingError,
54405434
"NEWOBJ_EX class argument doesn't have __new__");
5441-
return -1;
5435+
goto error;
5436+
}
5437+
if (!PyTuple_Check(args)) {
5438+
PyErr_Format(st->UnpicklingError,
5439+
"NEWOBJ_EX args argument must be a tuple, not %.200s",
5440+
Py_TYPE(args)->tp_name);
5441+
goto error;
5442+
}
5443+
if (!PyDict_Check(kwargs)) {
5444+
PyErr_Format(st->UnpicklingError,
5445+
"NEWOBJ_EX kwargs argument must be a dict, not %.200s",
5446+
Py_TYPE(kwargs)->tp_name);
5447+
goto error;
54425448
}
5449+
54435450
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
54445451
Py_DECREF(kwargs);
54455452
Py_DECREF(args);
@@ -5449,6 +5456,12 @@ load_newobj_ex(UnpicklerObject *self)
54495456
}
54505457
PDATA_PUSH(self->stack, obj, -1);
54515458
return 0;
5459+
5460+
error:
5461+
Py_DECREF(kwargs);
5462+
Py_DECREF(args);
5463+
Py_DECREF(cls);
5464+
return -1;
54525465
}
54535466

54545467
static int

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy