Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/tools/jackson/core/base/ParserMinimalBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,10 @@ public boolean nextName(SerializableString str) throws JacksonException {
public int nextNameMatch(PropertyNameMatcher matcher) throws JacksonException {
String str = nextName();
if (str != null) {
// 18-Mar-2026, tatu: [databind#5811] Guard against null matcher
if (matcher == null) {
return PropertyNameMatcher.MATCH_UNKNOWN_NAME;
}
return matcher.matchName(str);
}
if (_currToken == JsonToken.END_OBJECT) {
Expand All @@ -495,6 +499,10 @@ public int nextNameMatch(PropertyNameMatcher matcher) throws JacksonException {
@Override
public int currentNameMatch(PropertyNameMatcher matcher) {
if (_currToken == JsonToken.PROPERTY_NAME) {
// 18-Mar-2026, tatu: [databind#5811] Guard against null matcher
if (matcher == null) {
return PropertyNameMatcher.MATCH_UNKNOWN_NAME;
}
return matcher.matchName(currentName());
}
if (_currToken == JsonToken.END_OBJECT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,10 @@ public int nextNameMatch(PropertyNameMatcher matcher) throws JacksonException {
String str = nextName();
if (str != null) {
// 15-Nov-2017, tatu: We cannot rely on name being interned here
// 18-Mar-2026, tatu: [databind#5811] Guard against null matcher
if (matcher == null) {
return PropertyNameMatcher.MATCH_UNKNOWN_NAME;
}
return matcher.matchName(str);
}
if (hasToken(JsonToken.END_OBJECT)) {
Expand Down
31 changes: 19 additions & 12 deletions src/main/java/tools/jackson/core/json/UTF8StreamJsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -1163,20 +1163,27 @@ public int nextNameMatch(PropertyNameMatcher matcher) throws JacksonException
_updateNameLocation();

String name;
int match = _matchName(matcher, i);
if (match >= 0) { // gotcha! (expected case)
_inputPtr = _quadPtr;
name = matcher.nameLookup()[match];
// 18-Mar-2026, tatu: [databind#5811] Guard against null matcher
int match;
if (matcher == null) {
name = _parseName(i);
match = PropertyNameMatcher.MATCH_UNKNOWN_NAME;
} else {
// !!! TODO 12-Dec-2017, tatu: Should probably try to use symbol table
// for cases where quads were decoded ok, but no match?
/*
if (match == PropertyNameMatcher.MATCH_UNKNOWN_NAME) {
throw new RuntimeException("No name match!");
match = _matchName(matcher, i);
if (match >= 0) { // gotcha! (expected case)
_inputPtr = _quadPtr;
name = matcher.nameLookup()[match];
} else {
// !!! TODO 12-Dec-2017, tatu: Should probably try to use symbol table
// for cases where quads were decoded ok, but no match?
/*
if (match == PropertyNameMatcher.MATCH_UNKNOWN_NAME) {
throw new RuntimeException("No name match!");
}
*/
name = _parseName(i);
match = matcher.matchName(name);
}
*/
name = _parseName(i);
match = matcher.matchName(name);
}

_streamReadContext.setCurrentName(name);
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/tools/jackson/core/util/JsonParserSequence.java
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ public int nextNameMatch(PropertyNameMatcher matcher) throws JacksonException {
String str = nextName();
if (str != null) {
// 15-Nov-2017, tatu: Cannot assume intern()ing aspects when delegating...
// 18-Mar-2026, tatu: [databind#5811] Guard against null matcher
if (matcher == null) {
return PropertyNameMatcher.MATCH_UNKNOWN_NAME;
}
return matcher.matchName(str);
}
if (hasToken(JsonToken.END_OBJECT)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.*;

import org.junit.jupiter.api.Test;

import tools.jackson.core.JsonParser;
import tools.jackson.core.JsonToken;
import tools.jackson.core.json.JsonFactory;
Expand Down Expand Up @@ -32,6 +34,7 @@ public class NextNameWithMatcherTest
private final String DOC_1_CASE_MISMATCH = a2q(
"{ 'A' : 4, 'ENABLED' : true, 'LongerName' : 'Billy-Bob Burger', 'extra' : [0 ], 'otherStuff3' : 0.25 }");

@Test
public void testSimpleCaseSensitive() throws Exception
{
_testSimpleCaseSensitive(MODE_INPUT_STREAM);
Expand All @@ -45,6 +48,7 @@ private void _testSimpleCaseSensitive(int mode) throws Exception
_verifyDoc1(createParser(mode, DOC_1), MATCHER_CS_1, NAMES_1);
}

@Test
public void testSimpleCaseInsensitive() throws Exception
{
_testSimpleCaseInsensitive(MODE_INPUT_STREAM);
Expand All @@ -61,6 +65,81 @@ public void _testSimpleCaseInsensitive(int mode) throws Exception
_verifyDoc1(createParser(mode, DOC_1_CASE_MISMATCH), MATCHER_CI_1, NAMES_1_CASE_MISMATCH);
}

// [databind#5811] Guard against null PropertyNameMatcher in nextNameMatch/currentNameMatch
@Test
public void testNullMatcherNextNameMatch() throws Exception
{
_testNullMatcherNextNameMatch(MODE_INPUT_STREAM);
_testNullMatcherNextNameMatch(MODE_INPUT_STREAM_THROTTLED);
_testNullMatcherNextNameMatch(MODE_DATA_INPUT);
_testNullMatcherNextNameMatch(MODE_READER);
}

private void _testNullMatcherNextNameMatch(int mode) throws Exception
{
final String doc = a2q("{ 'a' : 1, 'b' : 2 }");
try (JsonParser p = createParser(mode, doc)) {
// START_OBJECT is not a name token -> MATCH_ODD_TOKEN
assertEquals(PropertyNameMatcher.MATCH_ODD_TOKEN, p.nextNameMatch(null));
assertToken(JsonToken.START_OBJECT, p.currentToken());

// property name 'a' -> MATCH_UNKNOWN_NAME (null matcher can't match anything)
assertEquals(PropertyNameMatcher.MATCH_UNKNOWN_NAME, p.nextNameMatch(null));
assertToken(JsonToken.PROPERTY_NAME, p.currentToken());
assertEquals("a", p.currentName());

// value '1' -> MATCH_ODD_TOKEN
assertEquals(PropertyNameMatcher.MATCH_ODD_TOKEN, p.nextNameMatch(null));
assertToken(JsonToken.VALUE_NUMBER_INT, p.currentToken());

// property name 'b' -> MATCH_UNKNOWN_NAME
assertEquals(PropertyNameMatcher.MATCH_UNKNOWN_NAME, p.nextNameMatch(null));
assertToken(JsonToken.PROPERTY_NAME, p.currentToken());
assertEquals("b", p.currentName());

// value '2' -> MATCH_ODD_TOKEN
assertEquals(PropertyNameMatcher.MATCH_ODD_TOKEN, p.nextNameMatch(null));
assertToken(JsonToken.VALUE_NUMBER_INT, p.currentToken());

// END_OBJECT -> MATCH_END_OBJECT
assertEquals(PropertyNameMatcher.MATCH_END_OBJECT, p.nextNameMatch(null));
assertToken(JsonToken.END_OBJECT, p.currentToken());
}
}

// [databind#5811] Guard against null PropertyNameMatcher in currentNameMatch
@Test
public void testNullMatcherCurrentNameMatch() throws Exception
{
_testNullMatcherCurrentNameMatch(MODE_INPUT_STREAM);
_testNullMatcherCurrentNameMatch(MODE_INPUT_STREAM_THROTTLED);
_testNullMatcherCurrentNameMatch(MODE_DATA_INPUT);
_testNullMatcherCurrentNameMatch(MODE_READER);
}

private void _testNullMatcherCurrentNameMatch(int mode) throws Exception
{
final String doc = a2q("{ 'a' : 1 }");
try (JsonParser p = createParser(mode, doc)) {
assertToken(JsonToken.START_OBJECT, p.nextToken());
// At START_OBJECT -> MATCH_ODD_TOKEN
assertEquals(PropertyNameMatcher.MATCH_ODD_TOKEN, p.currentNameMatch(null));

assertToken(JsonToken.PROPERTY_NAME, p.nextToken());
// At PROPERTY_NAME -> MATCH_UNKNOWN_NAME (null matcher can't match)
assertEquals(PropertyNameMatcher.MATCH_UNKNOWN_NAME, p.currentNameMatch(null));
assertEquals("a", p.currentName());

assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
// At value token -> MATCH_ODD_TOKEN
assertEquals(PropertyNameMatcher.MATCH_ODD_TOKEN, p.currentNameMatch(null));

assertToken(JsonToken.END_OBJECT, p.nextToken());
// At END_OBJECT -> MATCH_END_OBJECT
assertEquals(PropertyNameMatcher.MATCH_END_OBJECT, p.currentNameMatch(null));
}
}

private void _verifyDoc1(JsonParser p, PropertyNameMatcher matcher,
List<String> names) throws Exception
{
Expand Down
Loading