diff --git a/src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java b/src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java index d8430c5..2b223d3 100644 --- a/src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java +++ b/src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java @@ -2450,6 +2450,7 @@ private void parseComment() throws XmlPullParserException, IOException { if (pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = cch; if (cch2 != 0) { + if (pcEnd >= pc.length) ensurePC(pcEnd); pc[pcEnd++] = cch2; } } diff --git a/src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java b/src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java index 2698790..6cead6d 100644 --- a/src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java +++ b/src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java @@ -51,6 +51,29 @@ class MXParserTest { * * @throws java.lang.Exception if any. */ + @Test + void commentSurrogatePairAtBufferBoundary() throws Exception { + MXParser parser = new MXParser(); + java.lang.reflect.Field pcField = MXParser.class.getDeclaredField("pc"); + pcField.setAccessible(true); + int pcLength = ((char[]) pcField.get(parser)).length; + + // The leading CR switches the parser to its parsed-content buffer, which then holds the + // normalised LF plus pcLength - 2 characters; the surrogate pair needs the last two slots. + StringBuilder comment = new StringBuilder("\r"); + for (int i = 0; i < pcLength - 2; i++) { + comment.append('a'); + } + comment.append("\uD83D\uDE00"); + + parser.setInput(new StringReader("")); + + assertEquals(XmlPullParser.START_TAG, parser.nextToken()); + assertEquals(XmlPullParser.COMMENT, parser.nextToken()); + assertEquals("\n" + comment.substring(1), parser.getText()); + assertEquals(XmlPullParser.END_TAG, parser.nextToken()); + } + @Test void hexadecimalEntities() throws Exception { MXParser parser = new MXParser();