Repository navigation
Make Argument Clinic aware of possible UBSan failures #128180
Description
Activity
- addedtype-featureA feature request or enhancementA feature request or enhancement
on Dec 22, 2024 - Reacted by Peter Bierma
Took a stab at this. For simple cases, all that needs to change is this property to always return
PyObject *, and then the functionality to cast it is already implemented:cpython/Tools/clinic/libclinic/converters.py
Lines 1183 to 1188 in f9a5a3a
def parser_type(self) -> str: assert self.type is not None if self.function.kind in {METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD}: tp, _ = correct_name_for_self(self.function) return tp return self.type We'll still need to change some other things though, because some generated clinic code relies on specific structures (e.g. fields in
PyTypeObject *). More importantly, we'll have to manually go through and audit where we need to change casts for areas that call clinic funtions manually, typically for locking. For example, I did this with the SSL thread safety fix:Line 937 in f9a5a3a
if (_ssl__SSLSocket_owner_set(self, owner, NULL) == -1) { Here,
selfis aPySSLSocket *rather than aPyObject *, so changing that would break this case. We'll probably need to deal with that on an agonizing case-by-case basis.Reacted by Erlend E. AaslandI'm not afraid of doing the case-by-case, considering this is what I've been doing for the rest. But thanks for digging into this, I haven't looked at clinic a lot!
Feature or enhancement
A huge part of the CPython code base uses Argument Clinic for generating methods for classes or standalone functions. Generally, methods are then used as follows:
where each
<MODULE>_<CLASS>_<METHOD>_METHODDEFis something likeWe also have
Now, in order to fix #111178, we generally convert non-AC clinic methods by changing
FooObject *toPyObject *and doing a pointer cast in the function body. See #111178 for a wider discussion. The issue is that we cannot easily do the same for AC-generated code since the prototype is part of the auto-generated block.We can do it if we specify
self: self(type="PyObject *")instead of not specifyingselfin the AC input, but this is an overkill. Instead, AC should always generate two functions: an implementation function which takes a typed object (i.e., FooObject) and a public dispatcher which takes a PyObject *self and possibly unused arguments. Stated otherwise:I decided to open a separate issue to track this change orthogonally to the UBSan failures fixes that can be achieved without any AC changes. I hope that this will not deterioriate the performances of CPython too much.
Note: this does not only affect methods as above; this affects any method that is casted to
PyCFunctionor anything else with incompatible function pointer signatures.