Skip to content

Accept non-ASCII names in DOCTYPE, processing instructions and DTD declarations - #378

Open
wleeaf wants to merge 1 commit into
ruby:masterfrom
wleeaf:accept-non-ascii-names
Open

wleeaf wants to merge 1 commit into
ruby:masterfrom
wleeaf:accept-non-ascii-names

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 24, 2026

Copy link
Copy Markdown

BaseParser::NAME is built from \w, which is ASCII-only in Ruby regular expressions. So every name parsed with it rejects non-ASCII letters, while element and attribute names (QNAME, built from [:alpha:]) accept them:

Input master This PR Expat (Python xml.etree)
<!DOCTYPE été><r/> Malformed DOCTYPE: invalid name parses parses
<?été content?><r/> Invalid processing instruction node: invalid name parses parses
<!DOCTYPE r [<!ENTITY été "summer">]><r>&été;</r> Malformed entity declaration "summer" "summer"
<!NOTATION été PUBLIC 'urn:x'> in the internal subset Malformed notation declaration: invalid name parses parses
<!ATTLIST a été CDATA #IMPLIED> in the internal subset Bad ATTLIST declaration! parses parses

This change defines NAMECHAR and NAME with XMLTokens::NAME_CHAR and XMLTokens::NAME, the [4]/[4a]/[5] productions that REXML::Entity and REXML::Text already use. The capture group is the same, so the patterns that interpolate NAME keep their group numbers. One side effect: names that start with a digit, which [5] Name doesn't allow, are now rejected in these places too, as element names already are.

I found this with the W3C XML Conformance Test Suite (xmlts20130923). The three japanese/ valid documents (UTF-8 and UTF-16 with Japanese names in the DTD) now parse, and two not-wf tests (oasis p58fail3, IBM P66 ibm66n03) are now rejected.

Tests: test_non_ascii for DOCTYPE names and general entity names, test_non_ascii_name for notations, and test_non_ascii_target for processing instructions. All four fail before the change and pass after it. bundle exec rake test passes (845 tests), as does the --enable-frozen-string-literal run. ruby -w shows no new warnings.

Performance: a 5000-element document doesn't use these patterns for tags, so its parse time is unchanged. For a document with 500 entity, ATTLIST and NOTATION declarations, 2000 PIs and entity references, the difference was within run-to-run noise. A name scan in isolation is about 20% slower (about 0.25 µs per scan).

…clarations

BaseParser::NAME used \w, which is ASCII-only in Ruby, so <!DOCTYPE été>, <?été ...?>, <!ENTITY été ...>, &été;, <!NOTATION été ...> and non-ASCII ATTLIST names raised ParseException, although element and attribute names already accept non-ASCII letters. Use the XML Name production from XMLTokens (NameStartChar and NameChar), which REXML::Entity and REXML::Text already use. Names starting with a digit, which [5] Name does not allow, are now rejected in these places too.
Copilot AI balanced review requested due to automatic review settings October 24, 2026 23:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

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.

2 participants