diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index e908c79d85..eaed974527 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -1050,7 +1050,15 @@ public double nextDouble() throws IOException { } peeked = PEEKED_BUFFERED; - double result = Double.parseDouble(peekedString); // don't catch this NumberFormatException. + double result; + try { + result = Double.parseDouble(peekedString); + } catch (NumberFormatException e) { + NumberFormatException rethrown = + new NumberFormatException("Expected a double but was " + peekedString + locationString()); + rethrown.initCause(e); + throw rethrown; + } if (strictness != Strictness.LENIENT && (Double.isNaN(result) || Double.isInfinite(result))) { throw syntaxError("JSON forbids NaN and infinities: " + result); } @@ -1104,7 +1112,15 @@ public long nextLong() throws IOException { } peeked = PEEKED_BUFFERED; - double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException. + double asDouble; + try { + asDouble = Double.parseDouble(peekedString); + } catch (NumberFormatException e) { + NumberFormatException rethrown = + new NumberFormatException("Expected a long but was " + peekedString + locationString()); + rethrown.initCause(e); + throw rethrown; + } long result = (long) asDouble; if (result != asDouble) { // Make sure no precision was lost casting to 'long'. throw new NumberFormatException("Expected a long but was " + peekedString + locationString()); @@ -1347,7 +1363,15 @@ public int nextInt() throws IOException { } peeked = PEEKED_BUFFERED; - double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException. + double asDouble; + try { + asDouble = Double.parseDouble(peekedString); + } catch (NumberFormatException e) { + NumberFormatException rethrown = + new NumberFormatException("Expected an int but was " + peekedString + locationString()); + rethrown.initCause(e); + throw rethrown; + } result = (int) asDouble; if (result != asDouble) { // Make sure no precision was lost casting to 'int'. throw new NumberFormatException("Expected an int but was " + peekedString + locationString()); diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index 24f15cfb43..e7916ecf37 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -701,6 +701,38 @@ public void testLenientQuotedNonFiniteDoubles() throws IOException { reader.endArray(); } + /** Regression test for https://github.com/google/gson/issues/1564 */ + @Test + public void testNextDoubleNumberFormatExceptionContainsLocation() throws IOException { + JsonReader reader = new JsonReader(reader("[\"\" ]")); + reader.setStrictness(Strictness.LENIENT); + reader.beginArray(); + NumberFormatException e = assertThrows(NumberFormatException.class, () -> reader.nextDouble()); + assertThat(e).hasMessageThat().contains("path $[0]"); + } + + /** Regression test for https://github.com/google/gson/issues/1564 */ + @Test + public void testNextIntNumberFormatExceptionContainsLocation() throws IOException { + JsonReader reader = new JsonReader(reader("{\"x\": \"\"}")); + reader.setStrictness(Strictness.LENIENT); + reader.beginObject(); + var unused = reader.nextName(); + NumberFormatException e = assertThrows(NumberFormatException.class, () -> reader.nextInt()); + assertThat(e).hasMessageThat().contains("path $.x"); + } + + /** Regression test for https://github.com/google/gson/issues/1564 */ + @Test + public void testNextLongNumberFormatExceptionContainsLocation() throws IOException { + JsonReader reader = new JsonReader(reader("{\"y\": \"\"}")); + reader.setStrictness(Strictness.LENIENT); + reader.beginObject(); + var unused = reader.nextName(); + NumberFormatException e = assertThrows(NumberFormatException.class, () -> reader.nextLong()); + assertThat(e).hasMessageThat().contains("path $.y"); + } + @Test public void testStrictNonFiniteDoublesWithSkipValue() throws IOException { String json = "[NaN]";