Author: fanningpj
Date: Sun Jun 21 00:13:45 2026
New Revision: 1935533

Log:
validate NCName parts of xsd:QName in lexQName. Thanks to aizu-m. This closes 
#62

Modified:
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/util/XsTypeConverter.java
   xmlbeans/trunk/src/test/java/misc/checkin/RichParserTests.java

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/util/XsTypeConverter.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/util/XsTypeConverter.java 
    Sun Jun 21 00:10:15 2026        (r1935532)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/util/XsTypeConverter.java 
    Sun Jun 21 00:13:45 2026        (r1935533)
@@ -17,6 +17,7 @@ package org.apache.xmlbeans.impl.util;
 
 import org.apache.xmlbeans.*;
 import org.apache.xmlbeans.impl.common.InvalidLexicalValueException;
+import org.apache.xmlbeans.impl.common.XMLChar;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
@@ -505,6 +506,13 @@ public final class XsTypeConverter {
             localname = charSeq.toString();
         }
 
+        if (!prefix.isEmpty() && !XMLChar.isValidNCName(prefix)) {
+            throw new InvalidLexicalValueException("invalid xsd:QName '" + 
charSeq + "'");
+        }
+        if (!XMLChar.isValidNCName(localname)) {
+            throw new InvalidLexicalValueException("invalid xsd:QName '" + 
charSeq + "'");
+        }
+
         String uri = nscontext.getNamespaceURI(prefix);
 
         if (uri == null) {

Modified: xmlbeans/trunk/src/test/java/misc/checkin/RichParserTests.java
==============================================================================
--- xmlbeans/trunk/src/test/java/misc/checkin/RichParserTests.java      Sun Jun 
21 00:10:15 2026        (r1935532)
+++ xmlbeans/trunk/src/test/java/misc/checkin/RichParserTests.java      Sun Jun 
21 00:13:45 2026        (r1935533)
@@ -83,6 +83,30 @@ public class RichParserTests {
         assertThrows(InvalidLexicalValueException.class, () -> 
attByName.getAttributeBase64Value("", "b"));
     }
 
+    @Test
+    void testInvalidQNameThrowsInvalidLexicalValue() throws Exception {
+        // The localname of an xsd:QName must be an NCName, so a value whose
+        // local part still contains a ':' (or any other non-NCName char) is
+        // outside the lexical space. lexQName resolved the prefix but never
+        // checked the parts, so "p:b:c" came back as QName{uri}b:c instead of
+        // being rejected like the holder validate path does.
+        XMLStreamReaderExt colonInLocal = atFirstStartElement("<a 
xmlns:p='urn:x'>p:b:c</a>");
+        assertThrows(InvalidLexicalValueException.class, 
colonInLocal::getQNameValue);
+
+        XMLStreamReaderExt spaceInLocal = atFirstStartElement("<a>b c</a>");
+        assertThrows(InvalidLexicalValueException.class, 
spaceInLocal::getQNameValue);
+
+        XMLStreamReaderExt emptyLocal = atFirstStartElement("<a 
xmlns:p='urn:x'>p:</a>");
+        assertThrows(InvalidLexicalValueException.class, 
emptyLocal::getQNameValue);
+
+        XMLStreamReaderExt attColon = atFirstStartElement("<a xmlns:p='urn:x' 
b='p:b:c'/>");
+        assertThrows(InvalidLexicalValueException.class, () -> 
attColon.getAttributeQNameValue(0));
+
+        // a well-formed prefixed QName still resolves
+        XMLStreamReaderExt good = atFirstStartElement("<a 
xmlns:p='urn:x'>p:good</a>");
+        assertEquals(new QName("urn:x", "good"), good.getQNameValue());
+    }
+
     private static XMLStreamReaderExt atFirstStartElement(String xml) throws 
Exception {
         XMLStreamReader xsr = 
XmlObject.Factory.parse(xml).newXMLStreamReader();
         XMLStreamReaderExt ext = new XMLStreamReaderExtImpl(xsr);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to