Expand description
String utility functions for libxml-rs.
Provides operations on xmlChar* (i.e. *mut u8) strings compatible
with upstream libxml2 string handling.
§Upstream contract
Mirrors upstream xmlstring.c (SRC-LIBXML2-2.15.0-XMLSTRING-C): xmlStrlen, xmlStrdup, xmlStrndup, xmlStrchr, xmlStrstr, xmlStrcmp, xmlStrEqual, xmlStrsub, the UTF-8 helpers and the xmlChar* memory functions. Parity target: the system libxml2 2.15.3 oracle.
§Conceptual behavior
Provides operations on xmlChar* (u8) NUL-terminated strings compatible with upstream semantics: length scan, duplication, comparison, UTF-8 iteration and substring extraction. String values are owned per the upstream contract — the caller frees xmlStrdup results with xmlFree.
§Ownership & safety invariants
SAFETY: functions require NUL-terminated inputs (or NULL); callers own returned copies (freed with xmlFree). The R-000169 lesson applies here: xml_strndup must be used when the source is a Rust String with an exact length — xml_strdup on a non-NUL-terminated as_ptr() scans past the allocation (heap-buffer-overflow, caught by ASan).
§Historical quirks & epochs
The 11.1-X fix (R-000169) switched the parser filename duplication from xml_strdup to xml_strndup(fname.as_ptr(), fname.len()) after ASan pinned the overflow. Historical quirk: the upstream limit macro XML_MAX_TEXT_ LENGHT was misspelled for years (QUIRK-0004, commit 1fb2e0df) — the spelling is part of the observable header surface.
§Deliberate oddities
Deliberate oddity: xml_strdup returns NULL on NULL input and on OOM (matching upstream xmlStrdup); the module deliberately never assumes Rust-length semantics — every operation is NUL-terminated-centric.
§Proving courts
Exercised indirectly by TREE-001 (URL/base fingerprints), ERROR-001
(str1/str2/str3 copies), the data-ABI family probes, and cargo test --lib under ASan (which caught the R-000169 overflow).
§Tempting simplifications that would break parity
The tempting simplification is using Rust String/slices everywhere and dropping the NUL-terminated xmlChar* model — it would break the C ABI (xmlChar* parameters) and the ownership contract. Do not fix xml_strdup callers to assume NUL-termination of Rust Strings: that was the exact heap-buffer-overflow R-000169 fixed.
Functions§
- build_
qname ⚠ - Build a QName
prefix:local(upstream tree.cxmlBuildQName): writes intomemorywhen it is large enough, otherwise allocates. Returns the resulting string (allocator-owned when notmemory), or NULL on error. A NULL prefix returnsncnameunchanged. - check_
utf8 ⚠ - Check that a byte string is valid UTF-8 (upstream
xmlCheckUTF8): returns 1 when valid, 0 otherwise. - split_
qname2 ⚠ - Split a QName into prefix and local part (upstream tree.c
xmlSplitQName2): returns NULL when the name has no prefix (or starts with ‘:’), otherwise allocates*prefixwith the prefix and returns the local part. - split_
qname3 ⚠ - Split a QName returning the local-name pointer (upstream tree.c
xmlSplitQName3): returns a pointer to the local part after the ‘:’ and fills*lenwith the prefix length, or NULL when the name has no prefix (or NULL arguments). R-000176: the candidate previously returned the prefix length as an int. - utf8_
size ⚠ - Size in bytes of the UTF-8 sequence starting at
utf(upstreamxmlUTF8Size): returns the sequence length, or -1 on invalid leading byte, 0 on NUL. - utf8_
strlen ⚠ - Return the number of UTF-8 characters in a string (upstream
xmlUTF8Strlen).