Skip to content

Commit 8039f96

Browse files
authored
Fix issue in handling of corrupt Ion number (#429)
1 parent fc337c4 commit 8039f96

File tree

4 files changed

+77
-23
lines changed

4 files changed

+77
-23
lines changed

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonParser.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -333,13 +333,22 @@ public int getTextOffset() throws IOException {
333333
@Override
334334
public BigInteger getBigIntegerValue() throws IOException {
335335
_verifyIsNumberToken();
336-
return _reader.bigIntegerValue();
336+
try {
337+
return _reader.bigIntegerValue();
338+
} catch (IonException e) {
339+
return _reportCorruptNumber(e);
340+
}
337341
}
338342

339343
@Override
340344
public BigDecimal getDecimalValue() throws IOException {
345+
341346
_verifyIsNumberToken();
342-
return _reader.bigDecimalValue();
347+
try {
348+
return _reader.bigDecimalValue();
349+
} catch (IonException e) {
350+
return _reportCorruptNumber(e);
351+
}
343352
}
344353

345354
@Override
@@ -566,13 +575,10 @@ public JsonToken nextToken() throws IOException
566575
try {
567576
type = _reader.next();
568577
} catch (IonException e) {
569-
_wrapError(e.getMessage(), e);
570-
571-
// [dataformats-binary#420]: IonJava leaks IOOBEs so:
578+
return _reportCorruptContent(e);
579+
// [dataformats-binary#420]: IonJava leaks IOOBEs so:
572580
} catch (IndexOutOfBoundsException e) {
573-
_wrapError(String.format("Corrupt content to decode; underlying failure: (%s) %s",
574-
e.getClass().getName(), e.getMessage()),
575-
e);
581+
return _reportCorruptContent(e);
576582
}
577583
if (type == null) {
578584
if (_parsingContext.inRoot()) { // EOF?
@@ -589,13 +595,15 @@ public JsonToken nextToken() throws IOException
589595
boolean inStruct = !_parsingContext.inRoot() && _reader.isInStruct();
590596
// (isInStruct can return true for the first value read if the reader
591597
// was created from an IonValue that has a parent container)
598+
final String name;
592599
try {
593600
// getFieldName() can throw an UnknownSymbolException if the text of the
594601
// field name symbol cannot be resolved.
595-
_parsingContext.setCurrentName(inStruct ? _reader.getFieldName() : null);
596-
} catch (UnknownSymbolException e) {
597-
_wrapError(e.getMessage(), e);
602+
name = inStruct ? _reader.getFieldName() : null;
603+
} catch (IonException e) {
604+
return _reportCorruptContent(e);
598605
}
606+
_parsingContext.setCurrentName(name);
599607
JsonToken t = _tokenFromType(type);
600608
// and return either field name first
601609
if (inStruct) {
@@ -709,6 +717,20 @@ protected void _handleEOF() throws JsonParseException
709717
}
710718
}
711719

720+
private <T> T _reportCorruptContent(Exception e) throws IOException
721+
{
722+
final String msg = String.format("Corrupt content to decode; underlying failure: (%s) %s",
723+
e.getClass().getName(), e.getMessage());
724+
throw _constructError(msg, e);
725+
}
726+
727+
private <T> T _reportCorruptNumber(Exception e) throws IOException
728+
{
729+
final String msg = String.format("Corrupt Number value to decode; underlying failure: (%s) %s",
730+
e.getClass().getName(), e.getMessage());
731+
throw _constructError(msg, e);
732+
}
733+
712734
@Override
713735
public void overrideCurrentName(String name) {
714736
try {

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/fuzz/Fuzz424_65065_65126NPETest.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,25 @@
1414
// [dataformats-binary#424]
1515
public class Fuzz424_65065_65126NPETest
1616
{
17+
private final IonObjectMapper MAPPER = IonObjectMapper.builder().build();
18+
1719
@Test
1820
public void testFuzz65065() throws Exception {
19-
IonFactory f = IonFactory
20-
.builderForBinaryWriters()
21-
.build();
22-
23-
IonObjectMapper mapper = IonObjectMapper.builder(f).build();
24-
2521
try {
2622
byte[] bytes = {(byte) -32, (byte) 1, (byte) 0, (byte) -22, (byte) 123, (byte) -112};
27-
mapper.readTree(f.createParser(new ByteArrayInputStream(bytes)));
23+
MAPPER.readTree(new ByteArrayInputStream(bytes));
2824
fail("Should not pass (invalid content)");
2925
} catch (StreamReadException e) {
26+
e.printStackTrace();
3027
assertThat(e.getMessage(), Matchers.containsString("Internal `IonReader` error"));
3128
}
3229
}
3330

3431
@Test
3532
public void testFuzz65126() throws Exception {
36-
IonFactory f = IonFactory
37-
.builderForBinaryWriters()
38-
.build();
39-
4033
try {
4134
byte[] bytes = {(byte) 1, (byte) 0};
42-
f.createParser(bytes).getDecimalValue();
35+
MAPPER.createParser(bytes).getDecimalValue();
4336
fail("Should not pass (invalid content)");
4437
} catch (StreamReadException e) {
4538
assertThat(e.getMessage(), Matchers.containsString("Current token (null) not numeric"));
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.fasterxml.jackson.dataformat.ion.fuzz;
2+
3+
import java.io.InputStream;
4+
5+
import org.hamcrest.Matchers;
6+
import org.junit.Test;
7+
8+
import com.fasterxml.jackson.core.JsonParser;
9+
import com.fasterxml.jackson.core.JsonToken;
10+
import com.fasterxml.jackson.core.exc.StreamReadException;
11+
import com.fasterxml.jackson.dataformat.ion.*;
12+
13+
import static org.hamcrest.MatcherAssert.assertThat;
14+
import static org.junit.Assert.assertEquals;
15+
import static org.junit.Assert.fail;
16+
17+
// https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65062
18+
public class Fuzz_65062_VarintTest
19+
{
20+
final IonObjectMapper MAPPER = IonObjectMapper.builder().build();
21+
22+
@Test
23+
public void testFuzz65062_Varint() throws Exception {
24+
try (InputStream in = getClass().getResourceAsStream("/data/fuzz-65062.ion")) {
25+
try (JsonParser p = MAPPER.createParser(in)) {
26+
assertEquals(JsonToken.START_ARRAY, p.nextToken());
27+
28+
while (p.nextToken() == JsonToken.VALUE_NUMBER_FLOAT) {
29+
p.getDecimalValue();
30+
}
31+
assertEquals(JsonToken.END_ARRAY, p.nextToken());
32+
}
33+
fail("Should not pass (invalid content)");
34+
} catch (StreamReadException e) {
35+
// 21-Dec-2023, tatu: Not 100% sure why we won't get Number-specific fail but:
36+
assertThat(e.getMessage(), Matchers.containsString("Corrupt content to decode; underlying failure"));
37+
}
38+
}
39+
}
103 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)