From 8934e6ef53771dbc6fb8e04d991976c13b422928 Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 22 Jun 2021 19:09:20 +0800 Subject: [PATCH 1/2] Fix crash in union object with bad __module__ --- Lib/test/test_types.py | 9 ++++++++ .../2021-06-22-19-08-19.bpo-44483.eq2f7T.rst | 2 ++ Objects/unionobject.c | 23 ++++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-06-22-19-08-19.bpo-44483.eq2f7T.rst diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 767c3d06a4f583..d3e315a196b514 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -747,6 +747,15 @@ def __eq__(self, other): with self.assertRaises(TypeError): issubclass(list, type_) + def test_or_type_operator_with_bad_module(self): + class TypeVar: + @property + def __module__(self): + 1 / 0 + # Crashes in Issue44483 + with self.assertRaises(ZeroDivisionError): + str | TypeVar() + def test_ellipsis_type(self): self.assertIsInstance(Ellipsis, types.EllipsisType) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-06-22-19-08-19.bpo-44483.eq2f7T.rst b/Misc/NEWS.d/next/Core and Builtins/2021-06-22-19-08-19.bpo-44483.eq2f7T.rst new file mode 100644 index 00000000000000..ea54e79acfd9d8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-06-22-19-08-19.bpo-44483.eq2f7T.rst @@ -0,0 +1,2 @@ +Fix a crash in ``types.Union`` objects when creating a union of an object +with bad ``__module__`` field. diff --git a/Objects/unionobject.c b/Objects/unionobject.c index 05350363eed63f..79781d2631dee8 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -284,6 +284,19 @@ is_new_type(PyObject *obj) return is_typing_module(obj); } +// Emulates short-circuiting behavior of the ``||`` operator +// while also checking negative values. +#define CHECK_RES(obj, check) { \ + int result = check(obj); \ + if (result < 0) { \ + goto fail; \ + } \ + else if (result > 0) { \ + return 1; \ + } \ +} + +// Returns 1 on true, 0 on false, and -1 on error. static int is_unionable(PyObject *obj) { @@ -291,13 +304,17 @@ is_unionable(PyObject *obj) return 1; } PyTypeObject *type = Py_TYPE(obj); + CHECK_RES(obj, is_typevar); + CHECK_RES(obj, is_new_type); + CHECK_RES(obj, is_special_form); return ( - is_typevar(obj) || - is_new_type(obj) || - is_special_form(obj) || + // The following checks never fail. PyType_Check(obj) || PyObject_TypeCheck(obj, &Py_GenericAliasType) || type == &_Py_UnionType); + +fail: + return -1; } PyObject * From 1b8f932e13fc11f2a83a422d4f5312fb01597dec Mon Sep 17 00:00:00 2001 From: Fidget-Spinner <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 22 Jun 2021 20:21:51 +0800 Subject: [PATCH 2/2] Apply Serhiy's comments Co-Authored-By: Serhiy Storchaka <3659035+serhiy-storchaka@users.noreply.github.com> --- Objects/unionobject.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Objects/unionobject.c b/Objects/unionobject.c index 79781d2631dee8..a66d61524dcfc7 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -286,13 +286,10 @@ is_new_type(PyObject *obj) // Emulates short-circuiting behavior of the ``||`` operator // while also checking negative values. -#define CHECK_RES(obj, check) { \ - int result = check(obj); \ - if (result < 0) { \ - goto fail; \ - } \ - else if (result > 0) { \ - return 1; \ +#define CHECK_RES(res) { \ + int result = res; \ + if (result) { \ + return result; \ } \ } @@ -304,17 +301,14 @@ is_unionable(PyObject *obj) return 1; } PyTypeObject *type = Py_TYPE(obj); - CHECK_RES(obj, is_typevar); - CHECK_RES(obj, is_new_type); - CHECK_RES(obj, is_special_form); + CHECK_RES(is_typevar(obj)); + CHECK_RES(is_new_type(obj)); + CHECK_RES(is_special_form(obj)); return ( // The following checks never fail. PyType_Check(obj) || PyObject_TypeCheck(obj, &Py_GenericAliasType) || type == &_Py_UnionType); - -fail: - return -1; } PyObject *