Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support nesting limits for writing with StreamWriteConstraints #421

Merged
merged 5 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,11 @@ public CsvGenerator disable(Feature f) {
return this;
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
}

/*
/**********************************************************
/* Public API: low-level I/O
Expand Down Expand Up @@ -551,6 +556,7 @@ && _skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
}
}
_tokenWriteContext = _tokenWriteContext.createChildArrayContext(null);
streamWriteConstraints().validateNestingDepth(_tokenWriteContext.getNestingDepth());
// and that's about it, really
}

Expand Down Expand Up @@ -597,6 +603,7 @@ public final void writeStartObject() throws IOException
}
}
_tokenWriteContext = _tokenWriteContext.createChildObjectContext(null);
streamWriteConstraints().validateNestingDepth(_tokenWriteContext.getNestingDepth());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ protected SimpleTokenWriteContext(int type, SimpleTokenWriteContext parent, DupD
super();
_type = type;
_parent = parent;
_nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_dups = dups;
_index = -1;
_currentValue = currentValue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.fasterxml.jackson.dataformat.csv.ser.dos;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.ModuleTestBase;

import java.util.ArrayList;
import java.util.List;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest extends ModuleTestBase
{
private final CsvMapper MAPPER = mapperForCsv();

public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
assertTrue("JsonMappingException message is as expected?",
jmex.getMessage().startsWith("Document nesting depth (1001) exceeds the maximum allowed"));
pjfanning marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public JavaPropsGenerator(IOContext ctxt, int stdFeatures, ObjectCodec codec)
_jpropContext = JPropWriteContext.createRootContext();
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
}

@Override // since 2.13
public Object currentValue() {
return _jpropContext.getCurrentValue();
Expand Down Expand Up @@ -267,6 +272,7 @@ public void writeFieldName(String name) throws IOException
public void writeStartArray() throws IOException {
_verifyValueWrite("start an array");
_jpropContext = _jpropContext.createChildArrayContext(_basePath.length());
streamWriteConstraints().validateNestingDepth(_jpropContext.getNestingDepth());
}

@Override
Expand All @@ -281,6 +287,7 @@ public void writeEndArray() throws IOException {
public void writeStartObject() throws IOException {
_verifyValueWrite("start an object");
_jpropContext = _jpropContext.createChildObjectContext(_basePath.length());
streamWriteConstraints().validateNestingDepth(_jpropContext.getNestingDepth());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ protected JPropWriteContext(int type, JPropWriteContext parent,
super();
_type = type;
_parent = parent;
_nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_basePathLength = basePathLength;
_index = -1;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.fasterxml.jackson.dataformat.javaprop.dos;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper;
import com.fasterxml.jackson.dataformat.javaprop.ModuleTestBase;

import java.util.ArrayList;
import java.util.List;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest extends ModuleTestBase
{
private final JavaPropsMapper MAPPER = newPropertiesMapper();

public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
assertTrue("JsonMappingException message is as expected?",
jmex.getMessage().startsWith("Document nesting depth (1001) exceeds the maximum allowed"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public TomlGenerator(IOContext ioCtxt, int stdFeatures, int tomlFeatures, Object
_outputEnd = _outputBuffer.length;
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
}

/*
/**********************************************************************
/* Versioned
Expand Down Expand Up @@ -343,6 +348,7 @@ public void writeStartArray(Object currValue) throws IOException {
_verifyValueWrite("start an array", true);
_streamWriteContext = _streamWriteContext.createChildArrayContext(currValue,
_basePath.length());
streamWriteConstraints().validateNestingDepth(_streamWriteContext.getNestingDepth());
if (_streamWriteContext._inline) {
_writeRaw('[');
}
Expand Down Expand Up @@ -373,6 +379,7 @@ public void writeStartObject(Object forValue) throws IOException {
// objects aren't always materialized right now
_verifyValueWrite("start an object", false);
_streamWriteContext = _streamWriteContext.createChildObjectContext(forValue, _basePath.length());
streamWriteConstraints().validateNestingDepth(_streamWriteContext.getNestingDepth());
if (_streamWriteContext._inline) {
writeRaw('{');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ final class TomlWriteContext extends JsonStreamContext {
super();
_type = type;
_parent = parent;
_nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_basePathLength = basePathLength;
_index = -1;
_currentValue = currValue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.fasterxml.jackson.dataformat.toml.dos;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.toml.TomlMapperTestBase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest extends TomlMapperTestBase
{
private final ObjectMapper MAPPER = newTomlMapper();

@Test
public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
assertTrue("JsonMappingException message is as expected?",
jmex.getMessage().startsWith("Document nesting depth (1001) exceeds the maximum allowed"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@ protected DumperOptions buildDumperOptions(int jsonFeatures, int yamlFeatures,
return opt;
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _ioContext.streamWriteConstraints();
}

/*
/**********************************************************************
/* Versioned
Expand Down Expand Up @@ -585,6 +590,7 @@ public final void writeStartArray() throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext();
streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
FlowStyle style = _outputOptions.getDefaultFlowStyle();
String yamlTag = _typeId;
boolean implicit = (yamlTag == null);
Expand Down Expand Up @@ -613,6 +619,7 @@ public final void writeStartObject() throws IOException
{
_verifyValueWrite("start an object");
_writeContext = _writeContext.createChildObjectContext();
streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
FlowStyle style = _outputOptions.getDefaultFlowStyle();
String yamlTag = _typeId;
boolean implicit = (yamlTag == null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.fasterxml.jackson.dataformat.yaml.ser.dos;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

import java.util.ArrayList;
import java.util.List;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicDataSerTest extends ModuleTestBase
{
private final ObjectMapper MAPPER = YAMLMapper.builder().build();

public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected JsonMappingException");
} catch (JsonMappingException jmex) {
assertTrue("JsonMappingException message is as expected?",
jmex.getMessage().startsWith("Document nesting depth (1001) exceeds the maximum allowed"));
pjfanning marked this conversation as resolved.
Show resolved Hide resolved
}
}
}