Skip to main content

Module html

Module html 

Source
Expand description

HTML parser and serializer (§29, §85 Phase 4).

The libxml2 historical HTML parser — a tag-recovery parser, NOT a WHATWG HTML5 parser. Preserves version-specific historical behavior.

Implements:

  • Tag-recovery parsing (auto-close, implicit open, case-insensitive)
  • HTML element info table with flags matching libxml2
  • HTML entity resolution
  • Auto-creation of html/head/body when missing
  • HTML-specific serialization (no self-closing void tags, no namespace decls)
  • Minimized and unquoted attribute support

§Upstream contract

Mirrors upstream HTMLparser.c, HTMLtree.c and HTMLdocument.c (SRC-LIBXML2-2.15.0-HTMLPARSER-C et al., parity target libxml2 2.15.3 oracle): the tag-recovery HTML parser, the htmlElementInfo table, htmlDocDump serialization and the htmlDefaultSAXHandler / htmlDefaultSAXLocator data globals (R-000135 exports them byte-identical; htmlInitAutoClose / htmlElementAllowedHere are the R-000138 no-op set).

§Conceptual behavior

Implements libxml2 historical HTML parsing: case-insensitive tag recovery with auto-close and implicit-open rules driven by the htmlElementInfo flags table (HTML_EMPTY/HTML_NO_END/HTML_HEAD/…), HTML entity resolution, auto-creation of html/head/body, minimized and unquoted attributes, and HTML-specific serialization (no self-closing void tags, no namespace declarations). This is deliberately NOT a WHATWG HTML5 parser (WHATWG-HTML).

§Ownership & safety invariants

The parser creates a document the caller owns (freed with xmlFreeDoc, same as XML); elements/attributes are owned by the tree. Serialization borrows the tree and writes through the output buffer. Push-mode input buffers are owned by the parser context (CVE-2015-8242 fixed a push-mode buffer overread upstream, SEC-0008).

§Historical quirks & epochs

E-007: the --html dump became a single line in the 2.15.0 epoch — six xmlOutputBufferWriteString(buf, "\n") calls were removed from HTMLtree.c (commits 0d81d6f8, 46f05ea4); the crate matches the 2.15+ single-line epoch. R-000118 locked the HTML output method for XSLT. The tag-recovery rules themselves go back to the 1.x/2.0 HTML era and stay version-faithful.

§Deliberate oddities

The htmlElementInfo table ordering and flag values reproduce upstream exactly (R-000135 DATA-GLOBALS-001 fingerprints the default handler slots); case-folding and the auto-close stack follow HTMLparser.c rather than the WHATWG spec — a deliberate historical fidelity choice.

§Proving courts

HTML-* courts (SEC-0008), the CLI --html differential cases (html-dump epoch case in SEMANTIC_EPOCHS.md) and DATA-GLOBALS-001 compare output byte-identical against the oracle; cargo test runs the HTML unit suites.

§Tempting simplifications that would break parity

Do not switch to a WHATWG HTML5 parser: downstream consumers depend on libxml2 tag-recovery quirks. Do not re-add newlines to the dump (E-007 epoch) and do not reorder or re-flag the element table — both are observable through the serializer and the exported data globals.

§Safety

  • Raw _xmlDoc, _xmlNode, _xmlAttr and _xmlBuffer pointers are allocated by the crate allocator (or the tree helpers) and must stay valid for the duration of each call; owned documents are freed with tree::free_doc and buffers with the matching xmlFreeImpl routine.
  • HtmlParserCtxt.input must be non-NULL and readable for input_len bytes whenever input_pos is below input_len; every read is bounds-checked against input_len before dereferencing.
  • Node trees walked through parent, children, next and properties links must be well-formed: links are NULL-terminated, the parent chain terminates (no cycles), and every node in a chain is a valid _xmlNode.
  • name, content, version and encoding fields are NULL or valid NUL-terminated xmlChar strings.

Functions§

parse_file
Parse HTML from a file.
parse_memory
Parse HTML from a memory buffer.