Commit 8a487f2
committed
Unify the shadow reflection engine and prune its API (#356)
Review pass over the shadow-copy branch. The design stands; the helper
layer had grown two reflection engines (End for single-site template
calls, ReflectAll for multi-site sign/encrypt) plus five single-use
entry points. Collapse them into one engine so every binding uses the
same few lines:
- One reflection walk: fresh nodes are grafted at their child index,
and every parent that gained a node has its text slots (.text and
the children's .tail) synced wholesale from the re-parsed copy. The
sync replaces the old per-element "mirror" heuristic and also covers
text the call removed (encrypt Type=Content), which no fresh-node
scan can see.
- End maps the result node back after reflecting: grafted, or found
(attributes synced; a renamed prefix swaps in the copy's version).
It serves every Begin flavour, so EndNewDoc and EndReplace go away.
- Reflect(shadow, rv, error) ends status-returning calls in one line
(sign, encrypt_binary, encrypt_uri, C14N inclusive namespaces);
FindFresh is gone.
- BeginDoc replays the registered IDs itself; ReplayIds and DumpCopy
become static. Header: 15 -> 10 functions.
- Our re-parse uses XML_PARSE_HUGE and a cached huge_tree lxml parser,
so a CipherValue above libxml2's 10 MB text-node limit reflects
(12 MB encrypt_binary/decrypt round trip verified); path depth 256.
- The enc.c shadow bodies clear XMLSEC_ENC_RETURN_REPLACED_NODE
explicitly: xmlsec must free replaced nodes with our libxml2 before
the copy is discarded (it already did, implicitly).
Also fixes a pre-existing crash on the raw path, found by the new
tests: encrypt_xml with Type=Content on text or mixed content put text
nodes into xmlsec's replaced-node list, and PyXmlSec_ClearReplacedNodes
handed them to lxml's elementFactory; lxml frees the text siblings that
follow an element when its proxy is released, so the next list entry
was freed under our feet. Each node is now severed from the chain
before release and non-element nodes are freed directly.
Tests: decrypt of Type=Content with whitespace around EncryptedData
and with mixed content, register_id sign/verify round trip, prefix
rename on a live KeyInfo. Docs consolidated into developer.md
(356-summary.md and converting-functions.md removed).
Validated: real 2.14.6/2.15.3 mismatch 292 passed / 6 skipped, 10k
loop with flat RSS and byte-identical output; matched static wheel
304 / 6 on both the fast path and PYXMLSEC_FORCE_SHADOW=1.1 parent 92d68ad commit 8a487f2
11 files changed
Lines changed: 1072 additions & 1187 deletions
This file was deleted.
This file was deleted.
0 commit comments