Skip to content

Stability Guarantees

Lanexio Parser makes three public stability commitments. They are tested in CI, backed by fuzz harnesses, and enforced by architectural constraints. Breaking any one of them is a P0 bug.

parse(), reparse(), and streaming parse methods never throw. Malformed input produces LexError nodes in the AST. Exceptions never leave the parse boundary.

import { parseHtml } from '@lanexio/parser-grammar-html';
// This never throws, even on deeply malformed input.
const encoder = new TextEncoder();
const tree = parseHtml(encoder.encode('<<<<<\x00\xFF\xFE'));
// Check for parse errors in the tree.
for (const node of tree.root.children()) {
if (node.hasError) {
console.log('parse error at', node.range);
}
}
  • You do not need to wrap parseHtml or parseMarkdown in a try-catch.
  • Malformed input is always safe to pass to the parser.
  • The return value is always a valid LexTree.
  • The returned tree may contain LexError nodes. It is your responsibility to detect and handle them.
  • Third-party code you call with the parse output (e.g., innerHTML = serializeHtml(tree)) may behave unexpectedly on malformed input. That is outside the parse boundary.

Guarantee 2: Panic-Free Byte Sequence Immunity

Section titled “Guarantee 2: Panic-Free Byte Sequence Immunity”

No byte sequence of any length causes a panic, unhandled exception, or silent memory corruption.

This guarantee is backed by:

  • Iterative state machines (no recursion in parser hot paths)
  • Wrapping arithmetic operators in all Zig hot paths
  • Bounds checking before every slice index on user input
  • 24-hour continuous fuzz soak on every release

At tag v1.0.0, a 24-hour continuous fuzz soak ran 13 harnesses across all grammar packs:

HarnessCases / 24hResult
core-soak (parse)594,620,6740 crashes
html-char-eof3,829,498,4860 crashes
html-fragment-ns3,278,712,4340 crashes
html-frameset3,185,115,0650 crashes
html-aa-byte-range1,899,683,0160 crashes
html-foster-parent1,413,404,0610 crashes
html-aa-tree-shape1,179,886,4460 crashes
json-parse1,065,749,1990 throws
yaml-parse970,495,7530 throws
html-orphan-p823,743,5730 crashes
html-rawtext-nul604,480,3590 violations
css-parse403,933,2930 throws
html-noscript247,989,7170 violations
Total~20,000,000,0000 failures
  • You can pass any arbitrary byte sequence (null bytes, invalid UTF-8, binary data, adversarial inputs) to parseHtml or parseMarkdown without crashing the process.
  • The output is always a valid LexTree with the appropriate LexError nodes.
  • The parser accepts and structures malformed input. It is not a validator and does not diagnose every violation.
  • Performance on adversarial input may be slower than typical workloads, though the parser is bounded and will not hang or exhaust resources.

Guarantee 3: Deterministic 3-Token Recovery Window

Section titled “Guarantee 3: Deterministic 3-Token Recovery Window”

After a syntax error, the parser resyncs to a valid construct within 3 tokens.

This means:

  • Parse errors do not cascade indefinitely.
  • The tree shape after an error is bounded and predictable.
  • For any given input, parseHtml(input) always produces the same LexTree (deterministic output).
  • Calling parseHtml(input) twice with the same input always returns an equivalent tree.
  • Error recovery is local and bounded.
  • The parser resumes at a valid grammar point after an error, but the semantic meaning of the recovered subtree depends on the document.
  • The 3-token window applies to spec-defined recovery paths. Certain error classes (e.g., deeply nested malformed trees) may have documented exceptions.
GuaranteeWhat it coversHow it is enforced
Never-throwparse(), reparse(), streaming methodspnpm verify:no-throw, Vitest never-throw harness
Panic-freeAny byte sequence inputZig fuzz harnesses, zig build fuzz
3-token recoveryBounded error recovery in parse treesCorpus entries in corpus/malformed/, recovery.zig