Author: fanningpj
Date: Wed Jun 17 20:20:27 2026
New Revision: 1935461
Log:
fix pi terminator breakout after bad char in entitizeProcinst. Thanks to
aizu-m. This closes #54
Added:
xmlbeans/trunk/src/test/java/misc/checkin/ProcInstEscapeTest.java
Modified:
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
Modified: xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
Wed Jun 17 20:11:31 2026 (r1935460)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
Wed Jun 17 20:20:27 2026 (r1935461)
@@ -547,7 +547,7 @@ abstract class Saver {
}
private void addNewFrameMapping(String prefix, String uri, boolean
ensureDefaultEmpty) {
- // If the prefix maps to "", then don't include this mapping 'cause
it's not well formed.
+ // If the prefix maps to "", then don't include this mapping 'cause
it's not well-formed.
// Also, if we want to make sure that the default namespace is always
"", then check that
// here as well.
@@ -562,7 +562,7 @@ abstract class Saver {
}
// Also make sure that the prefix declaration is not redundant
- // This has the side-effect of making it impossible to set a
+ // This has the side effect of making it impossible to set a
// redundant prefix declaration, but seems that it's better
// to just never issue a duplicate prefix declaration.
if (uri.equals(getNamespaceForPrefix(prefix))) {
@@ -1413,7 +1413,7 @@ abstract class Saver {
i = replace(i, "?");
} else if (ch == '-') {
if (lastWasDash) {
- // Replace "--" with "- " to make well formed
+ // Replace "--" with "- " to make well-formed
i = replace(i, " ");
lastWasDash = false;
} else {
@@ -1452,11 +1452,12 @@ abstract class Saver {
char ch = _cbuf[i];
if (isBadChar(ch)) {
- i = replace(i, "?");
+ replace(i, "?");
+ ch = '?';
}
if (ch == '>') {
- // TODO - Had to convert to a space here ... imples not
well formed XML
+ // TODO - Had to convert to a space here ... implies not
well-formed XML
if (lastWasQuestion) {
i = replace(i, " ");
} else {
@@ -2141,7 +2142,7 @@ abstract class Saver {
_buf[i] = '?';
} else if (ch == '-') {
if (lastWasDash) {
- // Replace "--" with "- " to make well formed
+ // Replace "--" with "- " to make well-formed
_buf[i] = ' ';
lastWasDash = false;
} else {
@@ -2175,7 +2176,7 @@ abstract class Saver {
}
if (ch == '>') {
- // Had to convert to a space here ... imples not well
formed XML
+ // Had to convert to a space here ... implies not
well-formed XML
if (lastWasQuestion) {
_buf[i] = ' ';
}
Added: xmlbeans/trunk/src/test/java/misc/checkin/ProcInstEscapeTest.java
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ xmlbeans/trunk/src/test/java/misc/checkin/ProcInstEscapeTest.java Wed Jun
17 20:20:27 2026 (r1935461)
@@ -0,0 +1,67 @@
+/* Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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 misc.checkin;
+
+import org.apache.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.junit.jupiter.api.Test;
+
+import java.io.StringWriter;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class ProcInstEscapeTest {
+
+ private static XmlObject docWithProcInst(String piText) throws Exception {
+ XmlObject o = XmlObject.Factory.parse("<root>x</root>");
+ try (XmlCursor c = o.newCursor()) {
+ c.toNextToken();
+ c.toNextToken();
+ c.insertProcInst("tgt", piText);
+ }
+ return o;
+ }
+
+ private static String saveForSpeed(XmlObject o) throws Exception {
+ XmlOptions opts = new XmlOptions();
+ opts.setSaveOptimizeForSpeed(true);
+ StringWriter sw = new StringWriter();
+ o.save(sw, opts);
+ return sw.toString();
+ }
+
+ // a bad char immediately before "?>" used to make the default saver skip
the
+ // "?>" so it survived inside the processing instruction
+ @Test
+ void testBadCharBeforePiEnd() throws Exception {
+ XmlObject o = docWithProcInst("\u0007?>");
+ String out = o.xmlText();
+ assertEquals("<root><?tgt ?? ?>x</root>", out);
+ // the only "?>" in the output is the PI terminator
+ assertFalse(out.substring(0, out.indexOf("?>x")).contains("?>"));
+ // round-trips and both savers agree
+ XmlObject.Factory.parse(out);
+ assertEquals(out, saveForSpeed(o));
+ }
+
+ @Test
+ void testPlainQuestionGtStillEscaped() throws Exception {
+ XmlObject o = docWithProcInst("a?>b");
+ assertEquals("<root><?tgt a? b?>x</root>", o.xmlText());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]