From 9bc9a3dd26362bfd43deb2d76ee5f2ce4477d70f Mon Sep 17 00:00:00 2001 From: junhyeong9812 Date: Sat, 13 Jun 2026 19:33:37 +0900 Subject: [PATCH] Fix getTextCharacters to honor sourceStart offset AbstractXMLStreamReader.getTextCharacters(int sourceStart, char[], int, int) capped the copy length with Math.min(length, source.length), ignoring sourceStart. When sourceStart > 0 and sourceStart + length exceeds the text length, System.arraycopy read past the end of the source array and threw ArrayIndexOutOfBoundsException, contrary to the XMLStreamReader#getTextCharacters contract (copy up to length characters starting at sourceStart and return the number copied). Cap the length by the number of characters remaining from sourceStart. Signed-off-by: junhyeong9812 --- .../util/xml/AbstractXMLStreamReader.java | 2 +- .../util/xml/XMLEventStreamReaderTests.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLStreamReader.java b/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLStreamReader.java index 1c92c458fcd0..1bba07dc5f36 100644 --- a/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLStreamReader.java +++ b/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLStreamReader.java @@ -190,7 +190,7 @@ public char[] getTextCharacters() { @Override public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) { char[] source = getTextCharacters(); - length = Math.min(length, source.length); + length = Math.min(length, source.length - sourceStart); System.arraycopy(source, sourceStart, target, targetStart, length); return length; } diff --git a/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java index 40ef3b6410d0..876b660b92cc 100644 --- a/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java +++ b/spring-core/src/test/java/org/springframework/util/xml/XMLEventStreamReaderTests.java @@ -21,6 +21,7 @@ import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stax.StAXSource; @@ -68,4 +69,20 @@ void readCorrect() throws Exception { assertThat(XmlContent.from(writer)).isSimilarTo(XML, nodeFilter); } + @Test // getTextCharacters(sourceStart, ...) must not read past the source + void getTextCharactersHonorsSourceStart() throws Exception { + advanceToCharacters(); + // text node is "content" (7 chars); copy from index 4 with an oversized buffer + char[] target = new char[10]; + int count = streamReader.getTextCharacters(4, target, 0, 10); + assertThat(count).isEqualTo(3); + assertThat(new String(target, 0, count)).isEqualTo("ent"); + } + + private void advanceToCharacters() throws Exception { + while (streamReader.getEventType() != XMLStreamConstants.CHARACTERS) { + streamReader.next(); + } + } + }