Skip to content

Commit

Permalink
check number lengths (FasterXML#3687)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjfanning authored Dec 4, 2022
1 parent 1016dc5 commit 6a7b516
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) t
if (_checkTextualNull(ctxt, text)) {
return (Double) getNullValue(ctxt);
}
p.streamReadConstraints().validateFPLength(text.length());
try {
return _parseDouble(text, p.isEnabled(StreamReadFeature.USE_FAST_DOUBLE_PARSER));
} catch (IllegalArgumentException iae) { }
Expand Down Expand Up @@ -843,13 +844,15 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
}
try {
if (!_isIntNumber(text)) {
p.streamReadConstraints().validateFPLength(text.length());
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return NumberInput.parseBigDecimal(
text, p.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
}
return Double.valueOf(
NumberInput.parseDouble(text, p.isEnabled(StreamReadFeature.USE_FAST_DOUBLE_PARSER)));
}
p.streamReadConstraints().validateIntegerLength(text.length());
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
return NumberInput.parseBigInteger(text, p.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
}
Expand Down Expand Up @@ -961,6 +964,7 @@ public BigInteger deserialize(JsonParser p, DeserializationContext ctxt) throws
// note: no need to call `coerce` as this is never primitive
return getNullValue(ctxt);
}
p.streamReadConstraints().validateIntegerLength(text.length());
try {
return NumberInput.parseBigInteger(text, p.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
} catch (IllegalArgumentException iae) { }
Expand Down Expand Up @@ -1030,6 +1034,7 @@ public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt)
// note: no need to call `coerce` as this is never primitive
return getNullValue(ctxt);
}
p.streamReadConstraints().validateFPLength(text.length());
try {
return NumberInput.parseBigDecimal(text, p.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
} catch (IllegalArgumentException iae) { }
Expand Down
123 changes: 123 additions & 0 deletions src/test/java/com/fasterxml/jackson/databind/deser/TestBigNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.fasterxml.jackson.databind.deser;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;

import java.math.BigDecimal;
import java.math.BigInteger;

public class TestBigNumbers extends BaseMapTest
{
static class BigDecimalWrapper {
BigDecimal number;

public BigDecimalWrapper() {}

public BigDecimalWrapper(BigDecimal number) {
this.number = number;
}

public void setNumber(BigDecimal number) {
this.number = number;
}
}

static class BigIntegerWrapper {
BigInteger number;

public BigIntegerWrapper() {}

public BigIntegerWrapper(BigInteger number) {
this.number = number;
}

public void setNumber(BigInteger number) {
this.number = number;
}
}

/*
/**********************************************************
/* Tests
/**********************************************************
*/

private final ObjectMapper MAPPER = newJsonMapper();

private final ObjectMapper newJsonMapperWithUnlimitedNumberSizeSupport() {
JsonFactory jsonFactory = JsonFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder().maxNumberLength(Integer.MAX_VALUE).build())
.build();
return JsonMapper.builder(jsonFactory).build();
}

public void testDouble() throws Exception
{
try {
MAPPER.readValue(generateJson("d"), DoubleWrapper.class);
} catch (JsonMappingException jsonMappingException) {
assertTrue("unexpected exception message: " + jsonMappingException.getMessage(),
jsonMappingException.getMessage().startsWith("Malformed numeric value ([number with 1200 characters])"));
}
}

public void testDoubleUnlimited() throws Exception
{
DoubleWrapper dw =
newJsonMapperWithUnlimitedNumberSizeSupport().readValue(generateJson("d"), DoubleWrapper.class);
assertNotNull(dw);
}

public void testBigDecimal() throws Exception
{
try {
MAPPER.readValue(generateJson("number"), BigDecimalWrapper.class);
} catch (JsonMappingException jsonMappingException) {
assertTrue("unexpected exception message: " + jsonMappingException.getMessage(),
jsonMappingException.getMessage().startsWith("Malformed numeric value ([number with 1200 characters])"));
}
}

public void testBigDecimalUnlimited() throws Exception
{
BigDecimalWrapper bdw =
newJsonMapperWithUnlimitedNumberSizeSupport()
.readValue(generateJson("number"), BigDecimalWrapper.class);
assertNotNull(bdw);
}

public void testBigInteger() throws Exception
{
try {
MAPPER.readValue(generateJson("number"), BigIntegerWrapper.class);
} catch (JsonMappingException jsonMappingException) {
assertTrue("unexpected exception message: " + jsonMappingException.getMessage(),
jsonMappingException.getMessage().startsWith("Malformed numeric value ([number with 1200 characters])"));
}
}

public void testBigIntegerUnlimited() throws Exception
{
BigIntegerWrapper bdw =
newJsonMapperWithUnlimitedNumberSizeSupport()
.readValue(generateJson("number"), BigIntegerWrapper.class);
assertNotNull(bdw);
}

private String generateJson(final String fieldName) {
final int len = 1200;
final StringBuilder sb = new StringBuilder();
sb.append("{\"")
.append(fieldName)
.append("\": ");
for (int i = 0; i < len; i++) {
sb.append(1);
}
sb.append("}");
return sb.toString();
}
}

0 comments on commit 6a7b516

Please sign in to comment.