mirror of
https://github.com/python/cpython.git
synced 2026-10-28 18:35:21 +08:00
[3.14] gh-154902: Type-check the SET_ADD operand (#155072)
This commit is contained in:
1 parent
e7a45f431b
commit
c21e7c45a9
5 files changed
+55
-3
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import annotationlib
|
||||
import inspect
|
||||
import itertools
|
||||
import textwrap
|
||||
import types
|
||||
import unittest
|
||||
@@ -896,3 +897,18 @@ class RegressionTests(unittest.TestCase):
|
||||
mod = build_module(code)
|
||||
annos = mod.__annotations__
|
||||
self.assertEqual(annos, {"annotated_name": 0})
|
||||
|
||||
# gh-154902
|
||||
def test_conditional_annotations_rebound(self):
|
||||
# user code can rebind __conditional_annotations__ to any object
|
||||
lefts = ("__conditional_annotations__",
|
||||
'globals()["__conditional_annotations__"]')
|
||||
values = ("0", "{}", "[]", "''", "object()", "frozenset()")
|
||||
for left, value in itertools.product(lefts, values):
|
||||
with self.subTest(left=left, value=value):
|
||||
code = f"""
|
||||
{left} = {value}
|
||||
x: int
|
||||
"""
|
||||
with self.assertRaises(TypeError):
|
||||
run_code(code)
|
||||
@@ -0,0 +1,2 @@
|
||||
Fix a crash when ``__conditional_annotations__`` is rebound to a non-set
|
||||
object.
|
||||
+9
-1
@@ -1056,7 +1056,15 @@ dummy_func(
|
||||
}
|
||||
|
||||
inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {
|
||||
int err = _PySet_AddTakeRef((PySetObject *)PyStackRef_AsPyObjectBorrow(set),
|
||||
PyObject *set_o = PyStackRef_AsPyObjectBorrow(set);
|
||||
// gh-154902: user code can rebind __conditional_annotations__
|
||||
if (!PySet_CheckExact(set_o)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%T' object is not a set", set_o);
|
||||
PyStackRef_CLOSE(v);
|
||||
ERROR_IF(true);
|
||||
}
|
||||
int err = _PySet_AddTakeRef((PySetObject *)set_o,
|
||||
PyStackRef_AsPyObjectSteal(v));
|
||||
ERROR_IF(err);
|
||||
}
|
||||
|
||||
Generated
+14
-1
@@ -1609,8 +1609,21 @@
|
||||
oparg = CURRENT_OPARG();
|
||||
v = stack_pointer[-1];
|
||||
set = stack_pointer[-2 - (oparg-1)];
|
||||
PyObject *set_o = PyStackRef_AsPyObjectBorrow(set);
|
||||
if (!PySet_CheckExact(set_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%T' object is not a set", set_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(v);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int err = _PySet_AddTakeRef((PySetObject *)PyStackRef_AsPyObjectBorrow(set),
|
||||
int err = _PySet_AddTakeRef((PySetObject *)set_o,
|
||||
PyStackRef_AsPyObjectSteal(v));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (err) {
|
||||
|
||||
Generated
+14
-1
@@ -10859,8 +10859,21 @@
|
||||
_PyStackRef v;
|
||||
v = stack_pointer[-1];
|
||||
set = stack_pointer[-2 - (oparg-1)];
|
||||
PyObject *set_o = PyStackRef_AsPyObjectBorrow(set);
|
||||
if (!PySet_CheckExact(set_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%T' object is not a set", set_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(v);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int err = _PySet_AddTakeRef((PySetObject *)PyStackRef_AsPyObjectBorrow(set),
|
||||
int err = _PySet_AddTakeRef((PySetObject *)set_o,
|
||||
PyStackRef_AsPyObjectSteal(v));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (err) {
|
||||
|
||||
Reference in new issue
Block a user