From bd835f64e6a5f5e5f7a41adc4fea4a70b85ec8d4 Mon Sep 17 00:00:00 2001 From: aizu-m Date: Wed, 17 Jun 2026 13:33:02 +0530 Subject: [PATCH 1/2] fix pi terminator breakout after bad char in entitizeProcinst --- .../org/apache/xmlbeans/impl/store/Saver.java | 3 +- .../java/misc/checkin/ProcInstEscapeTest.java | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/test/java/misc/checkin/ProcInstEscapeTest.java diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java index 5a7fe94c6..f47631c99 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java @@ -1452,7 +1452,8 @@ private void entitizeProcinst() { char ch = _cbuf[i]; if (isBadChar(ch)) { - i = replace(i, "?"); + replace(i, "?"); + ch = '?'; } if (ch == '>') { diff --git a/src/test/java/misc/checkin/ProcInstEscapeTest.java b/src/test/java/misc/checkin/ProcInstEscapeTest.java new file mode 100644 index 000000000..66358c199 --- /dev/null +++ b/src/test/java/misc/checkin/ProcInstEscapeTest.java @@ -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("x"); + 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("x", 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("x", o.xmlText()); + } +} From a6feddf5ae3f5d54dbd13fd32edda15f6de04cb6 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 17 Jun 2026 17:43:25 +0100 Subject: [PATCH 2/2] spellings --- .../java/org/apache/xmlbeans/impl/store/Saver.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java index f47631c99..4dd999437 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java @@ -547,7 +547,7 @@ private void pushMappings(SaveCur c, boolean ensureDefaultEmpty) { } 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 @@ private void addNewFrameMapping(String prefix, String uri, boolean ensureDefault } // 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 @@ private void entitizeComment() { 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 { @@ -1457,7 +1457,7 @@ private void entitizeProcinst() { } 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 { @@ -2142,7 +2142,7 @@ private void entitizeAndWriteCommentText(int bufLimit) { _buf[i] = '?'; } else if (ch == '-') { if (lastWasDash) { - // Replace "--" with "- " to make well formed + // Replace "--" with "- " to make well-formed _buf[i] = ' '; lastWasDash = false; } else { @@ -2176,7 +2176,7 @@ private void entitizeAndWritePIText(int bufLimit) { } 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] = ' '; }