From 17d0d632392c6a1d2bec43158ddd860a26aba707 Mon Sep 17 00:00:00 2001 From: Charles Beattie Date: Fri, 19 Jun 2026 17:09:47 +0000 Subject: [PATCH 1/3] Fix handling of string_view to prevent GC'ing strings before they are used. --- include/pybind11/cast.h | 9 +++++++++ tests/test_stl.cpp | 11 +++++++++++ tests/test_stl.py | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index b7a4c2b0ce..ec5ae02e38 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -526,6 +526,9 @@ struct string_caster { return false; } value = StringType(buffer, static_cast(size)); + if (IsView) { + loader_life_support::add_patient(src); + } return true; } @@ -603,6 +606,9 @@ struct string_caster { pybind11_fail("Unexpected PYBIND11_BYTES_AS_STRING() failure."); } value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + if (IsView) { + loader_life_support::add_patient(src); + } return true; } if (PyByteArray_Check(src.ptr())) { @@ -613,6 +619,9 @@ struct string_caster { pybind11_fail("Unexpected PyByteArray_AsString() failure."); } value = StringType(bytearray, (size_t) PyByteArray_Size(src.ptr())); + if (IsView) { + loader_life_support::add_patient(utfNbytes); + } return true; } diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index 8bddbb1f38..b1b46b01ea 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -582,6 +582,17 @@ TEST_SUBMODULE(stl, m) { [](const std::list &) { return 2; }); m.def("func_with_string_or_vector_string_arg_overload", [](const std::string &) { return 3; }); +#ifdef PYBIND11_HAS_STRING_VIEW + m.def("func_with_string_views", + [](const std::vector &svs) { + py::list l; + for (std::string_view sv : svs) { + l.append(sv); + } + return l; + }); +#endif + class Placeholder { public: Placeholder() { print_created(this); } diff --git a/tests/test_stl.py b/tests/test_stl.py index b04f55c9f8..405f6eae25 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -28,6 +28,13 @@ def test_vector(doc): # Test regression caused by 936: pointers to stl containers weren't castable assert m.cast_ptr_vector() == ["lvalue", "lvalue"] + if hasattr(m, "func_with_string_views"): + def gen(): + return ('a' + str(x) for x in range(10000, 10010)) + expected = list(gen()) + assert m.func_with_string_views(gen()) == expected + assert m.func_with_string_views((x.encode() for x in gen())) == expected + assert m.func_with_string_views((bytearray(x.encode()) for x in gen())) == expected def test_deque(): """std::deque <-> list""" From 61a62569571b9a7ee4b4100f414f63eaff8ad529 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:23:30 +0000 Subject: [PATCH 2/3] style: pre-commit fixes --- tests/test_stl.cpp | 15 +++++++-------- tests/test_stl.py | 11 ++++++++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index b1b46b01ea..526c7643ac 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -583,14 +583,13 @@ TEST_SUBMODULE(stl, m) { m.def("func_with_string_or_vector_string_arg_overload", [](const std::string &) { return 3; }); #ifdef PYBIND11_HAS_STRING_VIEW - m.def("func_with_string_views", - [](const std::vector &svs) { - py::list l; - for (std::string_view sv : svs) { - l.append(sv); - } - return l; - }); + m.def("func_with_string_views", [](const std::vector &svs) { + py::list l; + for (std::string_view sv : svs) { + l.append(sv); + } + return l; + }); #endif class Placeholder { diff --git a/tests/test_stl.py b/tests/test_stl.py index 405f6eae25..8b97c76195 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -29,12 +29,17 @@ def test_vector(doc): assert m.cast_ptr_vector() == ["lvalue", "lvalue"] if hasattr(m, "func_with_string_views"): + def gen(): - return ('a' + str(x) for x in range(10000, 10010)) + return ("a" + str(x) for x in range(10000, 10010)) + expected = list(gen()) assert m.func_with_string_views(gen()) == expected - assert m.func_with_string_views((x.encode() for x in gen())) == expected - assert m.func_with_string_views((bytearray(x.encode()) for x in gen())) == expected + assert m.func_with_string_views(x.encode() for x in gen()) == expected + assert ( + m.func_with_string_views(bytearray(x.encode()) for x in gen()) == expected + ) + def test_deque(): """std::deque <-> list""" From 114df3d56ea1d96fa0f8c011681a11b22b4c4c12 Mon Sep 17 00:00:00 2001 From: Charles Beattie Date: Fri, 19 Jun 2026 18:29:21 +0100 Subject: [PATCH 3/3] Update cast.h --- include/pybind11/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index ec5ae02e38..32e730f50a 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -620,7 +620,7 @@ struct string_caster { } value = StringType(bytearray, (size_t) PyByteArray_Size(src.ptr())); if (IsView) { - loader_life_support::add_patient(utfNbytes); + loader_life_support::add_patient(src); } return true; }