Skip to content

fix: validator accepts multiple root nodes when a root is self closing - #879

Open
yu2971512385-ui wants to merge 1 commit into
NaturalIntelligence:masterfrom
yu2971512385-ui:fix/validator-self-closing-root
Open

yu2971512385-ui wants to merge 1 commit into
NaturalIntelligence:masterfrom
yu2971512385-ui:fix/validator-self-closing-root

Conversation

@yu2971512385-ui

Copy link
Copy Markdown

Description

XMLValidator already rejects documents with more than one root node, but the check is skipped whenever one of the roots is self closing:

const { XMLValidator } = require('fast-xml-parser');

XMLValidator.validate('<xml></xml><xml2></xml2>'); // error: Multiple possible root nodes found.  ✅
XMLValidator.validate('<xml/><xml2/>');            // true  ❌
XMLValidator.validate('<xml></xml><xml2/>');       // true  ❌
XMLValidator.validate('<test><nested/></test><xml2/>'); // true  ❌
XMLValidator.validate('<xml/>extra');              // true  ❌  ('<xml></xml>extra' is rejected)

All of these are not well-formed XML — a document has exactly one root element — and the validator's own error messages (Multiple possible root nodes found., Extra text at the end) exist for precisely these cases.

Root cause

In src/validator.js:

  • reachedRoot = true is only assigned in the closing-tag branch, when popping a tag empties the stack. A self closing tag never reaches that branch, so it never ends the root level — hence '<xml/>extra' and '<xml/><xml2/>' pass.
  • The Multiple possible root nodes found. check lives only in the branch for a paired opening tag, so a self closing tag after a completed root is never checked — hence '<xml></xml><xml2/>' passes.

Fix

In the self closing branch, once the attributes validate, treat a tag with an empty stack as a root node: report the multiple-root error if a root was already seen, otherwise mark the root level as reached. Nested self closing tags (<test><nested/></test>) are unaffected because the stack is not empty there.

Tests

Added to spec/validator_spec.js:

  • multiple roots with the first root self closing, the second root self closing, and a self closing root after a root with nested tags
  • a single self closing root (with and without attributes) and nested self closing tags stay valid
  • text after a self closing root is rejected, trailing whitespace is still allowed

4 of the new specs fail without the source change. The full suite passes with it (npx jasmine spec/*spec.js → 338 specs, 0 failures, 2 pending).

reachedRoot was only set when a closing tag emptied the tag stack, and
the 'Multiple possible root nodes found.' check only ran on the branch
for paired opening tags. A self closing tag at the top level therefore
neither ended the root level nor was rejected after one, so documents
with two roots validated as long as either root was self closing:

    XMLValidator.validate('<xml/><xml2/>')        // true
    XMLValidator.validate('<xml></xml><xml2/>')   // true
    XMLValidator.validate('<xml/>extra')          // true

while the paired forms of the same documents are already rejected.

Treat a self closing tag with an empty tag stack as a root node: report
the multiple-root error if one was already seen, otherwise mark the root
level as reached.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant