diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index d41734922a..72dda57f06 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -155,4 +155,7 @@ Doug Roper (htmldoug@github) * Suggested #463: Ensure that `skipChildren()` of non-blocking `JsonParser` will throw exception if not enough input (2.9.6) - + +Alexander Eyers-Taylor (aeyerstaylor@github) + * Reported #510: Fix ArrayIndexOutofBoundsException found by LGTM.com + (2.9.9) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 5145925401..ac205bf817 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -18,6 +18,8 @@ JSON library. #488: Fail earlier on coercions from "too big" `BigInteger` into fixed-size types (`int`, `long`, `short`) +#510: Fix ArrayIndexOutofBoundsException found by LGTM.com + (reported by Alexander E-T) - Improve exception message for missing Base64 padding (see databind#2183) 2.9.7 (19-Sep-2018) diff --git a/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java index 2c1f5a2303..f38e4aaedb 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java @@ -1960,7 +1960,7 @@ private String _handleOddName2(int startPtr, int hash, int[] codes) throws IOExc } char c = _inputBuffer[_inputPtr]; int i = (int) c; - if (i <= maxCode) { + if (i < maxCode) { if (codes[i] != 0) { break; } diff --git a/src/test/java/com/fasterxml/jackson/core/read/NonStandardUnquotedNamesTest.java b/src/test/java/com/fasterxml/jackson/core/read/NonStandardUnquotedNamesTest.java index d88d58856a..1aa75fff54 100644 --- a/src/test/java/com/fasterxml/jackson/core/read/NonStandardUnquotedNamesTest.java +++ b/src/test/java/com/fasterxml/jackson/core/read/NonStandardUnquotedNamesTest.java @@ -1,12 +1,18 @@ package com.fasterxml.jackson.core.read; import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; public class NonStandardUnquotedNamesTest extends com.fasterxml.jackson.core.BaseTest { + private final JsonFactory UNQUOTED_FIELDS_F = new JsonFactory(); + { + UNQUOTED_FIELDS_F.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + } + public void testSimpleUnquotedBytes() throws Exception { _testSimpleUnquoted(MODE_INPUT_STREAM); _testSimpleUnquoted(MODE_INPUT_STREAM_THROTTLED); @@ -16,7 +22,7 @@ public void testSimpleUnquotedBytes() throws Exception { public void testSimpleUnquotedChars() throws Exception { _testSimpleUnquoted(MODE_READER); } - + public void testLargeUnquoted() throws Exception { _testLargeUnquoted(MODE_INPUT_STREAM); @@ -25,12 +31,35 @@ public void testLargeUnquoted() throws Exception _testLargeUnquoted(MODE_READER); } + // [core#510]: ArrayIndexOutOfBounds + public void testUnquotedIssue510() throws Exception + { + // NOTE! Requires longer input buffer to trigger longer codepath + char[] fullChars = new char[4001]; + for (int i = 0; i < 3998; i++) { + fullChars[i] = ' '; + } + fullChars[3998] = '{'; + fullChars[3999] = 'a'; + fullChars[4000] = 256; + + JsonParser p = UNQUOTED_FIELDS_F.createParser(new java.io.StringReader(new String(fullChars))); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + try { + p.nextToken(); + fail("Should not pass"); + } catch (JsonParseException e) { + ; // should fail here + } + p.close(); + } + /* /**************************************************************** /* Secondary test methods /**************************************************************** */ - + private void _testLargeUnquoted(int mode) throws Exception { StringBuilder sb = new StringBuilder(5000); @@ -51,9 +80,7 @@ private void _testLargeUnquoted(int mode) throws Exception } sb.append("]"); String JSON = sb.toString(); - JsonFactory f = new JsonFactory(); - f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - JsonParser p = createParser(f, mode, JSON); + JsonParser p = createParser(UNQUOTED_FIELDS_F, mode, JSON); assertToken(JsonToken.START_ARRAY, p.nextToken()); for (int i = 0; i < REPS; ++i) { assertToken(JsonToken.START_OBJECT, p.nextToken()); @@ -68,11 +95,8 @@ private void _testLargeUnquoted(int mode) throws Exception private void _testSimpleUnquoted(int mode) throws Exception { - final JsonFactory f = new JsonFactory(); - f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - String JSON = "{ a : 1, _foo:true, $:\"money!\", \" \":null }"; - JsonParser p = createParser(f, mode, JSON); + JsonParser p = createParser(UNQUOTED_FIELDS_F, mode, JSON); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); @@ -98,7 +122,7 @@ private void _testSimpleUnquoted(int mode) throws Exception // Another thing, as per [Issue#102]: numbers JSON = "{ 123:true,4:false }"; - p = createParser(f, mode, JSON); + p = createParser(UNQUOTED_FIELDS_F, mode, JSON); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken());