-
Notifications
You must be signed in to change notification settings - Fork 122
code to handle FasterXML/jackson-databind/issues/2141 #84
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,11 @@ public class DurationDeserializer extends JSR310DeserializerBase<Duration> | |
|
||
public static final DurationDeserializer INSTANCE = new DurationDeserializer(); | ||
|
||
private static final BigDecimal DURATION_MAX = new BigDecimal( | ||
Long.MAX_VALUE + "." + java.time.Instant.MAX.getNano()); | ||
private static final BigDecimal DURATION_MIN = new BigDecimal( | ||
Long.MIN_VALUE + "." + java.time.Instant.MIN.getNano()); | ||
|
||
private DurationDeserializer() | ||
{ | ||
super(Duration.class); | ||
|
@@ -52,6 +57,13 @@ public Duration deserialize(JsonParser parser, DeserializationContext context) t | |
{ | ||
case JsonTokenId.ID_NUMBER_FLOAT: | ||
BigDecimal value = parser.getDecimalValue(); | ||
// If the decimal isn't within the bounds of a duration, bail out | ||
if(value.compareTo(DURATION_MAX) > 0 || | ||
value.compareTo(DURATION_MIN) < 0) { | ||
throw new DateTimeException( | ||
"Instant exceeds minimum or maximum Duration"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This changes the behavior, and I agree with @yishaigalatzer that we shouldn't change behavior while patching this problem. It's safer simply guard against the unbounded-execution time by catching the cases where the
That preserves the existing (though undesirable) behavior for large values with random low-order bits, and doesn't throw exceptions in new cases. As @cowtowncoder implied, that change requires careful design consideration, and shouldn't block this fix. |
||
} | ||
|
||
long seconds = value.longValue(); | ||
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); | ||
return Duration.ofSeconds(seconds, nanoseconds); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
package com.fasterxml.jackson.datatype.jsr310.deser; | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import com.fasterxml.jackson.core.JsonParseException; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still needed? I think all three added imports are leftover from a prior revision. |
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.core.JsonToken; | ||
import com.fasterxml.jackson.core.JsonTokenId; | ||
|
@@ -29,6 +30,8 @@ | |
|
||
import java.io.IOException; | ||
import java.math.BigDecimal; | ||
import java.text.DecimalFormat; | ||
import java.text.NumberFormat; | ||
import java.time.DateTimeException; | ||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
|
@@ -52,6 +55,11 @@ public class InstantDeserializer<T extends Temporal> | |
{ | ||
private static final long serialVersionUID = 1L; | ||
|
||
private static final BigDecimal INSTANT_MAX = new BigDecimal( | ||
java.time.Instant.MAX.getEpochSecond() + "." + java.time.Instant.MAX.getNano()); | ||
private static final BigDecimal INSTANT_MIN = new BigDecimal( | ||
java.time.Instant.MIN.getEpochSecond() + "." + java.time.Instant.MIN.getNano()); | ||
|
||
/** | ||
* Constants used to check if the time offset is zero. See [jackson-modules-java8#18] | ||
* | ||
|
@@ -279,6 +287,13 @@ protected T _fromLong(DeserializationContext context, long timestamp) | |
|
||
protected T _fromDecimal(DeserializationContext context, BigDecimal value) | ||
{ | ||
// If the decimal isnt within the bounds of an Instant, bail out | ||
if(value.compareTo(INSTANT_MAX) > 0 || | ||
value.compareTo(INSTANT_MIN) < 0) { | ||
throw new DateTimeException( | ||
"Instant exceeds minimum or maximum instant"); | ||
} | ||
|
||
long seconds = value.longValue(); | ||
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); | ||
return fromNanoseconds.apply(new FromDecimalArguments( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd write these bounds as (in effect) MAX+1 and MIN-1 which have the same safety-net effect to guard against
BigDecimal.longValue
while lettingDuration
worry about the specific sub-second boundary.(I'd rather not have to worry about, for example, how
Duration
deals with fractions with more decimal places than nanoseconds.)