diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonElementReader.java b/gson/src/main/java/com/google/gson/internal/bind/JsonElementReader.java index dbc04cd8..03821971 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JsonElementReader.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JsonElementReader.java @@ -170,6 +170,9 @@ public final class JsonElementReader extends JsonReader { throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); } double result = ((JsonPrimitive) peekStack()).getAsDouble(); + if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) { + throw new NumberFormatException("JSON forbids NaN and infinities: " + result); + } popStack(); return result; } diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapter.java index c246222b..6e3f3f83 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapter.java @@ -70,7 +70,7 @@ public abstract class TypeAdapter { public T fromJsonElement(JsonElement json) { try { - JsonReader jsonReader = new JsonReader(new StringReader(json.toString())); + JsonReader jsonReader = new JsonElementReader(json); jsonReader.setLenient(true); return read(jsonReader); } catch (IOException e) { diff --git a/gson/src/test/java/com/google/gson/internal/bind/JsonElementReaderTest.java b/gson/src/test/java/com/google/gson/internal/bind/JsonElementReaderTest.java index 5530f2f8..ff3e0ccf 100644 --- a/gson/src/test/java/com/google/gson/internal/bind/JsonElementReaderTest.java +++ b/gson/src/test/java/com/google/gson/internal/bind/JsonElementReaderTest.java @@ -34,6 +34,43 @@ public final class JsonElementReaderTest extends TestCase { reader.endArray(); } + public void testLenientNansAndInfinities() throws IOException { + JsonElement element = new JsonParser().parse("[NaN, -Infinity, Infinity]"); + JsonElementReader reader = new JsonElementReader(element); + reader.setLenient(true); + reader.beginArray(); + assertTrue(Double.isNaN(reader.nextDouble())); + assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); + assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); + reader.endArray(); + } + + public void testStrictNansAndInfinities() throws IOException { + JsonElement element = new JsonParser().parse("[NaN, -Infinity, Infinity]"); + JsonElementReader reader = new JsonElementReader(element); + reader.setLenient(false); + reader.beginArray(); + try { + reader.nextDouble(); + fail(); + } catch (NumberFormatException e) { + } + assertEquals("NaN", reader.nextString()); + try { + reader.nextDouble(); + fail(); + } catch (NumberFormatException e) { + } + assertEquals("-Infinity", reader.nextString()); + try { + reader.nextDouble(); + fail(); + } catch (NumberFormatException e) { + } + assertEquals("Infinity", reader.nextString()); + reader.endArray(); + } + public void testNumbersFromStrings() throws IOException { JsonElement element = new JsonParser().parse("[\"1\", \"2\", \"3\"]"); JsonElementReader reader = new JsonElementReader(element);