Skip to content

Commit f0445ad

Browse files
authored
Fixes for 449: Unexpected IOOBE handling (#450)
1 parent 041d619 commit f0445ad

File tree

4 files changed

+66
-7
lines changed

4 files changed

+66
-7
lines changed

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/deser/JacksonAvroParserImpl.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,8 @@ private final String _finishShortText(int len) throws IOException
614614
_inputPtr += len;
615615
final byte[] inputBuf = _inputBuffer;
616616

617-
// Let's actually do a tight loop for ASCII first:
618617
final int end = inPtr + len;
619-
618+
// Let's actually do a tight loop for ASCII first:
620619
int i;
621620
while ((i = inputBuf[inPtr]) >= 0) {
622621
outBuf[outPtr++] = (char) i;
@@ -628,9 +627,18 @@ private final String _finishShortText(int len) throws IOException
628627
final int[] codes = sUtf8UnitLengths;
629628
do {
630629
i = inputBuf[inPtr++] & 0xFF;
631-
switch (codes[i]) {
632-
case 0:
633-
break;
630+
final int code = codes[i];
631+
if (code == 0) { // still optimized for ASCII
632+
outBuf[outPtr++] = (char) i;
633+
continue;
634+
}
635+
if ((inPtr + code) > end) {
636+
if (code < 4) {
637+
throw _constructError(String.format(
638+
"Malformed %d-byte UTF-8 character at the end of Unicode text block", code));
639+
}
640+
}
641+
switch (code) {
634642
case 1:
635643
i = ((i & 0x1F) << 6) | (inputBuf[inPtr++] & 0x3F);
636644
break;
@@ -650,7 +658,7 @@ private final String _finishShortText(int len) throws IOException
650658
i = 0xDC00 | (i & 0x3FF);
651659
break;
652660
default: // invalid
653-
_reportError("Invalid byte "+Integer.toHexString(i)+" in Unicode text block");
661+
_reportError(String.format("Invalid byte 0x2X in Unicode text block", i));
654662
}
655663
outBuf[outPtr++] = (char) i;
656664
} while (inPtr < end);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.fasterxml.jackson.dataformat.avro.fuzz;
2+
3+
import org.junit.Test;
4+
5+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
6+
import com.fasterxml.jackson.core.JsonToken;
7+
import com.fasterxml.jackson.core.exc.StreamReadException;
8+
import com.fasterxml.jackson.dataformat.avro.AvroFactory;
9+
import com.fasterxml.jackson.dataformat.avro.AvroMapper;
10+
import com.fasterxml.jackson.dataformat.avro.AvroParser;
11+
import com.fasterxml.jackson.dataformat.avro.AvroSchema;
12+
import com.fasterxml.jackson.dataformat.avro.AvroTestBase;
13+
14+
// [dataformats-binary#449]
15+
public class AvroFuzz449_65618_IOOBETest extends AvroTestBase
16+
{
17+
@JsonPropertyOrder({ "name", "value" })
18+
static class RootType {
19+
public String name;
20+
public int value;
21+
}
22+
23+
@Test
24+
public void testFuzz65618IOOBE() throws Exception {
25+
final AvroFactory factory = AvroFactory.builderWithApacheDecoder().build();
26+
final AvroMapper mapper = new AvroMapper(factory);
27+
28+
final byte[] doc = {
29+
(byte) 2, (byte) 22, (byte) 36, (byte) 2, (byte) 0,
30+
(byte) 0, (byte) 8, (byte) 3, (byte) 3, (byte) 3,
31+
(byte) 122, (byte) 3, (byte) -24
32+
};
33+
34+
final AvroSchema schema = mapper.schemaFor(RootType.class);
35+
try (AvroParser p = factory.createParser(doc)) {
36+
p.setSchema(schema);
37+
assertToken(JsonToken.START_OBJECT, p.nextToken());
38+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
39+
p.nextToken();
40+
fail("Should not pass (invalid content)");
41+
} catch (StreamReadException e) {
42+
verifyException(e, "Malformed 2-byte UTF-8 character at the end of");
43+
}
44+
}
45+
}

release-notes/CREDITS-2.x

+5-1
Original file line numberDiff line numberDiff line change
@@ -295,5 +295,9 @@ 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()`
298+
* Contributed #434: (ion) Unexpected `NullPointerException` thrown from
299+
`IonParser::getNumberType()`
300+
(2.17.0)
301+
* Contributed #449: (avro) `IndexOutOfBoundsException` in `JacksonAvroParserImpl`
302+
for invalid input
299303
(2.17.0)

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Active maintainers:
3131
#434 (ion) Unexpected `NullPointerException` thrown from `IonParser::getNumberType()`
3232
(fix contributed by Arthur C)
3333
#437 (ion) `IonReader.next()` throws NPEs for some invalid content
34+
#449 (avro) `IndexOutOfBoundsException` in `JacksonAvroParserImpl` for invalid input
35+
(fix contributed by Arthur C)
3436
- (ion) Update `com.amazon.ion:ion-java` to 1.11.0 (from 1.10.5)
3537

3638
2.16.1 (24-Dec-2023)

0 commit comments

Comments
 (0)