Conversation
|
@toddr-bot an alternate solution was provided at https://github.com/cpan-authors/XML-LibXML/pull/105/changes. Compare it to the solution provided here. |
Comparison: PR #105 vs PR #180Both fix the same use-after-free in PR #105 — "compute fresh"Removes the early PmmFixOwner(PmmPROXYNODE(nNode),
PmmPROXYNODE((xmlNodePtr)nNode->doc));
PR #180 — "reorder"Keeps the early if ( nNode->_private != NULL ) {
PmmFixOwner(PmmPROXYNODE(nNode), owner);
}
LibXML_reparent_removed_node(ret);
CorrectnessBoth are correct for the documented bug. The mechanism:
PR #180 ensures step 3 can't free the owner because step 2.5 (the moved Comparison with
|
| PR #105 | PR #180 | |
|---|---|---|
| Location | New file t/73replaceNode_double_free_gh62.t |
Appended to t/04node.t |
| Tests | 8 (4 scenarios) | 2 (1 scenario) |
| Coverage | Standalone node, same-doc, dropped doc ref, children | Standalone node only |
PR #180 follows the project convention of adding to existing test files. PR #105 has broader scenario coverage.
Recommendation
PR #180's reorder approach is the better fit. It's the canonical fix for refcount ordering bugs — ensure increment before decrement — and the minimal diff reduces review surface. That said, PR #105's additional test scenarios (same-document replacement, document-ref-dropped, replacement with children) are worth adopting into t/04node.t for coverage.
|
@toddr-bot rebase |
#62) When replaceNode() was called with a new node created via Element->new() (not associated with any document), and the old node's parent proxy had no other Perl references, LibXML_reparent_removed_node() would free the parent proxy before PmmFixOwner() used it to set the new node's ownership — a use-after-free leading to double-free crashes. Fix by reordering: update the new node's proxy ownership before reparenting the removed node into a document fragment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
27aee0c to
955a660
Compare
What
Fix a use-after-free in
replaceNode()that causes double-free crashes when the replacement node was created standalone (viaElement->new) and the old node's parent has no other Perl references.Why
When
$foo->replaceNode($bar)is called where$barcomes fromElement->new()(no document association), the parent node's proxy may have a refcount of only 1 (held solely by$foo's ownership chain). The code capturesowner = PmmOWNERPO(PmmPROXYNODE(self))early, then callsLibXML_reparent_removed_node(ret)which changes the old node's ownership — decrementing the parent proxy's refcount to 0 and freeing it. The subsequentPmmFixOwner(PmmPROXYNODE(nNode), owner)then dereferences the freed proxy pointer.How
Reorder the operations so the new node's proxy ownership is updated before the removed node is reparented into a document fragment. This ensures the parent proxy's refcount is incremented (by the new node's ownership) before it can be decremented to zero (by the old node's ownership change).
Testing
t/04node.tcovering the exact scenario🤖 Generated with Claude Code
Quality Report
Changes: 2 files changed, 36 insertions(+), 4 deletions(-)
Code scan: clean
Tests: passed (OK)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline