clone_with_prefixes produces non-deterministic namespace node ordering#46
Open
frankarensmeier wants to merge 1 commit into
Open
clone_with_prefixes produces non-deterministic namespace node ordering#46frankarensmeier wants to merge 1 commit into
clone_with_prefixes produces non-deterministic namespace node ordering#46frankarensmeier wants to merge 1 commit into
Conversation
inherited_prefixes() returns an AHashMap whose iteration order varies across process runs due to random seeding. This caused clone_with_prefixes() to insert namespace nodes in non-deterministic order, which in turn made prefix_for_namespace() — which walks namespace nodes in tree order and returns the first match — return different prefixes for the same namespace across runs. Observable effects: - Serialized output had varying xmlns attribute order - XPath name() returned different QNames for the same element - XSLT conformance tests failed intermittently Fix: sort the inherited prefixes by PrefixId before inserting.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
clone_with_prefixesiterates over thePrefixesmap returned byinherited_prefixes()when inserting inherited namespace nodes onto the cloned element. SincePrefixesisAHashMap<PrefixId, NamespaceId>, the iteration order varies across process runs due to random hash seeding.This causes namespace nodes to be inserted in different tree order on each run, which has observable consequences:
prefix_for_namespace()returns different results — it walks namespace nodes in tree order and returns the first match, so different namespace node ordering means different prefix selection for the same namespace.name()becomes non-deterministic — since the chosen prefix varies, the qualified name of an element can change between runs.xmlnsdeclarations appear in different order, and elements may use different prefixes.Reproducer:
Parse an XML document with multiple namespace declarations on a parent element, then
clone_with_prefixesa child element. Run the program multiple times — the namespace declarations on the cloned element appear in a different order each time.Run this several times — the
xmlns:attributes will appear in varying order.Fix:
Sort the inherited prefixes by
PrefixIdbefore inserting, so the namespace node order is deterministic regardless of hash seed: