https://github.com/python/cpython/commit/50a595b37fe3201cd07701ffdda9d6baa6163562
commit: 50a595b37fe3201cd07701ffdda9d6baa6163562
branch: 3.13
author: mpage <[email protected]>
committer: markshannon <[email protected]>
date: 2024-08-21T13:16:30+01:00
summary:
[3.13] gh-122712: Guard against __code__ reassignment in
CALL_ALLOC_AND_ENTER_INIT (GH-122713) (GH-123184)
files:
M Lib/test/test_opcache.py
M Python/bytecodes.c
M Python/generated_cases.c.h
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index 92a34113bc0383..c4fcc1993ca627 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -28,6 +28,13 @@ def wrapper(*args, **kwargs):
return wrapper
+class TestBase(unittest.TestCase):
+ def assert_specialized(self, f, opname):
+ instructions = dis.get_instructions(f, adaptive=True)
+ opnames = {instruction.opname for instruction in instructions}
+ self.assertIn(opname, opnames)
+
+
class TestLoadSuperAttrCache(unittest.TestCase):
def test_descriptor_not_double_executed_on_spec_fail(self):
calls = []
@@ -479,7 +486,7 @@ def f():
self.assertFalse(f())
-class TestCallCache(unittest.TestCase):
+class TestCallCache(TestBase):
def test_too_many_defaults_0(self):
def f():
pass
@@ -507,10 +514,33 @@ def f(x, y):
f(None)
f()
+ @disabling_optimizer
+ @requires_specialization
+ def test_assign_init_code(self):
+ class MyClass:
+ def __init__(self):
+ pass
+
+ def instantiate():
+ return MyClass()
+
+ # Trigger specialization
+ for _ in range(1025):
+ instantiate()
+ self.assert_specialized(instantiate, "CALL_ALLOC_AND_ENTER_INIT")
+
+ def count_args(self, *args):
+ self.num_args = len(args)
+
+ # Set MyClass.__init__.__code__ to a code object that is incompatible
+ # (uses varargs) with the current specialization
+ MyClass.__init__.__code__ = count_args.__code__
+ instantiate()
+
@threading_helper.requires_working_threading()
@requires_specialization
-class TestRacesDoNotCrash(unittest.TestCase):
+class TestRacesDoNotCrash(TestBase):
# Careful with these. Bigger numbers have a higher chance of catching bugs,
# but you can also burn through a *ton* of type/dict/function versions:
ITEMS = 1000
@@ -518,11 +548,6 @@ class TestRacesDoNotCrash(unittest.TestCase):
WARMUPS = 2
WRITERS = 2
- def assert_specialized(self, f, opname):
- instructions = dis.get_instructions(f, adaptive=True)
- opnames = {instruction.opname for instruction in instructions}
- self.assertIn(opname, opnames)
-
@disabling_optimizer
def assert_races_do_not_crash(
self, opname, get_items, read, write, *, check_items=False
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 1a41c7e0d2dd99..cac9f67d7f2171 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -3407,6 +3407,8 @@ dummy_func(
PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
PyCodeObject *code = (PyCodeObject *)init->func_code;
DEOPT_IF(code->co_argcount != oparg+1);
+ DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS |
CO_OPTIMIZED)) != CO_OPTIMIZED);
+ DEOPT_IF(code->co_kwonlyargcount);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize
+ _Py_InitCleanup.co_framesize));
STAT_INC(CALL, hit);
PyObject *self = _PyType_NewManagedObject(tp);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 38a4c40e33ff22..fe42e20f4393d6 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -875,6 +875,8 @@
PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
PyCodeObject *code = (PyCodeObject *)init->func_code;
DEOPT_IF(code->co_argcount != oparg+1, CALL);
+ DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS |
CO_OPTIMIZED)) != CO_OPTIMIZED, CALL);
+ DEOPT_IF(code->co_kwonlyargcount, CALL);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize
+ _Py_InitCleanup.co_framesize), CALL);
STAT_INC(CALL, hit);
PyObject *self = _PyType_NewManagedObject(tp);
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]