Skip to content

Commit

Permalink
Minor refactoring of JsonPointer in preparation for tackling #818
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Oct 5, 2022
1 parent 2a6527f commit 724567f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 21 deletions.
52 changes: 32 additions & 20 deletions src/main/java/com/fasterxml/jackson/core/JsonPointer.java
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,16 @@ protected static JsonPointer _parseTail(String input) {
++i;
// quoting is different; offline this case
if (c == '~' && i < end) { // possibly, quote
return _parseQuotedTail(input, i);
// 04-Oct-2022, tatu: Let's decode escaped segment
// instead of recursive call
StringBuilder sb = new StringBuilder(32);
i = _extractEscapedSegment(input, i, sb);
final String segment = sb.toString();
if (i < 0) { // end!
return new JsonPointer(input, segment, EMPTY);
}
return new JsonPointer(input, segment,
_parseTail(input.substring(i)));
}
// otherwise, loop on
}
Expand All @@ -585,26 +594,29 @@ protected static JsonPointer _parseTail(String input) {
}

/**
* Method called to parse tail of pointer path, when a potentially
* escaped character has been seen.
* Method called to extract the next segment of the path, in case
* where we seem to have encountered a (tilde-)escaped character
* within segment.
*
* @param input Full input for the tail being parsed
* @param i Offset to character after tilde
* @param sb StringBuilder into which unquoted segment is added
*
* @return Pointer instance constructed
* @return Offset at which slash was encountered, if any, or -1
* if expression ended without seeing unescaped slash
*/
protected static JsonPointer _parseQuotedTail(String input, int i) {
protected static int _extractEscapedSegment(String input, int i,
StringBuilder sb)
{
final int end = input.length();
StringBuilder sb = new StringBuilder(Math.max(16, end));
if (i > 2) {
sb.append(input, 1, i-1);
}
_appendEscape(sb, input.charAt(i++));
while (i < end) {
char c = input.charAt(i);
if (c == '/') { // end is nigh!
return new JsonPointer(input, sb.toString(),
_parseTail(input.substring(i)));
return i;
}
++i;
if (c == '~' && i < end) {
Expand All @@ -614,7 +626,18 @@ protected static JsonPointer _parseQuotedTail(String input, int i) {
sb.append(c);
}
// end of the road, last segment
return new JsonPointer(input, sb.toString(), EMPTY);
return -1;
}

private static void _appendEscape(StringBuilder sb, char c) {
if (c == '0') {
c = '~';
} else if (c == '1') {
c = '/';
} else {
sb.append('~');
}
sb.append(c);
}

protected JsonPointer _constructHead()
Expand Down Expand Up @@ -642,17 +665,6 @@ protected JsonPointer _constructHead(int suffixLength, JsonPointer last)
_matchingElementIndex, next._constructHead(suffixLength, last));
}

private static void _appendEscape(StringBuilder sb, char c) {
if (c == '0') {
c = '~';
} else if (c == '1') {
c = '/';
} else {
sb.append('~');
}
sb.append(c);
}

/*
/**********************************************************
/* Support for JDK serialization (2.14+)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

// For https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=51806
// (reported as [core#818]
public class Fuzz51806JsonPointerParseTest extends BaseTest
public class Fuzz51806JsonPointerParse818Test extends BaseTest
{
// Before fix, looks like this is enough to cause StackOverflowError
private final static int TOO_DEEP_PATH = 6000;
Expand Down

0 comments on commit 724567f

Please sign in to comment.