-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
[BUG]: return_value_policy_override in optional_caster does not use the right types #3330
Comments
@ryancahoon-zoox For future reference, feel free to just open a PR, we can work on adding regressions tests there if necessary. |
Hi @ryancahoon-zoox, is there a chance that you could help by moving your code to a PR? We already have the ability to conditionally test with boost: Line 25 in ba9f919
Following that pattern would be a practical way to leverage your existing reproducer. Please mark the PR as modifiable by maintainers (I think it's the default, a green checkbox when you create the PR). That way we can jump in fixing issues surfaced by the CI. |
@ryancahoon-zoox are you planning to open a PR with your boost example as a test? |
I've been trying to work on it as I have time, but I'm having trouble reproducing my original issue in the test environment. There's a number of factors that I need to check still, like whether there are some versions of boost that aren't affected by this issue. |
We have had no problem in reproducing it in #3332, AFAICT, the problem has been compiling the new test on Windows; MSVC doesn't like it at all. |
@henryiii I've haven't been able to replicate the segfault behavior in the PR, but I was just going ahead and added the boost::optional tests since they are useful regardless. |
I've reproduced the issue after switching to Boost 1.54 (which is what is used in the software environment where I originally observed the bug), whereas the issue does not seem to be reproduced with Boost 1.71. I've not bothered to check intermediate versions, so I'm not sure exactly when boost::optional might have changed. For the purposes of testing, I'm going to write a simple optional-like type that reproduces the necessary parts of the old boost::optional behavior. |
Awesome, thanks a lot for working on the tailored test!
…On Sun, Oct 17, 2021 at 14:00 Ryan Cahoon ***@***.***> wrote:
I've reproduced the issue after switching to Boost 1.54 (which is what is
used in the software environment where I originally observed the bug),
whereas the issue does not seem to be reproduced with Boost 1.71. I've not
bothered to check intermediate versions, so I'm not sure exactly when
boost::optional might have changed.
For the purposes of testing, I'm going to write a simple optional-like
type that reproduces the necessary parts of the old boost::optional
behavior.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#3330 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFUZAAGDB2AUHJYFCGYMODUHM2QJANCNFSM5FL4M3CA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
`return_value_policy_override` was not being applied correctly in `optional_caster` in two ways: - The `is_lvalue_reference` condition referenced `T`, which was the `optional<T>` type parameter from the class, when it should have used `T_`, which was the parameter to the `cast` function. `T_` can potentially be a reference type, but `T` will never be. - The type parameter passed to `return_value_policy_override` should be `T::value_type`, not `T`. This matches the way that the other STL container type casters work. The result of these issues was that a method/property definition which used a `reference` or `reference_internal` return value policy would create a Python value that's bound by reference to a temporary C++ object, resulting in undefined behavior. For reasons that I was not able to figure out fully, it seems like this causes problems when using old versions of `boost::optional`, but not with recent versions of `boost::optional` or the `libstdc++` implementation of `std::optional`. The issue (that the override to `return_value_policy::move` is never being applied) is present for all implementations, it just seems like that somehow doesn't result in problems for the some implementation of `optional`. This change includes a regression type with a custom optional-like type which was able to reproduce the issue. Part of the issue with using the wrong types may have stemmed from the type variables `T` and `T_` having very similar names. This also changes the type variables in `optional_caster` to use slightly more descriptive names, which also more closely follow the naming convention used by the other STL casters. Fixes pybind#3330
…3376) * fix: the types for return_value_policy_override in optional_caster `return_value_policy_override` was not being applied correctly in `optional_caster` in two ways: - The `is_lvalue_reference` condition referenced `T`, which was the `optional<T>` type parameter from the class, when it should have used `T_`, which was the parameter to the `cast` function. `T_` can potentially be a reference type, but `T` will never be. - The type parameter passed to `return_value_policy_override` should be `T::value_type`, not `T`. This matches the way that the other STL container type casters work. The result of these issues was that a method/property definition which used a `reference` or `reference_internal` return value policy would create a Python value that's bound by reference to a temporary C++ object, resulting in undefined behavior. For reasons that I was not able to figure out fully, it seems like this causes problems when using old versions of `boost::optional`, but not with recent versions of `boost::optional` or the `libstdc++` implementation of `std::optional`. The issue (that the override to `return_value_policy::move` is never being applied) is present for all implementations, it just seems like that somehow doesn't result in problems for the some implementation of `optional`. This change includes a regression type with a custom optional-like type which was able to reproduce the issue. Part of the issue with using the wrong types may have stemmed from the type variables `T` and `T_` having very similar names. This also changes the type variables in `optional_caster` to use slightly more descriptive names, which also more closely follow the naming convention used by the other STL casters. Fixes #3330 * Fix clang-tidy complaints * Add missing NOLINT * Apply a couple more fixes * fix: support GCC 4.8 * tests: avoid warning about unknown compiler for compilers missing C++17 * Remove unneeded test module attribute * Change test enum to have more unique int values Co-authored-by: Aaron Gokaslan <skylion.aaron@gmail.com> Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
Required prerequisites
Problem description
return_value_policy_override
is not being applied correctly inoptional_caster
in two ways.is_lvalue_reference
condition referencesT
, which is theoptional<T>
type parameter from the class, when it should useT_
, which is the parameter to thecast
function.T_
can potentially be a reference type, butT
will never be.return_value_policy_override
should beT::value_type
, notT
. This matches the way that the other STL container type casters work.The result of these issues is that a method/property definition which uses a
reference
orreference_internal
return value policy will create a Python value that's bound by reference to a temporary C++ object, resulting in undefined behavior. For reasons that I was not able to figure out, it seems like this causes problems when usingboost::optional
, but not with thelibstdc++
implementation ofstd::optional
. The issue (that the override toreturn_value_policy::move
is never being applied) is present for all implementations, it just seems like that somehow doesn't result in problems for thelibstdc++
implementation.I believe the following patch is the correct resolution. I would open a PR directly, except I'm not sure how to write a regression test for this case.
Reproducible example code
The text was updated successfully, but these errors were encountered: