Skip to content

Commit bf8d729

Browse files
authored
Fixed #434: Add null check before accessing integer size (#435)
1 parent 80ae368 commit bf8d729

File tree

7 files changed

+110
-20
lines changed

7 files changed

+110
-20
lines changed

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

+38-18
Original file line numberDiff line numberDiff line change
@@ -384,27 +384,47 @@ private void _verifyIsNumberToken() throws IOException
384384
@Override
385385
public NumberType getNumberType() throws IOException
386386
{
387-
IonType type = _reader.getType();
388-
if (type != null) {
389-
// Hmmh. Looks like Ion gives little bit looser definition here;
390-
// harder to pin down exact type. But let's try some checks still.
391-
switch (type) {
392-
case DECIMAL:
393-
//Ion decimals can be arbitrary precision, need to read as big decimal
394-
return NumberType.BIG_DECIMAL;
395-
case INT:
396-
IntegerSize size = _reader.getIntegerSize();
397-
switch (size) {
387+
if (_currToken == JsonToken.VALUE_NUMBER_INT
388+
|| _currToken == JsonToken.VALUE_NUMBER_FLOAT
389+
// 30-Dec-2023, tatu: This is odd, but some current tests seem to
390+
// expect this case to work when creating `IonParser` from `IonReader`,
391+
// which does not seem to work without work-around like this:
392+
|| ((_currToken == null) && !isClosed())) {
393+
IonType type = _reader.getType();
394+
if (type != null) {
395+
// Hmmh. Looks like Ion gives little bit looser definition here;
396+
// harder to pin down exact type. But let's try some checks still.
397+
switch (type) {
398+
case DECIMAL:
399+
//Ion decimals can be arbitrary precision, need to read as big decimal
400+
return NumberType.BIG_DECIMAL;
398401
case INT:
399-
return NumberType.INT;
400-
case LONG:
401-
return NumberType.LONG;
402+
final IntegerSize size;
403+
// [dataformats-binary#434]: another problem with corrupt data handling.
404+
// Temporary measure until this bug fixing is merged and published
405+
// https://github.com/amazon-ion/ion-java/issues/685
406+
try {
407+
size = _reader.getIntegerSize();
408+
} catch (IonException e) {
409+
return _reportCorruptNumber(e);
410+
} catch (NullPointerException e) {
411+
return _reportCorruptContent(e);
412+
}
413+
if (size == null) {
414+
_reportError("Current token (%s) not integer", _currToken);
415+
}
416+
switch (size) {
417+
case INT:
418+
return NumberType.INT;
419+
case LONG:
420+
return NumberType.LONG;
421+
default:
422+
return NumberType.BIG_INTEGER;
423+
}
424+
case FLOAT:
425+
return NumberType.DOUBLE;
402426
default:
403-
return NumberType.BIG_INTEGER;
404427
}
405-
case FLOAT:
406-
return NumberType.DOUBLE;
407-
default:
408428
}
409429
}
410430
return null;

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/IonParserTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ public void testFloatType() throws IOException {
9393
reader.stepIn();
9494
// Step next.
9595
reader.next();
96+
// 30-Dec-2023, tatu: This is problematic as created parser is expected
97+
// to point to `JsonToken.VALUE_NUMBER_FLOAT`, but `createParser()`
98+
// does not initialize state. For now, `IonParser.getNumberType()` has
99+
// special handling allowing this case but that should not be needed
96100
final IonParser floatParser = new IonFactory().createParser(reader);
97101
Assert.assertEquals(JsonParser.NumberType.DOUBLE, floatParser.getNumberType());
98102
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.fasterxml.jackson.dataformat.ion.fuzz;
2+
3+
import java.io.*;
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.databind.ObjectMapper;
12+
import com.fasterxml.jackson.dataformat.ion.*;
13+
14+
import static org.hamcrest.MatcherAssert.assertThat;
15+
import static org.junit.Assert.assertEquals;
16+
import static org.junit.Assert.assertNull;
17+
import static org.junit.Assert.fail;
18+
19+
// [dataformats-binary#434]
20+
public class Fuzz434_65268_65274_NPETest
21+
{
22+
private final ObjectMapper ION_MAPPER = new IonObjectMapper();
23+
24+
// Test that used to fail on "getNumberType()" for `JsonToken.VALUE_NULL`
25+
@Test
26+
public void testFuzz65268() throws Exception {
27+
try (InputStream in = getClass().getResourceAsStream("/data/fuzz-65268.ion")) {
28+
try (JsonParser p = ION_MAPPER.createParser(in)) {
29+
assertEquals(JsonToken.VALUE_STRING, p.nextToken());
30+
p.getText();
31+
assertNull(p.nextTextValue());
32+
assertEquals(JsonToken.VALUE_NULL, p.currentToken());
33+
assertNull(p.getNumberType());
34+
}
35+
}
36+
}
37+
38+
@Test
39+
public void testFuzz65274Malformed() throws Exception {
40+
try (InputStream in = getClass().getResourceAsStream("/data/fuzz-65274.ion")) {
41+
byte[] invalid = new byte[in.available()];
42+
new DataInputStream(in).readFully(invalid);
43+
ION_MAPPER.readTree(new ByteArrayInputStream(invalid));
44+
fail("Should not pass (invalid content)");
45+
} catch (StreamReadException e) {
46+
assertThat(e.getMessage(), Matchers.containsString("Corrupt content to decode"));
47+
}
48+
}
49+
50+
@Test
51+
public void testFuzz65274Eof() throws Exception {
52+
try (InputStream in = getClass().getResourceAsStream("/data/fuzz-65274.ion")) {
53+
ION_MAPPER.readTree(in);
54+
fail("Should not pass (invalid content)");
55+
} catch (StreamReadException e) {
56+
assertThat(e.getMessage(), Matchers.containsString("Corrupt Number value to decode"));
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
n
2+
3+
null.int����~���ttttt(�t�740���������n����66}tt
5.09 KB
Binary file not shown.

release-notes/CREDITS-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,5 @@ Arthur Chan (@arthurscchan)
295295
* Contributed #432 (ion) More methods from `IonReader` could throw an unexpected
296296
`AssertionError`
297297
(2.17.0)
298+
* Contributed #434 (ion) Unexpected `NullPointerException` thrown from `IonParser::getNumberType()`
299+
(2.17.0)

release-notes/VERSION-2.x

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ Active maintainers:
2525
#424: (ion) `IonReader` throws `NullPointerException` for unchecked invalid data
2626
(fix contributed by Arthur C)
2727
#426: (smile) `SmileParser` throws unexpected IOOBE for corrupt content
28-
(fix contributed by Arthur C)
28+
(fix contributed by Arthur C)-(
2929
#432: (ion) More methods from `IonReader` could throw an unexpected `AssertionError`
3030
(fix contributed by Arthur C)
31-
-(ion) Update `com.amazon.ion:ion-java` to 1.11.0 (from 1.10.5)
31+
#434 (ion) Unexpected `NullPointerException` thrown from `IonParser::getNumberType()`
32+
(fix contributed by Arthur C)
33+
- (ion) Update `com.amazon.ion:ion-java` to 1.11.0 (from 1.10.5)
3234

3335
2.16.1 (24-Dec-2023)
3436

0 commit comments

Comments
 (0)