Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 @@ -25,6 +25,8 @@
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -218,7 +220,10 @@ public JsonWriter value(Number value) throws IOException {
return nullValue();
}

if (!isLenient()) {
// BigDecimal/BigInteger are always valid JSON numbers (mirrors
// JsonWriter.alwaysCreatesValidJsonNumber); their doubleValue() can overflow to Infinity
// even though the value is finite, so do not use it as the finiteness oracle for them.
if (!isLenient() && !(value instanceof BigDecimal) && !(value instanceof BigInteger)) {
double d = value.doubleValue();
if (Double.isNaN(d) || Double.isInfinite(d)) {
throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
Expand Down Expand Up @@ -316,4 +318,36 @@ public void testEndArrayWhenStackTopIsNotArrayThrows() throws IOException {
writer.beginObject();
assertThrows(IllegalStateException.class, () -> writer.endArray());
}

@Test
public void testStrictWriterAcceptsFiniteBigDecimalAboveDoubleMax() throws IOException {
// Pre-fix, JsonTreeWriter.value(Number) routed Number arguments through
// doubleValue() for finiteness checking and rejected BigDecimal("1E400") —
// a finite value whose doubleValue() overflows to Infinity. JsonWriter
// already skips that check for BigDecimal/BigInteger via the
// alwaysCreatesValidJsonNumber whitelist; this test pins that JsonTreeWriter
// now mirrors that behavior in STRICT mode.
JsonTreeWriter writer = new JsonTreeWriter();
writer.setStrictness(Strictness.STRICT);
writer.beginArray();
writer.value(new BigDecimal("1E400"));
writer.endArray();
assertThat(writer.get().toString()).isEqualTo("[1E+400]");
}

@Test
public void testStrictWriterAcceptsFiniteBigIntegerAboveDoubleMax() throws IOException {
// Same fix surface as the BigDecimal case above but for BigInteger.
// doubleValue() on a BigInteger > Double.MAX_VALUE overflows to Infinity;
// the alwaysCreatesValidJsonNumber whitelist covers both classes and the
// fix mirrors that. Pin BigInteger separately so a future change to the
// BigDecimal-only branch cannot silently regress BigInteger handling.
JsonTreeWriter writer = new JsonTreeWriter();
writer.setStrictness(Strictness.STRICT);
BigInteger finiteHuge = BigInteger.TEN.pow(400);
writer.beginArray();
writer.value(finiteHuge);
writer.endArray();
assertThat(writer.get().toString()).isEqualTo("[" + finiteHuge + "]");
}
}