diff --git a/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsParser.java b/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsParser.java index d00c219d..9df88880 100644 --- a/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsParser.java +++ b/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/JavaPropsParser.java @@ -266,6 +266,7 @@ public JsonToken nextToken() throws IOException { if (_readContext == null) { // end of content return null; } + _streamReadConstraints.validateNestingDepth(_readContext.getNestingDepth()); } return _currToken; } diff --git a/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/io/JPropReadContext.java b/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/io/JPropReadContext.java index 7cefe3e0..f1131d01 100644 --- a/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/io/JPropReadContext.java +++ b/properties/src/main/java/com/fasterxml/jackson/dataformat/javaprop/io/JPropReadContext.java @@ -52,6 +52,7 @@ public JPropReadContext(int contextType, JPropReadContext p, JPropNode node) _index = -1; _parent = p; _branchText = node.getValue(); + _nestingDepth = p == null ? 0 : p._nestingDepth + 1; } public static JPropReadContext create(JPropNode root) { diff --git a/properties/src/test/java/com/fasterxml/jackson/dataformat/javaprop/dos/DeepNestParserTest.java b/properties/src/test/java/com/fasterxml/jackson/dataformat/javaprop/dos/DeepNestParserTest.java new file mode 100644 index 00000000..2e3f3862 --- /dev/null +++ b/properties/src/test/java/com/fasterxml/jackson/dataformat/javaprop/dos/DeepNestParserTest.java @@ -0,0 +1,54 @@ +package com.fasterxml.jackson.dataformat.javaprop.dos; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.StreamReadConstraints; +import com.fasterxml.jackson.core.exc.StreamConstraintsException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.javaprop.JavaPropsFactory; +import com.fasterxml.jackson.dataformat.javaprop.ModuleTestBase; + +import java.io.IOException; + +public class DeepNestParserTest extends ModuleTestBase { + + public void testDeeplyNestedData() throws IOException { + final int depth = 1500; + final String doc = genDeeplyNestedData(depth); + final ObjectMapper mapper = newPropertiesMapper(); + try (JsonParser jp = mapper.createParser(doc)) { + JsonToken jt; + while ((jt = jp.nextToken()) != null) { + + } + fail("expected StreamConstraintsException"); + } catch (StreamConstraintsException e) { + assertEquals("Depth (1001) exceeds the maximum allowed nesting depth (1000)", e.getMessage()); + } + } + + public void testDeeplyNestedDataWithUnconstrainedMapper() throws IOException { + final int depth = 1500; + final String doc = genDeeplyNestedData(depth); + final JavaPropsFactory factory = JavaPropsFactory.builder() + .streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(Integer.MAX_VALUE).build()) + .build(); + final ObjectMapper mapper = propertiesMapperBuilder(factory).build(); + try (JsonParser jp = mapper.createParser(doc)) { + JsonToken jt; + while ((jt = jp.nextToken()) != null) { + + } + } + } + + private String genDeeplyNestedData(final int depth) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < depth; i++) { + if (i > 1) sb.append('.'); + sb.append('a'); + } + sb.append("=val"); + return sb.toString(); + } +}