gh-89811: Check for valid tp_version_tag in specializer (GH-113558)

This commit is contained in:
Peter Lazorchak 2024-01-10 21:33:05 -08:00 committed by GitHub
parent c65ae26f2b
commit f653caa5a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 243 additions and 3 deletions

View file

@ -586,6 +586,7 @@ _PyCode_Quicken(PyCodeObject *code)
static int function_kind(PyCodeObject *code);
static bool function_check_args(PyObject *o, int expected_argcount, int opcode);
static uint32_t function_get_version(PyObject *o, int opcode);
static uint32_t type_get_version(PyTypeObject *t, int opcode);
static int
specialize_module_load_attr(
@ -874,6 +875,9 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
PyObject *descr = NULL;
DescriptorClassification kind = analyze_descriptor(type, name, &descr, 0);
assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
if (type_get_version(type, LOAD_ATTR) == 0) {
goto fail;
}
switch(kind) {
case OVERRIDING:
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
@ -1057,6 +1061,9 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
}
PyObject *descr;
DescriptorClassification kind = analyze_descriptor(type, name, &descr, 1);
if (type_get_version(type, STORE_ATTR) == 0) {
goto fail;
}
switch(kind) {
case OVERRIDING:
SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
@ -1183,6 +1190,9 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
PyObject *descr = NULL;
DescriptorClassification kind = 0;
kind = analyze_descriptor((PyTypeObject *)owner, name, &descr, 0);
if (type_get_version((PyTypeObject *)owner, LOAD_ATTR) == 0) {
return -1;
}
switch (kind) {
case METHOD:
case NON_DESCRIPTOR:
@ -1455,6 +1465,18 @@ function_get_version(PyObject *o, int opcode)
return version;
}
/* Returning 0 indicates a failure. */
static uint32_t
type_get_version(PyTypeObject *t, int opcode)
{
uint32_t version = t->tp_version_tag;
if (version == 0) {
SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
return 0;
}
return version;
}
void
_Py_Specialize_BinarySubscr(
PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
@ -1726,6 +1748,9 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
}
if (tp->tp_new == PyBaseObject_Type.tp_new) {
PyFunctionObject *init = get_init_for_simple_managed_python_class(tp);
if (type_get_version(tp, CALL) == 0) {
return -1;
}
if (init != NULL) {
if (((PyCodeObject *)init->func_code)->co_argcount != nargs+1) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
@ -2466,7 +2491,10 @@ _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr)
SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
goto failure;
}
uint32_t version = Py_TYPE(value)->tp_version_tag;
uint32_t version = type_get_version(Py_TYPE(value), TO_BOOL);
if (version == 0) {
goto failure;
}
instr->op.code = TO_BOOL_ALWAYS_TRUE;
write_u32(cache->version, version);
assert(version);