From 5bc11f85918150da5c19e086858952287fe9a1e3 Mon Sep 17 00:00:00 2001 From: Aizal Khan Date: Wed, 8 Jul 2026 18:42:26 +0530 Subject: [PATCH] escape comment trailing dash only on the final chunk --- .../java/org/apache/xmlbeans/impl/store/Saver.java | 13 ++++++++----- .../java/misc/checkin/SaveOptimizeForSpeedTest.java | 13 +++++++++++++ 2 files changed, 21 insertions(+), 5 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 b5b8ac5af..58edaadef 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java @@ -2106,10 +2106,11 @@ protected void emitCommentText(SaveCur c) { int cch = c._cchSrc; int off = c._offSrc; int index = 0; + boolean lastWasDash = false; while (index < cch) { int indexLimit = Math.min(index + 512, cch); CharUtil.getChars(_buf, 0, src, off + index, indexLimit - index); - entitizeAndWriteCommentText(indexLimit - index); + lastWasDash = entitizeAndWriteCommentText(indexLimit - index, lastWasDash, indexLimit == cch); index = indexLimit; } } @@ -2156,9 +2157,7 @@ private int entitizeAndWriteText(int bufLimit, int trailingBrackets) { return trailingBrackets; } - private void entitizeAndWriteCommentText(int bufLimit) { - boolean lastWasDash = false; - + private boolean entitizeAndWriteCommentText(int bufLimit, boolean lastWasDash, boolean lastChunk) { for (int i = 0; i < bufLimit; i++) { char ch = _buf[i]; @@ -2181,11 +2180,15 @@ private void entitizeAndWriteCommentText(int bufLimit) { } } - if (_buf[bufLimit - 1] == '-') { + // A trailing '-' would form "--->" with the closing delimiter, so it + // is escaped only at the real end of the comment, not on every chunk. + if (lastChunk && _buf[bufLimit - 1] == '-') { _buf[bufLimit - 1] = ' '; + lastWasDash = false; } emit(_buf, 0, bufLimit); + return lastWasDash; } private boolean entitizeAndWritePIText(int bufLimit, boolean lastWasQuestion) { diff --git a/src/test/java/misc/checkin/SaveOptimizeForSpeedTest.java b/src/test/java/misc/checkin/SaveOptimizeForSpeedTest.java index 7d18d04bc..89b77325d 100644 --- a/src/test/java/misc/checkin/SaveOptimizeForSpeedTest.java +++ b/src/test/java/misc/checkin/SaveOptimizeForSpeedTest.java @@ -115,6 +115,19 @@ void testBadCharInText() throws Exception { XmlObject.Factory.parse(out); } + @Test + void testCommentDashAtChunkBoundary() throws Exception { + // a lone '-' sitting on the 512-char chunk boundary. It is legal in + // comment content, but the speed path applied its trailing-dash fixup + // at the end of every chunk, so the boundary '-' was silently rewritten + // to a space and the saved comment no longer matched the source. + String data = repeat('a', 511) + "-" + repeat('b', 600); + XmlObject o = XmlObject.Factory.parse(""); + String out = saveForSpeed(o); + XmlObject.Factory.parse(out); + assertTrue(out.contains(repeat('a', 511) + "-")); + } + @Test void testProcInstTerminatorAcrossChunkBoundary() throws Exception { // a '?>' that straddles the 512-char chunk boundary: '?' is the last char