From 0220ca97da99ae086bcbe9692cd435fc3703db44 Mon Sep 17 00:00:00 2001 From: yawkat Date: Tue, 22 Nov 2022 18:00:55 +0100 Subject: [PATCH 1/2] Fix TOML parse failure when number token hits buffer edge When a number token is exactly at the end of the lexer text buffer, the parser would advance the lexer, triggering a buffer refill, before the number is parsed from the buffer. This patch moves the advance operation to come after parsing, which resolves the issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kudos to @wbprime for finding this and reporting it as https://github.com/micronaut-projects/micronaut-toml/issues/93 . Not even the fuzzer managed to hit this – maybe because it does not fail fast, and just returns the wrong output (NumberInput does no input checking)? --- .../jackson/dataformat/toml/Parser.java | 6 ++++++ .../jackson/dataformat/toml/ParserTest.java | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/toml/src/main/java/com/fasterxml/jackson/dataformat/toml/Parser.java b/toml/src/main/java/com/fasterxml/jackson/dataformat/toml/Parser.java index efe9b58c..28ce75eb 100644 --- a/toml/src/main/java/com/fasterxml/jackson/dataformat/toml/Parser.java +++ b/toml/src/main/java/com/fasterxml/jackson/dataformat/toml/Parser.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.ValueNode; import java.io.IOException; import java.io.Reader; @@ -242,7 +243,12 @@ private JsonNode parseInt(int nextState) throws IOException { } } + ValueNode node = parseIntFromBuffer(buffer, start, length); pollExpected(TomlToken.INTEGER, nextState); + return node; + } + + private ValueNode parseIntFromBuffer(char[] buffer, int start, int length) throws TomlStreamReadException { if (length > 2) { char baseChar = buffer[start + 1]; diff --git a/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ParserTest.java b/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ParserTest.java index 7a2e450a..8499845b 100644 --- a/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ParserTest.java +++ b/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ParserTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.io.ContentReference; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.json.JsonReadFeature; +import com.fasterxml.jackson.core.util.BufferRecycler; import com.fasterxml.jackson.core.util.BufferRecyclers; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -23,6 +24,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; +import java.util.Arrays; @SuppressWarnings("OctalInteger") public class ParserTest { @@ -1027,4 +1029,23 @@ public void unknownEscape() throws IOException { expectedException.expectMessage("Unknown escape sequence"); toml("foo = \"\\k\""); } + + @Test + public void chunkEdge() throws IOException { + BufferRecycler br = BufferRecyclers.getBufferRecycler(); + char[] chars = br.allocCharBuffer(0); + br.releaseCharBuffer(0, chars); + int bufferLength = chars.length; + + ObjectNode node = toml("foo = \"" + repeat('a', bufferLength - 19) + "\"\n" + + "bar = 123\n" + + "baz = \"" + repeat('a', bufferLength) + "\""); + Assert.assertEquals(123, node.get("bar").intValue()); + } + + private static String repeat(char c, int n) { + char[] chars = new char[n]; + Arrays.fill(chars, c); + return new String(chars); + } } From d3965dd6cf9e51810cb54a9e44bf7b1eaef15e48 Mon Sep 17 00:00:00 2001 From: yawkat Date: Tue, 22 Nov 2022 18:15:15 +0100 Subject: [PATCH 2/2] change fuzz test errors --- .../fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java b/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java index 37c9f6fc..a8bd1397 100644 --- a/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java +++ b/toml/src/test/java/com/fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java @@ -29,7 +29,7 @@ public void testBigIntegerDecoding50033() throws Exception JsonNode n = TOML_MAPPER.readTree(INPUT); Assert.fail("Should not pass, got: "+n); } catch (StreamReadException e) { - verifyException(e, "Invalid number"); + verifyException(e, "Premature end of file"); // NOTE: decoding of token for error message seems wrong, cannot // quite verify it for the last line } @@ -73,8 +73,7 @@ public void testNumberParsingFail50395() throws Exception TOML_MAPPER.readTree(INPUT); Assert.fail("Should not pass"); } catch (StreamReadException e) { - verifyException(e, "Invalid number representation"); - verifyException(e, "Illegal leading minus sign"); + verifyException(e, "Premature end of file"); } }