Skip to content

Commit 86f3e25

Browse files
committed
fix: strdup args added after initialize_generic in def_property_static (pybindgh-5976)
`def_property_static` calls `process_attributes::init` on already-initialized function records (after `initialize_generic`'s strdup loop has run). Args added at this stage (e.g. "self" via `append_self_arg_if_needed`) remain as string literals, so `destruct()` would call `free()` on them. Fix by strdup'ing name/descr of any args appended by the late `process_attributes::init` call. Root cause introduced by pybindgh-5486. Made-with: Cursor
1 parent 3b62426 commit 86f3e25

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

include/pybind11/pybind11.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,19 +2687,41 @@ class class_ : public detail::generic_type {
26872687
if (rec_fget) {
26882688
char *doc_prev = rec_fget->doc; /* 'extra' field may include a property-specific
26892689
documentation string */
2690+
auto args_before = rec_fget->args.size();
26902691
detail::process_attributes<Extra...>::init(extra..., rec_fget);
26912692
if (rec_fget->doc && rec_fget->doc != doc_prev) {
26922693
std::free(doc_prev);
26932694
rec_fget->doc = PYBIND11_COMPAT_STRDUP(rec_fget->doc);
26942695
}
2696+
// Args added by process_attributes (e.g. "self" via is_method + pos_only/kw_only)
2697+
// need their strings strdup'd: initialize_generic's strdup loop already ran during
2698+
// cpp_function construction, so it won't process these late additions. Without this,
2699+
// destruct() would call free() on string literals. See gh-5976.
2700+
for (auto i = args_before; i < rec_fget->args.size(); ++i) {
2701+
if (rec_fget->args[i].name) {
2702+
rec_fget->args[i].name = PYBIND11_COMPAT_STRDUP(rec_fget->args[i].name);
2703+
}
2704+
if (rec_fget->args[i].descr) {
2705+
rec_fget->args[i].descr = PYBIND11_COMPAT_STRDUP(rec_fget->args[i].descr);
2706+
}
2707+
}
26952708
}
26962709
if (rec_fset) {
26972710
char *doc_prev = rec_fset->doc;
2711+
auto args_before = rec_fset->args.size();
26982712
detail::process_attributes<Extra...>::init(extra..., rec_fset);
26992713
if (rec_fset->doc && rec_fset->doc != doc_prev) {
27002714
std::free(doc_prev);
27012715
rec_fset->doc = PYBIND11_COMPAT_STRDUP(rec_fset->doc);
27022716
}
2717+
for (auto i = args_before; i < rec_fset->args.size(); ++i) {
2718+
if (rec_fset->args[i].name) {
2719+
rec_fset->args[i].name = PYBIND11_COMPAT_STRDUP(rec_fset->args[i].name);
2720+
}
2721+
if (rec_fset->args[i].descr) {
2722+
rec_fset->args[i].descr = PYBIND11_COMPAT_STRDUP(rec_fset->args[i].descr);
2723+
}
2724+
}
27032725
if (!rec_active) {
27042726
rec_active = rec_fset;
27052727
}

0 commit comments

Comments
 (0)