diff --git a/avro/src/test/java/com/fasterxml/jackson/dataformat/avro/RoundtripTest.java b/avro/src/test/java/com/fasterxml/jackson/dataformat/avro/RoundtripTest.java index 040753174..b88afb02a 100644 --- a/avro/src/test/java/com/fasterxml/jackson/dataformat/avro/RoundtripTest.java +++ b/avro/src/test/java/com/fasterxml/jackson/dataformat/avro/RoundtripTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.StreamReadConstraints; import com.fasterxml.jackson.databind.*; public class RoundtripTest extends MapTest @@ -69,14 +70,8 @@ public void testCharSequences() throws Exception input.id = "123"; input.name = "John"; - byte[] avroData = null; - try { - avroData = writ.writeValueAsBytes(input); - assertNotNull(avroData); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } + byte[] avroData = writ.writeValueAsBytes(input); + assertNotNull(avroData); CharSeqBean output = mapper.reader(CHARSEQ_SCHEMA) .forType(CharSeqBean.class).readValue(avroData); @@ -85,4 +80,29 @@ public void testCharSequences() throws Exception assertEquals(input.id, output.id); assertEquals(input.name, output.name); } + + public void testCharSequencesLowStringLimit() throws Exception + { + AvroFactory factory = AvroFactory.builder() + .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(1).build()) + .build(); + ObjectMapper mapper = new AvroMapper(factory) + .enable(JsonGenerator.Feature.IGNORE_UNKNOWN); + ObjectWriter writ = mapper.writer(CHARSEQ_SCHEMA); + + CharSeqBean input = new CharSeqBean(); + input.id = "123"; + input.name = "John"; + + byte[] avroData = writ.writeValueAsBytes(input); + assertNotNull(avroData); + + try { + mapper.reader(CHARSEQ_SCHEMA) + .forType(CharSeqBean.class).readValue(avroData); + fail("expected IllegalStateException"); + } catch (IllegalStateException ise) { + assertEquals("String length (3) exceeds the maximum length (1)", ise.getMessage()); + } + } } diff --git a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java index e8603b916..36c910101 100644 --- a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java +++ b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java @@ -525,7 +525,7 @@ public CBORParser(IOContext ctxt, int parserFeatures, int cborFeatures, _inputPtr = start; _inputEnd = end; _bufferRecyclable = bufferRecyclable; - _textBuffer = ctxt.constructTextBuffer(); + _textBuffer = ctxt.constructReadConstrainedTextBuffer(); DupDetector dups = JsonParser.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(parserFeatures) ? DupDetector.rootDetector(this) : null; _streamReadContext = CBORReadContext.createRootContext(dups); diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/CBORTestBase.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/CBORTestBase.java index 36e635703..8a57810c8 100644 --- a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/CBORTestBase.java +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/CBORTestBase.java @@ -45,6 +45,10 @@ protected CBORMapper cborMapper() { return new CBORMapper(cborFactory()); } + protected CBORMapper cborMapper(CBORFactory cborFactory) { + return new CBORMapper(cborFactory); + } + protected CBORFactory cborFactory() { return new CBORFactory(); } diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/seq/ReadTreesTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/seq/ReadTreesTest.java index 11edfd0d8..0d238500c 100644 --- a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/seq/ReadTreesTest.java +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/seq/ReadTreesTest.java @@ -2,8 +2,10 @@ import java.util.List; +import com.fasterxml.jackson.core.StreamReadConstraints; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; public class ReadTreesTest extends CBORTestBase @@ -62,4 +64,27 @@ public void testReadTreeSequence() throws Exception /* not differ) /********************************************************** */ + + public void testReadTreeSequenceLowStringLimit() throws Exception + { + final byte[] INPUT = concat( + cborDoc(a2q("{\"id\":1, \"value\":137 }")), + cborDoc(a2q("{\"id\":2, \"value\":256 }\n")), + cborDoc(a2q("{\"id\":3, \"value\":-89 }")) + ); + + CBORFactory cborFactory = cborFactoryBuilder() + .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(1).build()) + .build(); + try (MappingIterator it = cborMapper(cborFactory).readerFor(JsonNode.class) + .readValues(INPUT)) { + assertTrue(it.hasNextValue()); + try { + it.nextValue(); + fail("expected IllegalStateException"); + } catch (IllegalStateException ise) { + assertEquals("String length (2) exceeds the maximum length (1)", ise.getMessage()); + } + } + } } diff --git a/protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufParser.java b/protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufParser.java index 93e69cc1b..5dcc3b21e 100644 --- a/protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufParser.java +++ b/protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufParser.java @@ -305,7 +305,7 @@ public ProtobufParser(IOContext ctxt, int parserFeatures, _inputPtr = start; _inputEnd = end; _bufferRecyclable = bufferRecyclable; - _textBuffer = ctxt.constructTextBuffer(); + _textBuffer = ctxt.constructReadConstrainedTextBuffer(); _parsingContext = ProtobufReadContext.createRootContext(); _tokenInputRow = -1; diff --git a/protobuf/src/test/java/com/fasterxml/jackson/dataformat/protobuf/ReadSimpleTest.java b/protobuf/src/test/java/com/fasterxml/jackson/dataformat/protobuf/ReadSimpleTest.java index d2069b0cb..8e444a186 100644 --- a/protobuf/src/test/java/com/fasterxml/jackson/dataformat/protobuf/ReadSimpleTest.java +++ b/protobuf/src/test/java/com/fasterxml/jackson/dataformat/protobuf/ReadSimpleTest.java @@ -5,6 +5,8 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.StreamReadConstraints; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema; @@ -357,4 +359,28 @@ public void testSkipUnknown() throws Exception assertEquals(input.x, result.x); assertEquals(input.y, result.y); } + + public void testStringArraySimpleLowLimit() throws Exception + { + ProtobufSchema schema = ProtobufSchemaLoader.std.parse(PROTOC_STRINGS); + ProtobufFactory protobufFactory = ProtobufFactory.builder() + .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(1).build()) + .build(); + ProtobufMapper protobufMapper = ProtobufMapper.builder(protobufFactory).build(); + final ObjectWriter w = protobufMapper.writerFor(Strings.class) + .with(schema); + Strings input = new Strings("Dogs", "like", "Baco\u00F1"); + byte[] bytes = w.writeValueAsBytes(input); + assertNotNull(bytes); + assertEquals(20, bytes.length); + + try { + protobufMapper.readerFor(Strings.class).with(schema).readValue(bytes); + fail("Expected JsonMappingException"); + } catch (JsonMappingException jme) { + String message = jme.getMessage(); + assertTrue("unexpected message: " + message, + message.startsWith("String length (4) exceeds the maximum length (1)")); + } + } } diff --git a/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileParserBase.java b/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileParserBase.java index cf7db4a1b..92221148c 100644 --- a/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileParserBase.java +++ b/smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileParserBase.java @@ -269,7 +269,7 @@ public SmileParserBase(IOContext ctxt, int parserFeatures, int formatFeatures, ? DupDetector.rootDetector(this) : null; _streamReadContext = JsonReadContext.createRootContext(dups); - _textBuffer = ctxt.constructTextBuffer(); + _textBuffer = ctxt.constructReadConstrainedTextBuffer(); _smileBufferRecycler = _smileBufferRecycler(); } diff --git a/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/async/SimpleStringArrayTest.java b/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/async/SimpleStringArrayTest.java index aa57fff73..02e47cac6 100644 --- a/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/async/SimpleStringArrayTest.java +++ b/smile/src/test/java/com/fasterxml/jackson/dataformat/smile/async/SimpleStringArrayTest.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.StreamReadConstraints; import com.fasterxml.jackson.dataformat.smile.SmileFactory; import com.fasterxml.jackson.dataformat.smile.SmileGenerator; import com.fasterxml.jackson.dataformat.smile.SmileParser; @@ -109,6 +110,36 @@ public void testLongAsciiStrings() throws IOException _testStrings(f, input, data, 1, 1); } + public void testLongAsciiStringsLowStringLimit() throws IOException + { + final String[] input = new String[] { + // ~100 chars for long(er) content + String.format("%s %s %s %s %s %s %s %s %s %s %s %s", + str0to9,str0to9,"...",str0to9,"/", str0to9, + str0to9,"",str0to9,str0to9,"...",str0to9), + LONG_ASCII + }; + SmileFactory f = SmileFactory.builder() + .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(10).build()) + .enable(SmileParser.Feature.REQUIRE_HEADER) + .enable(SmileGenerator.Feature.CHECK_SHARED_NAMES) + .enable(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES) + .build(); + byte[] data = _stringDoc(f, input); + + AsyncReaderWrapper r = asyncForBytes(f, 1, data, 0); + // start with "no token" + assertNull(r.currentToken()); + assertToken(JsonToken.START_ARRAY, r.nextToken()); + assertToken(JsonToken.VALUE_STRING, r.nextToken()); + try { + r.currentText(); + fail("expected IllegalStateException"); + } catch (IllegalStateException ise) { + assertEquals("String length (98) exceeds the maximum length (10)", ise.getMessage()); + } + } + public void testLongUnicodeStrings() throws IOException { // ~100 chars for long(er) content