Skip to content

Fixes memory leak on every node accessor - #38

Merged
redvers merged 1 commit into
mainfrom
fix/raw-xmlchar-leaks
May 22, 2026
Merged

Fixes memory leak on every node accessor#38
redvers merged 1 commit into
mainfrom
fix/raw-xmlchar-leaks

Conversation

@redvers

@redvers redvers commented May 22, 2026

Copy link
Copy Markdown
Collaborator

libxml2 has functions that return const xmlChar* / const char* /
const unsigned char* and must not be freed by the caller. Freeing
them either corrupts a libxml2-owned buffer (xmlBufferContent,
xmlOutputBufferGetContent) or attempts to free a pointer into the
caller's input string (xmlStrchr, xmlSplitQName3) or a parser-owned
name table (xmlParseName, xmlTextReaderConst*).

Authoritative source: meta/libxml2.xml (the castxml output) records
the C-level return type of every function. Pointer types _2682,
_2695, _2696 are const char*, const xmlChar*, const unsigned char* respectively. 53 libxml2 functions return one of
these; 42 of them are wrapped through this generator (the remaining
11 are ICU symbols ucnv_* / u_errorName_74 which the Pony binding
does not wrap).

Mechanism

Two typedefs in usetypes.xml: String emits an Xml2Free call after
the clone; String val does not. use.xml's per-function rv
attribute selects which typedef applies. castxml2pony emits
rv="String" for every xmlChar*-returning function regardless of
const-ness; the 42 const-returning entries are rewritten to
rv="String val".

Changes

meta/Makefile: castxml2pony_uses gains a sed loop over a
CONST_RETURN_FNS variable that marks each const-returning entry's
as rv="String val". The list lives in the Makefile so the
conversion replays on any future full regen from castxml output.

meta/uses/use.xml: 41 entries rewritten to rv="String val"
(xmlBufferContent was already done).

meta/functions.pony, meta/uses.pony, libxml2/raw/functions.pony,
libxml2/raw/uses.pony: regen output. The 40 newly exempted
wrappers now return String val and skip the free.

Tests

None of the newly exempted functions are called from the in-scope
Pony API. All 63 existing tests pass; stability confirmed across 4
consecutive runs. TestRepeatedCstringAccessors continues to
exercise xmlBufferContent through nodeDump.

If a future PR wraps any of the now-exempted functions, the Pony
API call site receives String val instead of String. That is
the correct shape for borrowed-from-libxml2 strings; it does not
break any existing caller.

libxml2 has functions that return const xmlChar* / const char* /
const unsigned char* and must not be freed by the caller. Freeing
them either corrupts a libxml2-owned buffer (xmlBufferContent,
xmlOutputBufferGetContent) or attempts to free a pointer into the
caller's input string (xmlStrchr, xmlSplitQName3) or a parser-owned
name table (xmlParseName, xmlTextReaderConst*).

Authoritative source: meta/libxml2.xml (the castxml output) records
the C-level return type of every function. Pointer types `_2682`,
`_2695`, `_2696` are `const char*`, `const xmlChar*`, `const
unsigned char*` respectively. 53 libxml2 functions return one of
these; 42 of them are wrapped through this generator (the remaining
11 are ICU symbols ucnv_* / u_errorName_74 which the Pony binding
does not wrap).

Mechanism
---------

Two typedefs in usetypes.xml: `String` emits an Xml2Free call after
the clone; `String val` does not. use.xml's per-function `rv`
attribute selects which typedef applies. castxml2pony emits
rv="String" for every xmlChar*-returning function regardless of
const-ness; the 42 const-returning entries are rewritten to
rv="String val".

Changes
-------

meta/Makefile: castxml2pony_uses gains a sed loop over a
CONST_RETURN_FNS variable that marks each const-returning entry's
<use> as rv="String val". The list lives in the Makefile so the
conversion replays on any future full regen from castxml output.

meta/uses/use.xml: 41 <use> entries rewritten to rv="String val"
(xmlBufferContent was already done).

meta/functions.pony, meta/uses.pony, libxml2/raw/functions.pony,
libxml2/raw/uses.pony: regen output. The 40 newly exempted
wrappers now return `String val` and skip the free.

Tests
-----

None of the newly exempted functions are called from the in-scope
Pony API. All 63 existing tests pass; stability confirmed across 4
consecutive runs. TestRepeatedCstringAccessors continues to
exercise xmlBufferContent through nodeDump.

If a future PR wraps any of the now-exempted functions, the Pony
API call site receives `String val` instead of `String`. That is
the correct shape for borrowed-from-libxml2 strings; it does not
break any existing caller.
@redvers
redvers force-pushed the fix/raw-xmlchar-leaks branch from d38fda1 to 504a823 Compare May 22, 2026 06:32
@redvers
redvers merged commit f107c71 into main May 22, 2026
6 checks passed
@redvers
redvers deleted the fix/raw-xmlchar-leaks branch May 22, 2026 06:36
github-actions Bot pushed a commit that referenced this pull request May 22, 2026
github-actions Bot pushed a commit that referenced this pull request May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant