Skip to content

Commit c21e7c4

Browse files
authored
[3.14] gh-154902: Type-check the SET_ADD operand (#155072)
1 parent e7a45f4 commit c21e7c4

5 files changed

Lines changed: 55 additions & 3 deletions

File tree

Lib/test/test_type_annotations.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import annotationlib
22
import inspect
3+
import itertools
34
import textwrap
45
import types
56
import unittest
@@ -896,3 +897,18 @@ class Generic:
896897
mod = build_module(code)
897898
annos = mod.__annotations__
898899
self.assertEqual(annos, {"annotated_name": 0})
900+
901+
# gh-154902
902+
def test_conditional_annotations_rebound(self):
903+
# user code can rebind __conditional_annotations__ to any object
904+
lefts = ("__conditional_annotations__",
905+
'globals()["__conditional_annotations__"]')
906+
values = ("0", "{}", "[]", "''", "object()", "frozenset()")
907+
for left, value in itertools.product(lefts, values):
908+
with self.subTest(left=left, value=value):
909+
code = f"""
910+
{left} = {value}
911+
x: int
912+
"""
913+
with self.assertRaises(TypeError):
914+
run_code(code)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when ``__conditional_annotations__`` is rebound to a non-set
2+
object.

Python/bytecodes.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,15 @@ dummy_func(
10561056
}
10571057

10581058
inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {
1059-
int err = _PySet_AddTakeRef((PySetObject *)PyStackRef_AsPyObjectBorrow(set),
1059+
PyObject *set_o = PyStackRef_AsPyObjectBorrow(set);
1060+
// gh-154902: user code can rebind __conditional_annotations__
1061+
if (!PySet_CheckExact(set_o)) {
1062+
_PyErr_Format(tstate, PyExc_TypeError,
1063+
"'%T' object is not a set", set_o);
1064+
PyStackRef_CLOSE(v);
1065+
ERROR_IF(true);
1066+
}
1067+
int err = _PySet_AddTakeRef((PySetObject *)set_o,
10601068
PyStackRef_AsPyObjectSteal(v));
10611069
ERROR_IF(err);
10621070
}

Python/executor_cases.c.h

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)