Expand description
C ABI allocator compatibility — xmlMemSetup, xmlMemGet, xmlMalloc, xmlFree, etc. (§58).
This module implements the complete memory hook system exposed by libxml2:
- Global allocator function pointers (malloc, realloc, free, strdup)
xmlMemSetup()/xmlMemGet()— set/get allocator hooksxmlGcMemSetup()/xmlGcMemGet()— GC-aware allocator hooks (wrappers)xmlMalloc()/xmlMallocAtomic()/xmlRealloc()/xmlFree()/xmlMemStrdup()xmlMemUsed()/xmlMemBlocks()— allocation trackingxmlMemDisplay()/xmlMemShow()— debugging output
§Phase 1 status
Complete — all allocator APIs are implemented; state lives in the five
exported function-pointer variables exactly as upstream (globals.c),
giving xmlMemSetup and direct xmlMalloc = custom assignment one
shared override mechanism (R-000176).
§Safety
Allocator hooks are unsafe because they operate on raw pointers and are called
from C code. Every public function documents its safety contract.
§Upstream contract
The parity target is libxml2 2.15.3 (SRC-LIBXML2-2.15.0-XMLMEMORY-C:
oracle/historical/src/libxml2-2.15.0/xmlmemory.c) plus the allocator globals
of globals.c. The 5 allocator entry points (xmlMalloc, xmlMallocAtomic,
xmlRealloc, xmlFree, xmlMemStrdup) are exported as DATA function-pointer
globals matching the upstream XMLPUBVAR declarations (R-000162).
§Conceptual behavior
This module implements the complete libxml2 memory-hook system: swappable
allocator hooks via xmlMemSetup/xmlMemGet (and the GC aliases), a
per-block metadata registry mirroring upstream xmlmemory.cs debug block
table, and the tracking/debug entry points built on it (xmlMemUsed,
xmlMemBlocks, xmlMemSize, xmlMemDisplay*, xmlMemShow,
xmlMemoryDump).
§Ownership & safety invariants
Every pointer returned by an xml* allocator must be freed with xmlFree
(OWNERSHIP_ATLAS section 1). The block registry records
ptr -> (size, file, line) so xmlMemSize and the dumps are exact, and
xmlMemUsed/xmlMemBlocks track live totals. xmlMemSetup custom
allocators bypass the registry (counters only), matching upstreams
debug-allocator-only contract. xmlFree on a foreign/unknown pointer is a
registry-removal no-op instead of upstreams corruption — a documented safe
divergence (OWNERSHIP_ATLAS section 8).
§Historical quirks & epochs
R-000131 (11.1-J): the legacy allocator surface was simplified before the
per-block registry existed — xmlMemSize returned 0 and the *Loc variants
ignored file/line. Since the 11.1-J fix the registry is the source of truth;
xmlMemShows upstream most-recent ordering is still not reproduced
(documented divergence). R-000133 (11.1-H): the legacy names
(xmlMemMalloc/xmlMemFree/xmlMemRealloc/xmlMemoryStrdup) were
declared-but-unexported and had to be implemented for the honest-header
rule.
§Deliberate oddities
xmlMemSetup/direct variable assignment bypass the accounting registry
(deliberate: upstream’s block table exists only in the debug allocator).
The default allocator routes through Rust’s global allocator but the five
exported variables (xmlMalloc, xmlMallocAtomic, xmlRealloc, xmlFree,
xmlMemStrdup) default to the *Default accounting bodies, so downstream
xmlMemSetup swaps behave identically to upstream. The exported variables
are the single source of truth (R-000176, 11.1-Z.2): xmlMemSetup assigns
them and every internal allocation reads them through the *Impl
indirection, exactly like upstream internal xmlMalloc(...) calls.
§Proving courts
ABI-DATA, ALLOCATOR, GLOBAL-STATE and THREADING court families; the
allocator probes (tools/abi/*_probe.py + courts/suites/data-abi/*)
compile the same C probe against the oracle DSO and the candidate and
require byte-identical output; the DSO-LOADER court resolves every exported
symbol from the built DSO.
§Tempting simplifications that would break parity
A tempting simplification is to drop the per-block registry and return 0
from xmlMemSize — that is exactly the pre-R-000131 state and would break
the ALLOCATOR probes, xmlMemUsed exactness, and every downstream
allocator-debugging consumer. Another tempting shortcut is exporting the
allocator entry points as plain functions — upstream exports them as data
function pointers, so the allocator-override mechanism (xmlMalloc =
custom) could not link (R-000162 lesson).
Statics§
- xmlFree
xmlFreeFunc xmlFree— the free hook.- xmlMalloc
xmlMallocFunc xmlMalloc— the malloc hook (default:xmlMallocDefault).- xmlMalloc
Atomic xmlMallocFunc xmlMallocAtomic— the atomic-malloc hook.- xmlMem
Strdup xmlStrdupFunc xmlMemStrdup— the strdup hook.- xmlRealloc
xmlReallocFunc xmlRealloc— the realloc hook.
Functions§
- xmlCleanup
Memory - Clean up the memory layer.
- xmlFree
Impl ⚠ - Free through the exported
xmlFreevariable. - xmlGc
MemGet ⚠ - Get GC-aware memory allocator functions (upstream xmlmemory.h).
- xmlGc
MemSetup ⚠ - Set GC-aware memory allocator functions (upstream xmlmemory.h).
- xmlInit
Memory - Initialize the memory layer with debugging support.
- xmlMalloc
Atomic ⚠Impl - Allocate through the exported
xmlMallocAtomicvariable. - xmlMalloc
Atomic ⚠Loc - Allocate zeroed memory, recording the allocation site (upstream xmlmemory.h).
- xmlMalloc
Atomic ⚠Zero - Allocate zero-initialized memory (atomic variant).
- xmlMalloc
Impl ⚠ - Allocate memory through the exported
xmlMallocvariable. - xmlMalloc
Loc ⚠ - Allocate memory, recording the allocation site (upstream xmlmemory.h).
- xmlMalloc
Zero ⚠ - Allocate zero-initialized memory.
- xmlMem
Blocks - Return the current number of allocated blocks (approximate).
- xmlMem
Display ⚠ - Display memory allocation information to a file.
- xmlMem
Display ⚠Last - Display a limited amount of memory debug information (upstream xmlmemory.h).
- xmlMem
Free ⚠ - Free memory (legacy name; same contract as
xmlFree). - xmlMem
Get ⚠ - Get the current memory allocator functions (upstream xmlmemory.h).
- xmlMem
Malloc ⚠ - Allocate memory (legacy name; same contract as
xmlMalloc). - xmlMem
Realloc ⚠ - Reallocate memory (legacy name; same contract as
xmlRealloc). - xmlMem
Setup ⚠ - Set custom memory allocator functions (upstream xmlmemory.h).
- xmlMem
Show ⚠ - Show memory allocation information.
- xmlMem
Size ⚠ - Return the size of an allocated block (upstream xmlmemory.h).
- xmlMem
Strdup ⚠Impl - Duplicate a C string through the exported
xmlMemStrdupvariable. - xmlMem
Strdup ⚠Loc - Duplicate a string, recording the allocation site (upstream xmlmemory.h).
- xmlMem
Used - Return the total amount of memory currently allocated (approximate).
- xmlMemory
Dump ⚠ - Dump memory allocation statistics (upstream xmlmemory.h).
- xmlMemory
Strdup ⚠ - Duplicate a string (legacy name; same contract as
xmlMemStrdup). - xmlRealloc
Impl ⚠ - Reallocate through the exported
xmlReallocvariable. - xmlRealloc
Loc ⚠ - Reallocate memory, recording the allocation site (upstream xmlmemory.h).
- xmlRealloc
Zero ⚠ - Reallocate and zero-initialize the new portion.