]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-108487: Change assert that should've been DEOPT_IF (#108509)
authorGuido van Rossum <guido@python.org>
Sat, 26 Aug 2023 23:22:40 +0000 (16:22 -0700)
committerGitHub <noreply@github.com>
Sat, 26 Aug 2023 23:22:40 +0000 (01:22 +0200)
* Remove assert that should've been DEOPT_IF

The assert(method != NULL) in CALL_NO_KW_LIST_APPEND is wrong --
this condition should lead to a deoptimization, and indeed there
is a DEOPT_IF two lines later that will trigger if method == NULL.

This would crash in a devious repro scenario (first seen live
in boto3 tests) when compiled with assertions enabled.
In a production version there is no crash, so impact is limited.

(The crash also appears in main; I will prepare a separate PR.)

* Add back a different assert(self != NULL)

* ðŸ“œðŸ¤– Added by blurb_it.

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Misc/NEWS.d/next/Core and Builtins/2023-08-26-04-33-18.gh-issue-108487.aUFxqf.rst [new file with mode: 0644]
Python/bytecodes.c
Python/generated_cases.c.h

diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-26-04-33-18.gh-issue-108487.aUFxqf.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-26-04-33-18.gh-issue-108487.aUFxqf.rst
new file mode 100644 (file)
index 0000000..1117bcd
--- /dev/null
@@ -0,0 +1 @@
+Change an assert that would cause a spurious crash in a devious case that should only trigger deoptimization.
index dc2ae221f0bdb1b2357cc7709b11fda7b8863e64..5e80e06205ae4e08eec9161b00e47d945747548c 100644 (file)
@@ -2992,9 +2992,9 @@ dummy_func(
         inst(CALL_NO_KW_LIST_APPEND, (unused/1, unused/2, method, self, args[oparg] -- unused)) {
             assert(kwnames == NULL);
             assert(oparg == 1);
-            assert(method != NULL);
             PyInterpreterState *interp = _PyInterpreterState_GET();
             DEOPT_IF(method != interp->callable_cache.list_append, CALL);
+            assert(self != NULL);
             DEOPT_IF(!PyList_Check(self), CALL);
             STAT_INC(CALL, hit);
             if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) {
index b0a363ce9aa111ba36c5645e4f337fd33532b018..a3c049569268c112447c629fee73c543485fc61c 100644 (file)
             #line 2993 "Python/bytecodes.c"
             assert(kwnames == NULL);
             assert(oparg == 1);
-            assert(method != NULL);
             PyInterpreterState *interp = _PyInterpreterState_GET();
             DEOPT_IF(method != interp->callable_cache.list_append, CALL);
+            assert(self != NULL);
             DEOPT_IF(!PyList_Check(self), CALL);
             STAT_INC(CALL, hit);
             if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) {