DOS in jackson-dataformats-text
Description
Jackson-dataformats-text TOML parser is vulnerable to denial of service via stack overflow due to uncontrolled recursion in deeply nested tables.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Jackson-dataformats-text TOML parser is vulnerable to denial of service via stack overflow due to uncontrolled recursion in deeply nested tables.
Vulnerability
CVE-2023-3894 describes a denial-of-service (DoS) vulnerability in the TOML parser of jackson-dataformats-text. The root cause is the absence of nesting depth validation, allowing deeply nested tables or arrays to cause a stack overflow and crash the JVM [1]. The issue was introduced in versions prior to the fix.
Exploitation
An attacker can exploit this by supplying a specially crafted TOML document with extremely deep nesting of tables (e.g., multiple [a.b.c...] or [[array]] structures) to any application that parses untrusted TOML input using the vulnerable parser. No authentication or special privileges are required beyond network access to the parser [1].
Impact
Successful exploitation leads to a denial-of-service condition: the parser crashes with a stack overflow, disrupting service availability [1].
Mitigation
The vulnerability is fixed in jackson-dataformats-text versions 2.16.0 and later. The fix adds nesting depth tracking via StreamReadConstraints.validateNestingDepth(), which limits recursion depth [2]. Users should upgrade to a patched version or apply input validation to limit nesting depth [4].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.fasterxml.jackson.dataformat:jackson-dataformat-tomlMaven | < 2.15.0 | 2.15.0 |
Affected products
2- Range: 0
Patches
15dd5f740aedcTOML: check nesting depth (#398)
16 files changed · +148 −69
properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsFactory.java+3 −1 modified@@ -28,7 +28,9 @@ public class JavaPropsFactory extends JsonFactory /********************************************************** */ - public JavaPropsFactory() { } + public JavaPropsFactory() { + super(); + } public JavaPropsFactory(ObjectCodec codec) { super(codec);
toml/src/main/java/com/fasterxml/jackson/dataformat/toml/Parser.java+11 −3 modified@@ -56,7 +56,9 @@ public static ObjectNode parse( Parser parser = new Parser(new TomlFactory(), ioContext, new TomlStreamReadException.ErrorContext(ioContext.contentReference(), null), options, reader); try { - return parser.parse(); + final ObjectNode node = parser.parse(); + assert parser.getNestingDepth() == 0; + return node; } finally { parser.lexer.releaseBuffers(); } @@ -80,12 +82,18 @@ public static ObjectNode parse( new TomlStreamReadException.ErrorContext(ioContext.contentReference(), null), factory.getFormatParserFeatures(), reader); try { - return parser.parse(); + final ObjectNode node = parser.parse(); + assert parser.getNestingDepth() == 0; + return node; } finally { parser.lexer.releaseBuffers(); } } + int getNestingDepth() { + return lexer.getNestingDepth(); + } + private TomlToken peek() throws TomlStreamReadException { TomlToken here = this.next; if (here == null) throw errorContext.atPosition(lexer).generic("Premature end of file"); @@ -376,7 +384,7 @@ private ValueNode parseIntFromBuffer(char[] buffer, int start, int length) throw } private JsonNode parseFloat(int nextState) throws IOException { - String text = lexer.yytext().replace("_", ""); + final String text = lexer.yytext().replace("_", ""); pollExpected(TomlToken.FLOAT, nextState); if (text.endsWith("nan")) { return factory.numberNode(Double.NaN);
toml/src/main/java/com/fasterxml/jackson/dataformat/toml/TomlFactory.java+1 −0 modified@@ -56,6 +56,7 @@ public final class TomlFactory extends JsonFactory */ public TomlFactory() { + super(); _tomlParserFeatures = DEFAULT_TOML_PARSER_FEATURE_FLAGS; _tomlGeneratorFeatures = DEFAULT_TOML_GENERATOR_FEATURE_FLAGS; }
toml/src/main/jflex/com/fasterxml/jackson/dataformat/toml/toml.jflex+47 −10 modified@@ -15,6 +15,7 @@ package com.fasterxml.jackson.dataformat.toml; %init{ this.ioContext = ioContext; +this.streamReadConstraints = ioContext.streamReadConstraints(); this.errorContext = errorContext; yybegin(EXPECT_EXPRESSION); this.zzBuffer = ioContext.allocTokenBuffer(); @@ -30,6 +31,8 @@ this.textBuffer = ioContext.constructReadConstrainedTextBuffer(); private boolean trimmedNewline; final com.fasterxml.jackson.core.util.TextBuffer textBuffer; + private final com.fasterxml.jackson.core.StreamReadConstraints streamReadConstraints; + private int nestingDepth; private void requestLargerBuffer() throws TomlStreamReadException { if (prohibitInternalBufferAllocate) { @@ -54,6 +57,10 @@ this.textBuffer = ioContext.constructReadConstrainedTextBuffer(); textBuffer.releaseBuffers(); } + public int getNestingDepth() { + return nestingDepth; + } + private void startString() { // resetWithEmpty does not set _currentSegment, so we need this variant to be able to append further data textBuffer.emptyAndGetCurrentSegment(); @@ -257,8 +264,14 @@ HexDig = [0-9A-Fa-f] yybegin(LITERAL_STRING); startString(); } - {StdTableOpen} {return TomlToken.STD_TABLE_OPEN;} - {ArrayTableOpen} {return TomlToken.ARRAY_TABLE_OPEN;} + {StdTableOpen} { + streamReadConstraints.validateNestingDepth(++nestingDepth); + return TomlToken.STD_TABLE_OPEN; + } + {ArrayTableOpen} { + streamReadConstraints.validateNestingDepth(++nestingDepth); + return TomlToken.ARRAY_TABLE_OPEN; + } {KeyValSep} {return TomlToken.KEY_VAL_SEP;} {NewLine} {} {Comment} {} @@ -284,9 +297,18 @@ HexDig = [0-9A-Fa-f] startString(); } {KeyValSep} {return TomlToken.KEY_VAL_SEP;} - {InlineTableClose} {return TomlToken.INLINE_TABLE_CLOSE;} - {StdTableClose} {return TomlToken.STD_TABLE_CLOSE;} - {ArrayTableClose} {return TomlToken.ARRAY_TABLE_CLOSE;} + {InlineTableClose} { + nestingDepth--; + return TomlToken.INLINE_TABLE_CLOSE; + } + {StdTableClose} { + nestingDepth--; + return TomlToken.STD_TABLE_CLOSE; + } + {ArrayTableClose} { + nestingDepth--; + return TomlToken.ARRAY_TABLE_CLOSE; + } } <EXPECT_EOL> { @@ -340,18 +362,30 @@ HexDig = [0-9A-Fa-f] } // inline array / table - {ArrayOpen} {WsCommentNewlineNonEmpty}* {return TomlToken.ARRAY_OPEN;} - {InlineTableOpen} {return TomlToken.INLINE_TABLE_OPEN;} + {ArrayOpen} {WsCommentNewlineNonEmpty}* { + streamReadConstraints.validateNestingDepth(++nestingDepth); + return TomlToken.ARRAY_OPEN; + } + {InlineTableOpen} { + streamReadConstraints.validateNestingDepth(++nestingDepth); + return TomlToken.INLINE_TABLE_OPEN; + } // array end just after comma - {WsCommentNewlineNonEmpty}* {ArrayClose} {return TomlToken.ARRAY_CLOSE;} + {WsCommentNewlineNonEmpty}* {ArrayClose} { + nestingDepth--; + return TomlToken.ARRAY_CLOSE; + } } <EXPECT_ARRAY_SEP> { // array-values = ws-comment-newline val ws-comment-newline array-sep array-values // array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ] {Comma} {WsCommentNewlineNonEmpty}* {return TomlToken.COMMA;} - {ArrayClose} {return TomlToken.ARRAY_CLOSE;} + {ArrayClose} { + nestingDepth--; + return TomlToken.ARRAY_CLOSE; + } {WsCommentNewlineNonEmpty} {} // always allowed here } @@ -360,7 +394,10 @@ HexDig = [0-9A-Fa-f] // inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ] {Ws} {Comma} {Ws} {return TomlToken.COMMA;} - {InlineTableClose} {return TomlToken.INLINE_TABLE_CLOSE;} + {InlineTableClose} { + nestingDepth--; + return TomlToken.INLINE_TABLE_CLOSE; + } } <BASIC_STRING> {
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/BigStringsTest.java+2 −2 modified@@ -9,7 +9,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class BigStringsTest +public class BigStringsTest extends TomlMapperTestBase { final static class StringWrapper @@ -25,7 +25,7 @@ void setString(String string) { } } - private final TomlMapper MAPPER = new TomlMapper(); + private final TomlMapper MAPPER = newTomlMapper(); private TomlMapper newMapperWithUnlimitedStringSizeSupport() { TomlFactory tomlFactory = TomlFactory.builder()
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ComplexPojoReadWriteTest.java+2 −2 modified@@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; // Copied from YAML modules "DatabindAdvancedTest" -public class ComplexPojoReadWriteTest +public class ComplexPojoReadWriteTest extends TomlMapperTestBase { enum Size { SMALL, LARGE; } @@ -145,7 +145,7 @@ public Image(String uri, String title, int w, int h, Size s) @Test public void testReadWriteComplexPojo() throws Exception { - ObjectMapper mapper = new TomlMapper(); + ObjectMapper mapper = newTomlMapper(); MediaItem input = new MediaItem(); MediaContent content = new MediaContent();
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ComplianceInvalidTest.java+2 −2 modified@@ -15,7 +15,7 @@ import java.util.stream.Collectors; @RunWith(Parameterized.class) -public class ComplianceInvalidTest { +public class ComplianceInvalidTest extends TomlMapperTestBase { @Parameterized.Parameters public static Collection<Object[]> data() throws IOException { Path folder = Paths.get("compliance", "invalid"); @@ -28,7 +28,7 @@ public static Collection<Object[]> data() throws IOException { .collect(Collectors.toList()); } - private final ObjectMapper MAPPER = new TomlMapper(); + private final ObjectMapper MAPPER = newTomlMapper(); private final Path path;
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ComplianceValidTest.java+1 −1 modified@@ -27,7 +27,7 @@ import java.util.stream.Collectors; @RunWith(Parameterized.class) -public class ComplianceValidTest { +public class ComplianceValidTest extends TomlMapperTestBase { @Parameterized.Parameters public static Collection<Object[]> data() throws IOException { Path folder = Paths.get("compliance", "valid");
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/FuzzTomlReadTest.java+18 −2 modified@@ -3,6 +3,7 @@ import java.io.IOException; import java.util.Arrays; +import com.fasterxml.jackson.core.exc.StreamConstraintsException; import org.junit.Assert; import org.junit.Test; @@ -13,9 +14,9 @@ /** * Collection of OSS-Fuzz found issues for TOML format module. */ -public class FuzzTomlReadTest +public class FuzzTomlReadTest extends TomlMapperTestBase { - private final ObjectMapper TOML_MAPPER = new TomlMapper(); + private final ObjectMapper TOML_MAPPER = newTomlMapper(); // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50036 @Test @@ -76,6 +77,21 @@ public void testNumberParsingFail50395() throws Exception verifyException(e, "Premature end of file"); } } + + @Test + public void testStackOverflow50083() throws Exception + { + StringBuilder input = new StringBuilder(); + for (int i = 0; i < 9999; i++) { + input.append("a={"); + } + try { + TOML_MAPPER.readTree(input.toString()); + Assert.fail("Should not pass"); + } catch (StreamConstraintsException e) { + verifyException(e, "Depth (1001) exceeds the maximum allowed nesting depth (1000)"); + } + } protected void verifyException(Throwable e, String... matches) {
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/LongTokenTest.java+3 −4 modified@@ -1,7 +1,6 @@ package com.fasterxml.jackson.dataformat.toml; import com.fasterxml.jackson.core.StreamReadConstraints; -import com.fasterxml.jackson.core.exc.StreamConstraintsException; import com.fasterxml.jackson.core.io.ContentReference; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.util.BufferRecyclers; @@ -15,14 +14,14 @@ import java.math.BigDecimal; import java.math.BigInteger; -public class LongTokenTest { +public class LongTokenTest extends TomlMapperTestBase { private static final int SCALE = 10000; // must be bigger than the default buffer size // Need to ensure max-number-limit not hit private final TomlFactory FACTORY = TomlFactory.builder() .streamReadConstraints(StreamReadConstraints.builder().maxNumberLength(Integer.MAX_VALUE).build()) .build(); - private final ObjectMapper NO_LIMITS_MAPPER = new TomlMapper(FACTORY); + private final ObjectMapper NO_LIMITS_MAPPER = newTomlMapper(FACTORY); @Test public void decimal() throws IOException { @@ -42,7 +41,7 @@ public void decimal() throws IOException { @Test public void decimalTooLong() throws IOException { // default TomlFactory has max num length of 1000 - final ObjectMapper mapper = new TomlMapper(); + final ObjectMapper mapper = newTomlMapper(); StringBuilder toml = new StringBuilder("foo = 0."); for (int i = 0; i < SCALE; i++) { toml.append('0');
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/ParserTest.java+10 −9 modified@@ -27,8 +27,8 @@ import java.util.Arrays; @SuppressWarnings("OctalInteger") -public class ParserTest { - private static final ObjectMapper TOML_MAPPER = new TomlMapper(); +public class ParserTest extends TomlMapperTestBase { + private static final ObjectMapper TOML_MAPPER = newTomlMapper(); private static final ObjectMapper jsonMapper = JsonMapper.builder() .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS) @@ -42,11 +42,11 @@ static ObjectNode toml(@Language("toml") String toml) throws IOException { return (ObjectNode) TOML_MAPPER.readTree(toml); } - static ObjectNode toml(int opts, @Language("toml") String toml) throws IOException { + static ObjectNode toml(TomlFactory factory, @Language("toml") String toml) throws IOException { return Parser.parse( + factory, new IOContext(BufferRecyclers.getBufferRecycler(), ContentReference.rawReference(toml), false), - opts, new StringReader(toml) ); } @@ -950,15 +950,16 @@ public void bigintBase() throws IOException { @Test public void javaTimeDeser() throws IOException { // this is the same test as above, except with explicit java.time deserialization - int options = TomlReadFeature.PARSE_JAVA_TIME.getMask(); + final TomlFactory tomlFactory = newTomlFactory(); + tomlFactory.enable(TomlReadFeature.PARSE_JAVA_TIME); Assert.assertEquals( JsonNodeFactory.instance.objectNode() .<ObjectNode>set("odt1", JsonNodeFactory.instance.pojoNode(OffsetDateTime.parse("1979-05-27T07:32:00Z"))) .<ObjectNode>set("odt2", JsonNodeFactory.instance.pojoNode(OffsetDateTime.parse("1979-05-27T00:32:00-07:00"))) .<ObjectNode>set("odt3", JsonNodeFactory.instance.pojoNode(OffsetDateTime.parse("1979-05-27T00:32:00.999999-07:00"))) .<ObjectNode>set("odt4", JsonNodeFactory.instance.pojoNode(OffsetDateTime.parse("1979-05-27T07:32:00Z"))), - toml(options, + toml(tomlFactory, "odt1 = 1979-05-27T07:32:00Z\n" + "odt2 = 1979-05-27T00:32:00-07:00\n" + "odt3 = 1979-05-27T00:32:00.999999-07:00\n" + @@ -968,20 +969,20 @@ public void javaTimeDeser() throws IOException { JsonNodeFactory.instance.objectNode() .<ObjectNode>set("ldt1", JsonNodeFactory.instance.pojoNode(LocalDateTime.parse("1979-05-27T07:32:00"))) .<ObjectNode>set("ldt2", JsonNodeFactory.instance.pojoNode(LocalDateTime.parse("1979-05-27T00:32:00.999999"))), - toml(options, + toml(tomlFactory, "ldt1 = 1979-05-27T07:32:00\n" + "ldt2 = 1979-05-27T00:32:00.999999") ); Assert.assertEquals( JsonNodeFactory.instance.objectNode() .set("ld1", JsonNodeFactory.instance.pojoNode(LocalDate.parse("1979-05-27"))), - toml(options, "ld1 = 1979-05-27") + toml(tomlFactory, "ld1 = 1979-05-27") ); Assert.assertEquals( JsonNodeFactory.instance.objectNode() .<ObjectNode>set("lt1", JsonNodeFactory.instance.pojoNode(LocalTime.parse("07:32:00"))) .<ObjectNode>set("lt2", JsonNodeFactory.instance.pojoNode(LocalTime.parse("00:32:00.999999"))), - toml(options, + toml(tomlFactory, "lt1 = 07:32:00\n" + "lt2 = 00:32:00.999999") );
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/POJOReadWriteTest.java+2 −2 modified@@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; // Composed of pieces from other format modules' tests -public class POJOReadWriteTest +public class POJOReadWriteTest extends TomlMapperTestBase { @JsonPropertyOrder({ "topLeft", "bottomRight" }) protected static class Rectangle { @@ -150,7 +150,7 @@ public int hashCode() { } } - private final ObjectMapper MAPPER = new TomlMapper(); + private final ObjectMapper MAPPER = newTomlMapper(); private final ObjectMapper JSON_MAPPER = new JsonMapper(); @Test
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/StringOutputUtilTest.java+1 −1 modified@@ -9,7 +9,7 @@ import java.io.IOException; import java.io.StringReader; -public class StringOutputUtilTest { +public class StringOutputUtilTest extends TomlMapperTestBase { @Test public void exhaustiveWriteReadTest() throws IOException { // this test attempts single-character writes for *all* code points, and sees whether they're read back
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/TomlGeneratorTest.java+21 −21 modified@@ -11,11 +11,11 @@ import java.io.StringWriter; import java.time.*; -public class TomlGeneratorTest { +public class TomlGeneratorTest extends TomlMapperTestBase { @Test public void number() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeNumber(123); @@ -27,7 +27,7 @@ public void number() throws IOException { @Test public void bool() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeBoolean(true); @@ -39,7 +39,7 @@ public void bool() throws IOException { @Test public void floats() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeNumber(1.23); @@ -51,7 +51,7 @@ public void floats() throws IOException { @Test public void stringNormal() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo"); @@ -63,7 +63,7 @@ public void stringNormal() throws IOException { @Test public void stringApostrophe() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo'"); @@ -75,7 +75,7 @@ public void stringApostrophe() throws IOException { @Test public void stringQuote() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo\""); @@ -87,7 +87,7 @@ public void stringQuote() throws IOException { @Test public void stringQuoteApostrophe() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo\"'"); @@ -99,7 +99,7 @@ public void stringQuoteApostrophe() throws IOException { @Test public void stringControlCharUnicode() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo\u0001"); @@ -111,7 +111,7 @@ public void stringControlCharUnicode() throws IOException { @Test public void stringControlCharSpecial() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeString("foo\b"); @@ -123,7 +123,7 @@ public void stringControlCharSpecial() throws IOException { @Test public void binary() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeBinary(new byte[] {1,2,3}); @@ -135,7 +135,7 @@ public void binary() throws IOException { @Test public void emptyObject() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartObject(); @@ -148,7 +148,7 @@ public void emptyObject() throws IOException { @Test public void objectWithValues() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartObject(); @@ -165,7 +165,7 @@ public void objectWithValues() throws IOException { @Test public void emptyArray() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartArray(); @@ -178,7 +178,7 @@ public void emptyArray() throws IOException { @Test public void arrayWithScalars() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartArray(); @@ -194,7 +194,7 @@ public void arrayWithScalars() throws IOException { @Test public void arrayMixed() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartArray(); @@ -214,7 +214,7 @@ public void arrayMixed() throws IOException { @Test public void temporal() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("abc"); generator.writeStartArray(); @@ -231,7 +231,7 @@ public void temporal() throws IOException { @Test public void complexKey() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("foo bar"); generator.writeNumber(123); @@ -243,7 +243,7 @@ public void complexKey() throws IOException { // [dataformats-text#258]: byte-backed output not flushing? @Test public void nestedObjectValues() throws IOException { - final ObjectMapper mapper = new TomlMapper(); + final ObjectMapper mapper = newTomlMapper(); final String EXP_TOML = "point.x = 19\n" +"point.y = 72\n"; @@ -277,7 +277,7 @@ private void _writeNested(JsonGenerator g) throws IOException { @Test public void nullEnabledDefault() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("foo"); generator.writeNull(); @@ -289,7 +289,7 @@ public void nullEnabledDefault() throws IOException { @Test(expected = TomlStreamWriteException.class) public void nullDisable() throws IOException { StringWriter w = new StringWriter(); - try (JsonGenerator generator = new TomlMapper().enable(TomlWriteFeature.FAIL_ON_NULL_WRITE).createGenerator(w)) { + try (JsonGenerator generator = newTomlMapper().enable(TomlWriteFeature.FAIL_ON_NULL_WRITE).createGenerator(w)) { generator.writeStartObject(); generator.writeFieldName("foo"); generator.writeNull();
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/TomlMapperTestBase.java+15 −0 added@@ -0,0 +1,15 @@ +package com.fasterxml.jackson.dataformat.toml; + +abstract class TomlMapperTestBase { + protected static TomlFactory newTomlFactory() { + return TomlFactory.builder().build(); + } + + protected static TomlMapper newTomlMapper() { + return new TomlMapper(newTomlFactory()); + } + + protected static TomlMapper newTomlMapper(TomlFactory tomlFactory) { + return new TomlMapper(tomlFactory); + } +}
toml/src/test/java/com/fasterxml/jackson/dataformat/toml/TomlMapperTest.java+9 −9 modified@@ -19,7 +19,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -public class TomlMapperTest { +public class TomlMapperTest extends TomlMapperTestBase { @SuppressWarnings("deprecation") @Rule public final ExpectedException expectedException = ExpectedException.none(); @@ -37,22 +37,22 @@ public class TomlMapperTest { @Test public void string() throws JsonProcessingException { - Assert.assertEquals(TEST_OBJECT, new TomlMapper().readValue(TEST_STRING, TestClass.class)); + Assert.assertEquals(TEST_OBJECT, newTomlMapper().readValue(TEST_STRING, TestClass.class)); } @Test public void bytes() throws IOException { - Assert.assertEquals(TEST_OBJECT, new TomlMapper().readValue(TEST_STRING.getBytes(StandardCharsets.UTF_8), TestClass.class)); + Assert.assertEquals(TEST_OBJECT, newTomlMapper().readValue(TEST_STRING.getBytes(StandardCharsets.UTF_8), TestClass.class)); } @Test public void stream() throws IOException { - Assert.assertEquals(TEST_OBJECT, new TomlMapper().readValue(new ByteArrayInputStream(TEST_STRING.getBytes(StandardCharsets.UTF_8)), TestClass.class)); + Assert.assertEquals(TEST_OBJECT, newTomlMapper().readValue(new ByteArrayInputStream(TEST_STRING.getBytes(StandardCharsets.UTF_8)), TestClass.class)); } @Test public void reader() throws IOException { - Assert.assertEquals(TEST_OBJECT, new TomlMapper().readValue(new StringReader(TEST_STRING), TestClass.class)); + Assert.assertEquals(TEST_OBJECT, newTomlMapper().readValue(new StringReader(TEST_STRING), TestClass.class)); } public static class TestClass { @@ -108,7 +108,7 @@ public void bigDecimal() throws JsonProcessingException { Assert.assertEquals( JsonNodeFactory.instance.objectNode() .put("abc", testValue), - new TomlMapper().readTree("abc = " + testValue.toString()) + newTomlMapper().readTree("abc = " + testValue.toString()) ); } @@ -121,7 +121,7 @@ public void veryBigDecimal() throws JsonProcessingException { } final String value = sb.toString(); try { - new TomlMapper().readTree("abc = " + value); + newTomlMapper().readTree("abc = " + value); Assert.fail("expected TomlStreamReadException"); } catch (TomlStreamReadException e) { Assert.assertTrue("unexpected message: " + e.getMessage(), @@ -141,7 +141,7 @@ public void veryBigDecimalWithNumLenUnlimited() throws JsonProcessingException { TomlFactory factory = TomlFactory.builder() .streamReadConstraints(StreamReadConstraints.builder().maxNumberLength(Integer.MAX_VALUE).build()) .build(); - TomlMapper mapper = new TomlMapper(factory); + TomlMapper mapper = newTomlMapper(factory); Assert.assertEquals( testValue, mapper.readTree("abc = " + value).get("abc").decimalValue() @@ -159,7 +159,7 @@ public void temporalFieldFlag() throws JsonProcessingException { ); Assert.assertEquals( "2021-03-26", - new TomlMapper().readValue("foo = 2021-03-26", ObjectField.class).foo + newTomlMapper().readValue("foo = 2021-03-26", ObjectField.class).foo ); }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-rg2c-cfxv-qp6fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-3894ghsaADVISORY
- bugs.chromium.org/p/oss-fuzz/issues/detailghsaWEB
- github.com/FasterXML/jackson-dataformats-text/blob/2.16/release-notes/VERSION-2.xghsaWEB
- github.com/FasterXML/jackson-dataformats-text/commit/5dd5f740aedcf37adad7ffece460e75e54abb0edghsaWEB
- github.com/FasterXML/jackson-dataformats-text/pull/398ghsaWEB
News mentions
0No linked articles in our index yet.