PureXML/Sources/XSLT
Mihaela Mihaljevic dc6727538d
perf(xslt): make the template evaluator iterative (#358)
The XSLT engine was mutually recursive on template-application and result-tree
nesting (instantiate, evaluate, applyTemplates), so a recursive named template
whose depth comes from source data could overflow the native stack (SIGBUS) on
attacker-controllable input, and an identity transform of a deep source
overflowed on a small (Swift-concurrency Task) stack.

The engine is now an explicit work-stack driver (XSLTDriver). Each instruction
appends its produced items to a sink or pushes sub-work, with the rest of the
body pushed first so result-tree document order is preserved; template
application, the built-in rule's source descent, and result-element nesting all
run on the heap. Only stylesheet-bounded helper evaluation (a variable's or
parameter's result-tree fragment, an attribute set, an xsl:message body)
re-enters through a nested driver call, whose native depth is bounded by the
stylesheet's own nesting.

The result-tree serialization walks the engine now exposes at depth were made
iterative too: XSLTNamespaceFixup (an explicit pre-order visit that keeps the
ns0/ns1 counter in document order), the text and string-value extractions
(iterative accumulators), and the content-type-meta and CDATA-section rewrites
(the shared Node.rebuildingBottomUp spine).

Deep recursion now succeeds on any stack: a 5000-level recursive template builds
and serializes on the test Task stack. maxTemplateDepth is retained as runaway
protection (an unbounded result tree would exhaust memory), defaulting to 40000
and throwing XSLTError.recursionLimitExceeded only past that.

Behavior is otherwise unchanged: the full Apache Xalan XSLT 1.0 conformance
corpus (1086 cases) and the in-repo XSLT/XPath suites pass identically; one
previously-failing Xalan case (mdocs07) now passes and was de-baselined. Full
suite green. Closes #356.
2026-06-27 19:29:51 +02:00
..
XSLTAVT.swift feat(xslt): implement xsl:namespace-alias, completing #81 2026-06-09 02:10:16 +02:00
XSLTCollation.swift feat(xpath,xslt,wasm): evaluation budget, tailored collation, WASI runtime proof 2026-06-11 06:26:13 +02:00
XSLTDocumentCache.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTElements.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTFunctions.swift fix(xslt): make key(), id(), and EXSLT set functions linear over wide fan-outs (#300) 2026-06-25 18:45:08 +02:00
XSLTGlobals.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTInstantiation.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTInstantiationElements.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTInstantiationSteps.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTLookups.swift perf(xslt): direct ID lookup in id() instead of full-index scan (#315) 2026-06-26 04:25:58 +02:00
XSLTMatchCache.swift XSLT/XPath conformance: close 68 Apache Xalan cases (#254) 2026-06-24 00:13:14 +02:00
XSLTModel.swift fix(xslt): xsl:namespace-alias keeps the literal prefix, remapping only the URI (closes namespace19/23/24/35/113) (#273) 2026-06-24 15:43:02 +02:00
XSLTNamespaceFixup.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTNumbering.swift perf(xslt): cache xsl:number level single/multiple sibling ranks (#310) 2026-06-26 01:13:07 +02:00
XSLTParser.swift fix(xslt): bound template recursion so it fails gracefully, not with a crash (#357) 2026-06-27 18:30:19 +02:00
XSLTParserDeclarations.swift fix(xslt): xsl:namespace-alias keeps the literal prefix, remapping only the URI (closes namespace19/23/24/35/113) (#273) 2026-06-24 15:43:02 +02:00
XSLTParserEntry.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTParserStructural.swift fix(xslt): evaluate the xsl:number format attribute as an AVT (#269) 2026-06-24 10:40:11 +02:00
XSLTRawText.swift feat(xslt): output methods in depth 2026-06-10 13:10:50 +02:00
XSLTRuntime.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTSorting.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTTransform.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTTransformer.swift perf(xslt): make the template evaluator iterative (#358) 2026-06-27 19:29:51 +02:00
XSLTUnitCollector.swift fix(xslt): composition cycles terminate; id() gains a per-document index 2026-06-10 18:07:02 +02:00
XSLTWhitespace.swift fix(xslt): match strip-space/preserve-space element tests by namespace (#265) 2026-06-24 03:52:45 +02:00