Skip to content

Commit ac3c439

Browse files
ZeroIntensitysobolevnvstinnermarkshannon
authored
gh-131998: Fix NULL dereference when using an unbound method descriptor in a specialized code path (#132000)
Co-authored-by: sobolevn <mail@sobolevn.me> Co-authored-by: Victor Stinner <vstinner@python.org> Co-authored-by: Mark Shannon <mark@hotpy.org>
1 parent 3eda146 commit ac3c439

File tree

5 files changed

+47
-0
lines changed

5 files changed

+47
-0
lines changed

Lib/test/test_types.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
run_with_locale, cpython_only, no_rerun,
55
MISSING_C_DOCSTRINGS, EqualToForwardRef,
66
)
7+
from test.support.script_helper import assert_python_ok
78
from test.support.import_helper import import_fresh_module
89

910
import collections.abc
@@ -672,6 +673,24 @@ def test_traceback_and_frame_types(self):
672673
def test_capsule_type(self):
673674
self.assertIsInstance(_datetime.datetime_CAPI, types.CapsuleType)
674675

676+
def test_call_unbound_crash(self):
677+
# GH-131998: The specialized instruction would get tricked into dereferencing
678+
# a bound "self" that didn't exist if subsequently called unbound.
679+
code = """if True:
680+
681+
def call(part):
682+
[] + ([] + [])
683+
part.pop()
684+
685+
for _ in range(3):
686+
call(['a'])
687+
try:
688+
call(list)
689+
except TypeError:
690+
pass
691+
"""
692+
assert_python_ok("-c", code)
693+
675694

676695
class UnionTests(unittest.TestCase):
677696

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when using an unbound method :term:`descriptor` object in a
2+
function where a bound method descriptor was used.

Python/bytecodes.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4300,12 +4300,14 @@ dummy_func(
43004300
arguments--;
43014301
total_args++;
43024302
}
4303+
EXIT_IF(total_args == 0);
43034304
PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o;
43044305
EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type));
43054306
PyMethodDef *meth = method->d_method;
43064307
EXIT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS));
43074308
PyTypeObject *d_type = method->d_common.d_type;
43084309
PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]);
4310+
assert(self != NULL);
43094311
EXIT_IF(!Py_IS_TYPE(self, d_type));
43104312
STAT_INC(CALL, hit);
43114313
int nargs = total_args - 1;
@@ -4378,12 +4380,14 @@ dummy_func(
43784380
arguments--;
43794381
total_args++;
43804382
}
4383+
EXIT_IF(total_args == 0);
43814384
PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o;
43824385
/* Builtin METH_FASTCALL methods, without keywords */
43834386
EXIT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type));
43844387
PyMethodDef *meth = method->d_method;
43854388
EXIT_IF(meth->ml_flags != METH_FASTCALL);
43864389
PyObject *self = PyStackRef_AsPyObjectBorrow(arguments[0]);
4390+
assert(self != NULL);
43874391
EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type));
43884392
STAT_INC(CALL, hit);
43894393
int nargs = total_args - 1;

Python/executor_cases.c.h

Lines changed: 10 additions & 0 deletions
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: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy