Skip to content

fix: prevent elname SV leak when Start/End handlers die#260

Merged
toddr merged 1 commit intomainfrom
koan.toddr.bot/fix-callback-exception-leaks
Apr 23, 2026
Merged

fix: prevent elname SV leak when Start/End handlers die#260
toddr merged 1 commit intomainfrom
koan.toddr.bot/fix-callback-exception-leaks

Conversation

@toddr-bot
Copy link
Copy Markdown
Collaborator

@toddr-bot toddr-bot commented Apr 15, 2026

What

Fix memory leak of element name SVs when Start or End handlers throw exceptions.

Why

When a Start handler dies, call_sv longjmps past av_push(cbv->context, elname) — the element name SV (refcount 1) is never stored or freed. Similarly in endElement, SvREFCNT_dec(elname) is skipped. Every handler exception leaks one SV. This adds up in applications that parse untrusted XML and use handlers that validate/reject content by dying.

How

Use SAVEFREESV(elname) inside the ENTER/LEAVE scope that wraps the call_sv. This registers the SV for automatic cleanup if the scope unwinds via exception. On the normal (non-exception) path, SvREFCNT_inc_simple_void(elname) before LEAVE preserves the SV for the post-scope operations (av_push in startElement, SvREFCNT_dec in endElement).

Audited all 19 XS callbacks — startElement and endElement are the only ones with non-mortal SVs across a call_sv boundary. All other callbacks properly use sv_2mortal before pushing SVs.

Testing

  • Added t/handler_die.t with 6 tests: Start/End die propagation, parser reuse after exception, and stress test (10 consecutive exception cycles)
  • Full test suite passes

🤖 Generated with Claude Code


Quality Report

Changes: 2 files changed, 91 insertions(+), 1 deletion(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

When a Start or End handler throws an exception via die/croak, the
call_sv longjmp skips the cleanup code after it: av_push(context) in
startElement and SvREFCNT_dec(elname) in endElement. The element name
SV leaks on every handler exception.

Fix: register elname with SAVEFREESV inside the ENTER/LEAVE scope so
Perl's scope cleanup frees it on exception unwind. On normal exit,
SvREFCNT_inc before LEAVE keeps it alive for the post-scope cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.63%. Comparing base (45216a7) to head (103a592).
⚠️ Report is 14 commits behind head on main.

Files with missing lines Patch % Lines
Expat/Expat.xs 50.00% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #260      +/-   ##
==========================================
- Coverage   75.73%   75.63%   -0.10%     
==========================================
  Files           1        1              
  Lines        1092     1096       +4     
  Branches      342      344       +2     
==========================================
+ Hits          827      829       +2     
  Misses         59       59              
- Partials      206      208       +2     
Flag Coverage Δ
perl 75.63% <50.00%> (-0.10%) ⬇️
xs 75.63% <50.00%> (-0.10%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@toddr toddr marked this pull request as ready for review April 23, 2026 10:10
@toddr toddr merged commit 9218551 into main Apr 23, 2026
34 of 36 checks passed
@toddr toddr deleted the koan.toddr.bot/fix-callback-exception-leaks branch April 23, 2026 10:10
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