From 19fa4b8884250edf01a3a7ed71684933b5adb6dd Mon Sep 17 00:00:00 2001 From: "Adam J. Shook" Date: Mon, 21 Oct 2024 08:50:44 -0400 Subject: [PATCH 1/2] Fix infinite loop due to integer overflow when reading large strings If the StreamReadConstraints are set to Integer.MAX_VALUE, reading a string results in an infinite loop due to the value of max overflowing to a negative value. while (ptr < max) is always false so break ascii_loop is never reached. This change uses Math.addExact to throw an ArthimeticException if an overflow were to occur and sets max to max integer, allowing the loop to break and large strings to be properly deserialized. --- .../jackson/core/json/UTF8StreamJsonParser.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java index 571e48b799..8c0e220e30 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java @@ -2544,7 +2544,14 @@ private final void _finishString2(char[] outBuf, int outPtr) outBuf = _textBuffer.finishCurrentSegment(); outPtr = 0; } - final int max = Math.min(_inputEnd, (ptr + (outBuf.length - outPtr))); + + int max; + try { + max = Math.min(_inputEnd, Math.addExact(ptr, outBuf.length - outPtr)); + } catch (ArithmeticException ex) { + max = Integer.MAX_VALUE; + } + while (ptr < max) { c = inputBuffer[ptr++] & 0xFF; if (codes[c] != 0) { From 0c96b0ae75ab9bdf0afe09810b9489e4d372b613 Mon Sep 17 00:00:00 2001 From: "Adam J. Shook" Date: Mon, 21 Oct 2024 09:45:09 -0400 Subject: [PATCH 2/2] Add TestLargeString.java --- .../jackson/core/json/TestLargeString.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/java/com/fasterxml/jackson/core/json/TestLargeString.java diff --git a/src/test/java/com/fasterxml/jackson/core/json/TestLargeString.java b/src/test/java/com/fasterxml/jackson/core/json/TestLargeString.java new file mode 100644 index 0000000000..0f65952866 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/core/json/TestLargeString.java @@ -0,0 +1,32 @@ +package com.fasterxml.jackson.core.json; + +import com.fasterxml.jackson.core.*; +import net.bytebuddy.utility.RandomString; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TestLargeString extends JUnit5TestBase { + + @Test + void testLargeStringDeserialization() throws Exception + { + String largeString = RandomString.make(Integer.MAX_VALUE - 1024); + JsonFactory f = JsonFactory.builder() + .streamReadConstraints(StreamReadConstraints.builder() + .maxStringLength(Integer.MAX_VALUE) + .build()) + .build(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + JsonGenerator g = f.createGenerator(bytes); + g.writeString(largeString); + g.close(); + + JsonParser parser = f.createParser(bytes.toByteArray()); + String parsedString = parser.nextTextValue(); + + assertEquals(largeString, parsedString); + } +}