Skip to content

revert: "add life support to handles cast to string_view (#6092)" - #6097

Merged
henryiii merged 1 commit into
masterfrom
revert-6092-string-view-life-support
Jun 29, 2026
Merged

revert: "add life support to handles cast to string_view (#6092)"#6097
henryiii merged 1 commit into
masterfrom
revert-6092-string-view-life-support

Conversation

@henryiii

Copy link
Copy Markdown
Collaborator

🤖 AI text below 🤖

Reverts #6092.

#6092 ("add life support to handles cast to string_view") introduced regressions that are being addressed in #6096. Reverting it here so master is clean while the proper fix is worked out.

This is a clean revert of 59d7cb2 — it removes the loader_life_support::add_patient(src) calls added to string_caster and the accompanying func_with_string_views test.

Suggested changelog entry

Reverted #6092 (string_view life support), which introduced regressions.

This reverts commit 59d7cb2 (#6092).

#6092 introduced regressions that are being addressed in #6096; reverting

Assisted-by: ClaudeCode:claude-opus-4.8
@henryiii
henryiii merged commit db92ad9 into master Jun 29, 2026
87 checks passed
@henryiii
henryiii deleted the revert-6092-string-view-life-support branch June 29, 2026 04:38
@github-actions github-actions Bot added the needs changelog Possibly needs a changelog entry label Jun 29, 2026
henryiii added a commit to henryiii/pybind11 that referenced this pull request Jun 29, 2026
…ind#6092)"

This re-applies pybind#6092 (reverting pybind#6097) so the follow-up fixes in this PR can build on it.

Assisted-by: ClaudeCode:claude-opus-4.8
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Jul 25, 2026
rwgk added a commit that referenced this pull request Jul 29, 2026
* revert: "revert: add life support to handles cast to string_view (#6092)"

This re-applies #6092 (reverting #6097) so the follow-up fixes in this PR can build on it.

Assisted-by: ClaudeCode:claude-opus-4.8

* fix: don't throw from string_view life support outside a bound function

PR #6092 added loader_life_support::add_patient(src) to keep the source
object alive when loading a string view, fixing a real use-after-free when
a container of views is built from a non-sequence iterable (e.g. a
generator): list_caster materializes a temporary tuple that owns the
strings and destroys it when load() returns, before the bound function
body runs.

add_patient throws when there is no life support frame, so casting to a
view outside a bound function (e.g. a manual py::cast<std::string_view>)
now raises instead of relying on the caller-owned source, a regression
from #6092.

For these view-into-src cases registration is best effort: inside a bound
function it keeps src alive (fixing the UAF), and outside one the caller
owns src's lifetime as before. Add try_add_patient(), which returns false
instead of throwing when there is no frame, and use it at the three view
load sites. add_patient() keeps its strict contract for value-creating
conversions.

Assisted-by: ClaudeCode:claude-opus-4.8

* fix: only add string_view life support for transient sources

Refine the previous commit. Best-effort registration (try_add_patient)
silently produces a dangling view when a container of views is built from
a generator outside a bound function: there the materialized temporary is
released before the view is used, and with no frame nothing keeps it
alive. Such a cast cannot be made safe, so it should fail loudly, while a
view into a durable, caller-owned object needs no life support at all.

The view caster cannot tell a durable source from a pybind11-managed
transient one; that provenance lives in the container caster. Introduce an
ambient transient_source_guard that the list, set, map, and array casters
set around their generator/materialized paths, and have the string caster
keep the source alive only when loading from a transient source (via the
throwing add_patient, so try_add_patient is no longer needed). This means:

- views into durable sources (direct arguments, sequences, manual casts)
  add no life support and no longer throw outside a bound function, and
- a generator used outside a frame throws, rather than silently dangling.

The guard restores (rather than clears) the previous value, so a durable
container nested in a transient one is correctly treated as transient.

Verified with AddressSanitizer: the in-frame generator case is clean, the
out-of-frame durable cases succeed, and the out-of-frame generator case
throws.

Assisted-by: ClaudeCode:claude-opus-4.8

* Revert "fix: only add string_view life support for transient sources"

This reverts commit e18b834.

* test: cover string_view argument life support

* test: cover generated and nested string_view lifetimes

* test: cover temporary-backed string_view casts

* test: explain string_view lifetime regression tests

* docs: clarify string_view lifetime requirements

* docs: explain life support for custom view casters

---------

Co-authored-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com>
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