Skip to content

Commit

Permalink
Fix #692
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Mar 25, 2021
1 parent 8a2036e commit f348880
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 20 deletions.
5 changes: 5 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,8 @@ Jonathan Haber (jhaber@github)
Ferenc Csaky (ferenc-csaky@github)
* Contributed #677: Introduce O(n^1.5) BigDecimal parser implementation
(2.13.0)

Fabian Meumertzheim (fmeum@github)
* Reported #692: UTF32Reader ArrayIndexOutOfBoundsException
(2.13.0)

2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ JSON library.
(contributed by Ferenc C)
#687: ByteQuadsCanonicalizer.addName(String, int, int) has incorrect handling
for case of q2 == null
#692: UTF32Reader ArrayIndexOutOfBoundsException
(reported by Fabian M)

2.12.2 (03-Mar-2021)
2.12.1 (08-Jan-2021)
Expand Down
29 changes: 13 additions & 16 deletions src/main/java/com/fasterxml/jackson/core/io/UTF32Reader.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ public class UTF32Reader extends Reader
* to the same as xml (to basically limit UTF-8 max byte sequence
* length to 4)
*/
final protected static int LAST_VALID_UNICODE_CHAR = 0x10FFFF;
protected final static int LAST_VALID_UNICODE_CHAR = 0x10FFFF;

final protected static char NC = (char) 0;
protected final static char NC = (char) 0;

final protected IOContext _context;
protected final IOContext _context;

protected InputStream _in;

Expand Down Expand Up @@ -47,7 +47,7 @@ public class UTF32Reader extends Reader
protected int _byteCount;

protected final boolean _managedBuffers;

/*
/**********************************************************
/* Life-cycle
Expand Down Expand Up @@ -100,7 +100,8 @@ public int read() throws IOException {
}

@Override
public int read(char[] cbuf, int start, int len) throws IOException {
public int read(char[] cbuf, int start, int len) throws IOException
{
// Already EOF?
if (_buffer == null) { return -1; }
if (len < 1) { return len; }
Expand Down Expand Up @@ -136,7 +137,7 @@ public int read(char[] cbuf, int start, int len) throws IOException {
final int lastValidInputStart = (_length - 4);

main_loop:
while (outPtr < outEnd) {
while ((outPtr < outEnd) && (_ptr <= lastValidInputStart)) {
int ptr = _ptr;
int hi, lo;

Expand Down Expand Up @@ -168,9 +169,6 @@ public int read(char[] cbuf, int start, int len) throws IOException {
}
}
cbuf[outPtr++] = (char) lo;
if (_ptr > lastValidInputStart) {
break main_loop;
}
}
int actualLen = (outPtr - start);
_charCount += actualLen;
Expand Down Expand Up @@ -212,9 +210,8 @@ private boolean loadMore(int available) throws IOException {
}
_length = available;
} else {
/* Ok; here we can actually reasonably expect an EOF,
* so let's do a separate read right away:
*/
// Ok; here we can actually reasonably expect an EOF,
// so let's do a separate read right away:
_ptr = 0;
int count = (_in == null) ? -1 : _in.read(_buffer);
if (count < 1) {
Expand All @@ -231,9 +228,7 @@ private boolean loadMore(int available) throws IOException {
_length = count;
}

/* Need at least 4 bytes; if we don't get that many, it's an
* error.
*/
// Need at least 4 bytes; if we don't get that many, it's an error.
while (_length < 4) {
int count = (_in == null) ? -1 : _in.read(_buffer, _length, _buffer.length - _length);
if (count < 1) {
Expand All @@ -260,7 +255,9 @@ private void freeBuffers() {
byte[] buf = _buffer;
if (buf != null) {
_buffer = null;
_context.releaseReadIOBuffer(buf);
if (_context != null) { // tests pass null
_context.releaseReadIOBuffer(buf);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,74 @@
package com.fasterxml.jackson.core.fuzz;

import java.io.CharConversionException;
import java.io.InputStream;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.UTF32Reader;
import com.fasterxml.jackson.core.testsupport.ThrottledInputStream;

// Trying to repro: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=32216
// but so far without success (fails on seemingly legit validation problem)
public class Fuzz32208UTF32ParseTest extends BaseTest
{
public void testFuzz32208() throws Exception
private final byte[] DOC = readResource("/data/fuzz-json-utf32-32208.json");

public void testFuzz32208ViaParser() throws Exception
{
final JsonFactory f = new JsonFactory();
final byte[] doc = readResource("/data/fuzz-json-utf32-32208.json");

JsonParser p = f.createParser(/*ObjectReadContext.empty(), */ doc);
JsonParser p = f.createParser(/*ObjectReadContext.empty(), */ DOC);
try {
assertToken(JsonToken.VALUE_STRING, p.nextToken());
String text = p.getText();
fail("Should not have passed; got text with length of: "+text.length());
} catch (CharConversionException e) {
//e.printStackTrace();
verifyException(e, "Invalid UTF-32 character ");
}
p.close();
}

// How about through UTF32Reader itself?
public void testFuzz32208Direct() throws Exception
{
_testFuzz32208Direct(1);
_testFuzz32208Direct(2);
_testFuzz32208Direct(3);
_testFuzz32208Direct(7);
_testFuzz32208Direct(13);
_testFuzz32208Direct(67);
_testFuzz32208Direct(111);
_testFuzz32208Direct(337);
_testFuzz32208Direct(991);
}

private void _testFuzz32208Direct(int readSize) throws Exception
{
InputStream in = new ThrottledInputStream(DOC, readSize);
// apparently input is NOT big-endian so:
UTF32Reader r = new UTF32Reader(null, in, new byte[500], 0, 0, false);

int count = 0;
int ch;

try {
final char[] chunkBuffer = new char[19];

while (true) {
ch = r.read(chunkBuffer);
if (ch == -1) {
break;
}
if (ch == 0) {
fail("Received 0 chars; broken reader");
}
count += ch;
}
fail("Should have failed, got all "+count+" characters, last 0x"+Integer.toHexString(ch));
} catch (CharConversionException e) {
verifyException(e, "Invalid UTF-32 character ");
}

r.close();
}
}

0 comments on commit f348880

Please sign in to comment.