This is an automated email from the ASF dual-hosted git repository. veithen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ws-axiom.git
commit c4af6b514f71789ad8fda85d6332e8af14848493 Author: Andreas Veithen <andreas.veit...@gmail.com> AuthorDate: Sun Dec 17 21:39:27 2023 +0000 Properly decode UTF-16 when validating names --- .../java/org/apache/axiom/util/xml/XMLChar.java | 4 +- .../src/main/java/org/apache/axiom/dom/NSUtil.java | 15 +++++--- .../apache/axiom/ts/dom/DOMTestSuiteBuilder.java | 7 ++++ ...tCreateElementNSWithSupplementaryCharacter.java | 43 ++++++++++++++++++++++ ...stCreateElementWithSupplementaryCharacter.java} | 36 ++++++++---------- .../TestSetPrefixWithSupplementaryCharacter.java} | 37 +++++++++---------- .../java/org/apache/axiom/ts/dom/XercesTest.java | 7 ++++ 7 files changed, 101 insertions(+), 48 deletions(-) diff --git a/components/xml-utils/src/main/java/org/apache/axiom/util/xml/XMLChar.java b/components/xml-utils/src/main/java/org/apache/axiom/util/xml/XMLChar.java index f91da58d6..077493aa5 100644 --- a/components/xml-utils/src/main/java/org/apache/axiom/util/xml/XMLChar.java +++ b/components/xml-utils/src/main/java/org/apache/axiom/util/xml/XMLChar.java @@ -43,7 +43,7 @@ public final class XMLChar { * @param c the character to examine * @return {@code true} if the character is name start char, {@code false} otherwise */ - public static boolean isNameStartChar(char c) { + public static boolean isNameStartChar(int c) { return c == ':' || 'A' <= c && c <= 'Z' || c == '_' @@ -70,7 +70,7 @@ public final class XMLChar { * @param c the character to examine * @return {@code true} if the character is name char, {@code false} otherwise */ - public static boolean isNameChar(char c) { + public static boolean isNameChar(int c) { return isNameStartChar(c) || c == '-' || c == '.' diff --git a/mixins/dom-mixins/src/main/java/org/apache/axiom/dom/NSUtil.java b/mixins/dom-mixins/src/main/java/org/apache/axiom/dom/NSUtil.java index 18a6e6a3b..439c5fef9 100644 --- a/mixins/dom-mixins/src/main/java/org/apache/axiom/dom/NSUtil.java +++ b/mixins/dom-mixins/src/main/java/org/apache/axiom/dom/NSUtil.java @@ -32,23 +32,25 @@ public final class NSUtil { if (name.length() == 0) { throw DOMExceptionUtil.newDOMException(DOMException.INVALID_CHARACTER_ERR); } - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); + for (int i = 0; i < name.length(); ) { + int c = name.codePointAt(i); if (i == 0 && !isNameStartChar(c) || i > 0 && !isNameChar(c)) { throw DOMExceptionUtil.newDOMException(DOMException.INVALID_CHARACTER_ERR); } + i += Character.charCount(c); } } public static void validatePrefix(String prefix) throws DOMException { - for (int i = 0; i < prefix.length(); i++) { - char c = prefix.charAt(i); + for (int i = 0; i < prefix.length(); ) { + int c = prefix.codePointAt(i); if (c == ':') { throw DOMExceptionUtil.newDOMException(DOMException.NAMESPACE_ERR); } if (i == 0 && !isNameStartChar(c) || i > 0 && !isNameChar(c)) { throw DOMExceptionUtil.newDOMException(DOMException.INVALID_CHARACTER_ERR); } + i += Character.charCount(c); } } @@ -58,8 +60,8 @@ public final class NSUtil { } int colonPosition = -1; boolean checkNameStart = true; - for (int i = 0; i < qualifiedName.length(); i++) { - char c = qualifiedName.charAt(i); + for (int i = 0; i < qualifiedName.length(); ) { + int c = qualifiedName.codePointAt(i); if (c == ':') { if (colonPosition == -1 && i > 0) { colonPosition = i; @@ -78,6 +80,7 @@ public final class NSUtil { } else if (!isNameChar(c)) { throw DOMExceptionUtil.newDOMException(DOMException.INVALID_CHARACTER_ERR); } + i += Character.charCount(c); } if (checkNameStart) { // If we get here, then the qualified name ends with a colon diff --git a/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/DOMTestSuiteBuilder.java b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/DOMTestSuiteBuilder.java index be9db5dc1..2d9a126bb 100644 --- a/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/DOMTestSuiteBuilder.java +++ b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/DOMTestSuiteBuilder.java @@ -94,6 +94,12 @@ public final class DOMTestSuiteBuilder extends MatrixTestSuiteBuilder { addTest(new org.apache.axiom.ts.dom.document.TestCreateElementNS(dbf)); addTest(new org.apache.axiom.ts.dom.document.TestCreateElementNSWithInvalidName(dbf)); addTest(new org.apache.axiom.ts.dom.document.TestCreateElementNSWithoutNamespace(dbf)); + addTest( + new org.apache.axiom.ts.dom.document.TestCreateElementNSWithSupplementaryCharacter( + dbf)); + addTest( + new org.apache.axiom.ts.dom.document.TestCreateElementWithSupplementaryCharacter( + dbf)); addTest(new org.apache.axiom.ts.dom.document.TestCreateEntityReference(dbf)); addTest(new org.apache.axiom.ts.dom.document.TestCreateText(dbf)); addTest(new org.apache.axiom.ts.dom.document.TestDocumentSiblings(dbf)); @@ -209,6 +215,7 @@ public final class DOMTestSuiteBuilder extends MatrixTestSuiteBuilder { addTest(new org.apache.axiom.ts.dom.element.TestSetPrefixNotNullWithNamespace(dbf)); addTest(new org.apache.axiom.ts.dom.element.TestSetPrefixNotNullWithoutNamespace(dbf)); addTest(new org.apache.axiom.ts.dom.element.TestSetPrefixNull(dbf)); + addTest(new org.apache.axiom.ts.dom.element.TestSetPrefixWithSupplementaryCharacter(dbf)); addTest(new org.apache.axiom.ts.dom.element.TestSetTextContent(dbf)); addTest( new org.apache.axiom.ts.dom.element.attributes.TestSetNamedItemNSWrongDocument( diff --git a/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementNSWithSupplementaryCharacter.java b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementNSWithSupplementaryCharacter.java new file mode 100644 index 000000000..67ebb5a22 --- /dev/null +++ b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementNSWithSupplementaryCharacter.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.axiom.ts.dom.document; + +import static org.assertj.core.api.Assertions.assertThat; + +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.axiom.ts.dom.DOMTestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class TestCreateElementNSWithSupplementaryCharacter extends DOMTestCase { + public TestCreateElementNSWithSupplementaryCharacter(DocumentBuilderFactory dbf) { + super(dbf); + } + + @Override + protected void runTest() throws Throwable { + String prefix = new String(new int[] {'a', 0x10001, 'b'}, 0, 3); + String localName = new String(new int[] {0x10002, 'c'}, 0, 2); + Document doc = dbf.newDocumentBuilder().newDocument(); + Element elem = doc.createElementNS("http://test.org", prefix + ":" + localName); + assertThat(elem.getPrefix()).isEqualTo(prefix); + assertThat(elem.getLocalName()).isEqualTo(localName); + } +} diff --git a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementWithSupplementaryCharacter.java similarity index 51% copy from testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java copy to testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementWithSupplementaryCharacter.java index 8daac8d4d..93be6380a 100644 --- a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java +++ b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/document/TestCreateElementWithSupplementaryCharacter.java @@ -16,30 +16,26 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.axiom.ts.dom; +package org.apache.axiom.ts.dom.document; -import javax.xml.parsers.DocumentBuilderFactory; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import static org.assertj.core.api.Assertions.assertThat; -import org.apache.axiom.ts.dom.element.TestLookupNamespaceURIXercesJ1586; -import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; +import javax.xml.parsers.DocumentBuilderFactory; -public class XercesTest extends TestCase { - public static TestSuite suite() { - DOMTestSuiteBuilder builder = - new DOMTestSuiteBuilder( - new DocumentBuilderFactoryFactory() { - @Override - public DocumentBuilderFactory newInstance() { - return new DocumentBuilderFactoryImpl(); - } - }); +import org.apache.axiom.ts.dom.DOMTestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; - // XERCESJ-1586 - builder.exclude(TestLookupNamespaceURIXercesJ1586.class); +public class TestCreateElementWithSupplementaryCharacter extends DOMTestCase { + public TestCreateElementWithSupplementaryCharacter(DocumentBuilderFactory dbf) { + super(dbf); + } - return builder.build(); + @Override + protected void runTest() throws Throwable { + String tagName = new String(new int[] {0x10000}, 0, 1); + Document doc = dbf.newDocumentBuilder().newDocument(); + Element elem = doc.createElement(tagName); + assertThat(elem.getTagName()).isEqualTo(tagName); } } diff --git a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/element/TestSetPrefixWithSupplementaryCharacter.java similarity index 51% copy from testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java copy to testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/element/TestSetPrefixWithSupplementaryCharacter.java index 8daac8d4d..fff02cbef 100644 --- a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java +++ b/testing/dom-testsuite/src/main/java/org/apache/axiom/ts/dom/element/TestSetPrefixWithSupplementaryCharacter.java @@ -16,30 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.axiom.ts.dom; +package org.apache.axiom.ts.dom.element; -import javax.xml.parsers.DocumentBuilderFactory; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import static org.assertj.core.api.Assertions.assertThat; -import org.apache.axiom.ts.dom.element.TestLookupNamespaceURIXercesJ1586; -import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; +import javax.xml.parsers.DocumentBuilderFactory; -public class XercesTest extends TestCase { - public static TestSuite suite() { - DOMTestSuiteBuilder builder = - new DOMTestSuiteBuilder( - new DocumentBuilderFactoryFactory() { - @Override - public DocumentBuilderFactory newInstance() { - return new DocumentBuilderFactoryImpl(); - } - }); +import org.apache.axiom.ts.dom.DOMTestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; - // XERCESJ-1586 - builder.exclude(TestLookupNamespaceURIXercesJ1586.class); +public class TestSetPrefixWithSupplementaryCharacter extends DOMTestCase { + public TestSetPrefixWithSupplementaryCharacter(DocumentBuilderFactory dbf) { + super(dbf); + } - return builder.build(); + @Override + protected void runTest() throws Throwable { + String prefix = new String(new int[] {0x10000}, 0, 1); + Document doc = dbf.newDocumentBuilder().newDocument(); + Element elem = doc.createElementNS("http://example.org", "foobar"); + elem.setPrefix(prefix); + assertThat(elem.getPrefix()).isEqualTo(prefix); } } diff --git a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java b/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java index 8daac8d4d..23d5bd246 100644 --- a/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java +++ b/testing/dom-testsuite/src/test/java/org/apache/axiom/ts/dom/XercesTest.java @@ -23,7 +23,10 @@ import javax.xml.parsers.DocumentBuilderFactory; import junit.framework.TestCase; import junit.framework.TestSuite; +import org.apache.axiom.ts.dom.document.TestCreateElementNSWithSupplementaryCharacter; +import org.apache.axiom.ts.dom.document.TestCreateElementWithSupplementaryCharacter; import org.apache.axiom.ts.dom.element.TestLookupNamespaceURIXercesJ1586; +import org.apache.axiom.ts.dom.element.TestSetPrefixWithSupplementaryCharacter; import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; public class XercesTest extends TestCase { @@ -37,6 +40,10 @@ public class XercesTest extends TestCase { } }); + builder.exclude(TestCreateElementWithSupplementaryCharacter.class); + builder.exclude(TestCreateElementNSWithSupplementaryCharacter.class); + builder.exclude(TestSetPrefixWithSupplementaryCharacter.class); + // XERCESJ-1586 builder.exclude(TestLookupNamespaceURIXercesJ1586.class);