Skip to content

Commit adfa1ba

Browse files
authoredJun 22, 2021
bpo-44483: Fix crash in union object with bad __module__ (GH-26848)
1 parent bc6c12c commit adfa1ba

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed
 

‎Lib/test/test_types.py

+9
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,15 @@ def __eq__(self, other):
747747
with self.assertRaises(TypeError):
748748
issubclass(list, type_)
749749

750+
def test_or_type_operator_with_bad_module(self):
751+
class TypeVar:
752+
@property
753+
def __module__(self):
754+
1 / 0
755+
# Crashes in Issue44483
756+
with self.assertRaises(ZeroDivisionError):
757+
str | TypeVar()
758+
750759
def test_ellipsis_type(self):
751760
self.assertIsInstance(Ellipsis, types.EllipsisType)
752761

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in ``types.Union`` objects when creating a union of an object
2+
with bad ``__module__`` field.

‎Objects/unionobject.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -284,17 +284,28 @@ is_new_type(PyObject *obj)
284284
return is_typing_module(obj);
285285
}
286286

287+
// Emulates short-circuiting behavior of the ``||`` operator
288+
// while also checking negative values.
289+
#define CHECK_RES(res) { \
290+
int result = res; \
291+
if (result) { \
292+
return result; \
293+
} \
294+
}
295+
296+
// Returns 1 on true, 0 on false, and -1 on error.
287297
static int
288298
is_unionable(PyObject *obj)
289299
{
290300
if (obj == Py_None) {
291301
return 1;
292302
}
293303
PyTypeObject *type = Py_TYPE(obj);
304+
CHECK_RES(is_typevar(obj));
305+
CHECK_RES(is_new_type(obj));
306+
CHECK_RES(is_special_form(obj));
294307
return (
295-
is_typevar(obj) ||
296-
is_new_type(obj) ||
297-
is_special_form(obj) ||
308+
// The following checks never fail.
298309
PyType_Check(obj) ||
299310
PyObject_TypeCheck(obj, &Py_GenericAliasType) ||
300311
type == &_Py_UnionType);

0 commit comments

Comments
 (0)