Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a long-standing bug in the handling of Python multiple inheritance #30056

Merged
merged 7 commits into from
Sep 12, 2023

Conversation

rwgk
Copy link
Contributor

@rwgk rwgk commented Jul 28, 2023

Description

For full background please see pybind/pybind11#4762.

The core of the added test is this:

struct CppBase {};
struct CppDrvd : CppBase {};
class PC(m.CppBase):
    pass

class PPCC(PC, m.CppDrvd):
    pass

Without this PR, the runtime behavior depends on the order in which PC or PPCC are first instantiated, which can be highly surprising and potentially very difficult to debug. See pybind/pybind11#4762 (comment) for a full analysis.

However, use cases appear to be surprisingly rare (pybind/pybind11#4762 (comment)). The only known use cases are through PyCLIF.

More-or-less as a side-effect, this PR also:

Suggested changelog entry:

Ralf W. Grosse-Kunstleve added 6 commits July 29, 2023 14:03
… *>()` introduced with PR google#2152

The `reinterpret_cast<instance *>(self)` is unsafe if `__new__` is mocked,
which was actually found in the wild: the mock returned `None` for `self`.
This was inconsequential because `inst` is currently cast straight back to
`PyObject *` to compute `all_type_info()`, which is empty if `self` is not
a pybind11 `instance`, and then `inst` is never dereferenced. However, the
unsafe detour through `instance *` is easily avoided and the updated
implementation is less prone to accidents while debugging or refactoring.
It turns out the previous commit message is incorrect, the `inst` pointer is actually dereferenced, in the `value_and_holder` ctor here:

https://github.com/pybind/pybind11/blob/f3e0602802c7840992c97f4960515777cad6a5c7/include/pybind11/detail/type_caster_base.h#L262-L263

```
259     // Main constructor for a found value/holder:
260     value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index)
261         : inst{i}, index{index}, type{type},
262           vh{inst->simple_layout ? inst->simple_value_holder
263                                  : &inst->nonsimple.values_and_holders[vpos]} {}
```
@rwgk rwgk changed the title WIP: test_python_multiple_inheritance Fix a long-standing bug in the handling of Python multiple inheritance Sep 12, 2023
@rwgk rwgk marked this pull request as ready for review September 12, 2023 22:22
@rwgk rwgk requested a review from wangxf123456 September 12, 2023 22:23
@rwgk rwgk merged commit dc89e50 into google:main Sep 12, 2023
149 checks passed
@rwgk rwgk deleted the python_multiple_inheritance_test_pywrapcc branch September 12, 2023 23:35
rwgk pushed a commit to google/clif that referenced this pull request Sep 28, 2023
…fixed).

pybind11 bug fix: google/pybind11clif#30056

For the full history of the bug fix see pybind/pybind11#4762.

Tested manually with `_GEN_PYBIND11 = True` in google3/devtools/clif/python/clif_build_rule.bzl;l=56;rcl=559537444:

* http://sponge2/b3a0816f-9acb-4f76-aebe-4d0637ea430f

PiperOrigin-RevId: 565096151
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants