Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndexOutOfBoundsException in JacksonAvroParserImpl for invalid input #449

Closed
arthurscchan opened this issue Jan 8, 2024 · 0 comments
Closed
Milestone

Comments

@arthurscchan
Copy link
Contributor

arthurscchan commented Jan 8, 2024

In the JacksonAvroParserImpl::_finishShortText(int) method, there is a missing bound check-in handling the value reading from the byte array inputBuf and could cause unexpected IndexOutOfBoundsException if the provided input is not correctly ended.

In the first line of the do..while loop, the current index pointed by the inPtr variable is retrieved, processed and stored. Then the inPtr value is increased by one. From the study of the code, the value of inPtr must be within the range of the byte array inputBuf, but since it has increased by one in this line, the value of inPtr may be larger or equals to the length of inputBuf on some invalid input. This causes the subsequent inputBuf value access with the out-of-bound inPtr to throw an unexpected IndexOutOfBoundsException.

...
        final int[] codes = sUtf8UnitLengths;
        do {
            i = inputBuf[inPtr++] & 0xFF;
            switch (codes[i]) {
            case 0:
                break;
            case 1:
                i = ((i & 0x1F) << 6) | (inputBuf[inPtr++] & 0x3F);
                break;
            case 2:
                i = ((i & 0x0F) << 12)
                   | ((inputBuf[inPtr++] & 0x3F) << 6)
                   | (inputBuf[inPtr++] & 0x3F);
                break;
            case 3:
                i = ((i & 0x07) << 18)
                 | ((inputBuf[inPtr++] & 0x3F) << 12)
                 | ((inputBuf[inPtr++] & 0x3F) << 6)
                 | (inputBuf[inPtr++] & 0x3F);
                // note: this is the codepoint value; need to split, too
                i -= 0x10000;
                outBuf[outPtr++] = (char) (0xD800 | (i >> 10));
                i = 0xDC00 | (i & 0x3FF);
                break;
            default: // invalid
                _reportError("Invalid byte "+Integer.toHexString(i)+" in Unicode text block");
            }
            outBuf[outPtr++] = (char) i;
        } while (inPtr < end);
        return _textBuffer.setCurrentAndReturn(outPtr);
...

Similar problem happened in JacksonAvroParserImpl::_finishLongText(int) method.

    private final void _finishLongText(int len) throws IOException
...
            case 3: // 4-byte UTF
                c = _decodeUTF8_4(c);
                // Let's add first part right away:
                outBuf[outPtr++] = (char) (0xD800 | (c >> 10));

The suggested fix is to add a bound checking in the do..while loop after the inPtr++ process to ensure the inPtr is still within bound and throws an error if not for identifying invalid input.

We found this issue by OSS-Fuzz and it is reported in https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65618 and We found this issue by OSS-Fuzz and it is reported in https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65649.

@cowtowncoder cowtowncoder changed the title Unexpected IndexOutOfBoundsException in JacksonAvroParserImpl for invalid input Unexpected IndexOutOfBoundsException in JacksonAvroParserImpl for invalid input Jan 9, 2024
@cowtowncoder cowtowncoder changed the title Unexpected IndexOutOfBoundsException in JacksonAvroParserImpl for invalid input IndexOutOfBoundsException in JacksonAvroParserImpl for invalid input Jan 9, 2024
@cowtowncoder cowtowncoder added this to the 2.17.0 milestone Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants