Skip to content

Commit 772bd09

Browse files
committed
Fix #818
1 parent 724567f commit 772bd09

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ JSON library.
6464
`byte[]`/`char[]`/String-with-offsets input
6565
#812: Add explicit bounds checks for `JsonFactory.createParser()` methods
6666
that take `byte[]`/`char[]`-with-offsets input
67+
#818: Calling `JsonPointer.compile(...)` on very deeply nested expression
68+
throws `StackOverflowErrror`
6769

6870
2.13.4 (03-Sep-2022)
6971

src/main/java/com/fasterxml/jackson/core/JsonPointer.java

+53-12
Original file line numberDiff line numberDiff line change
@@ -562,37 +562,56 @@ private final static int _parseIndex(String str) {
562562
}
563563
return NumberInput.parseInt(str);
564564
}
565-
566-
protected static JsonPointer _parseTail(String input) {
567-
final int end = input.length();
565+
566+
protected static JsonPointer _parseTail(String fullPath)
567+
{
568+
PointerParent parent = null;
568569

569570
// first char is the contextual slash, skip
570-
for (int i = 1; i < end; ) {
571-
char c = input.charAt(i);
571+
int i = 1;
572+
int end = fullPath.length();
573+
574+
while (i < end) {
575+
char c = fullPath.charAt(i);
572576
if (c == '/') { // common case, got a segment
573-
return new JsonPointer(input, input.substring(1, i),
574-
_parseTail(input.substring(i)));
577+
parent = new PointerParent(parent, fullPath, fullPath.substring(1, i));
578+
fullPath = fullPath.substring(i);
579+
i = 1;
580+
end = fullPath.length();
581+
continue;
575582
}
576583
++i;
577584
// quoting is different; offline this case
578585
if (c == '~' && i < end) { // possibly, quote
579586
// 04-Oct-2022, tatu: Let's decode escaped segment
580587
// instead of recursive call
581588
StringBuilder sb = new StringBuilder(32);
582-
i = _extractEscapedSegment(input, i, sb);
589+
i = _extractEscapedSegment(fullPath, i, sb);
583590
final String segment = sb.toString();
584591
if (i < 0) { // end!
585-
return new JsonPointer(input, segment, EMPTY);
592+
return _buildPath(fullPath, segment, parent);
586593
}
587-
return new JsonPointer(input, segment,
588-
_parseTail(input.substring(i)));
594+
parent = new PointerParent(parent, fullPath, segment);
595+
fullPath = fullPath.substring(i);
596+
i = 1;
597+
end = fullPath.length();
598+
continue;
589599
}
590600
// otherwise, loop on
591601
}
592602
// end of the road, no escapes
593-
return new JsonPointer(input, input.substring(1), EMPTY);
603+
return _buildPath(fullPath, fullPath.substring(1), parent);
594604
}
595605

606+
private static JsonPointer _buildPath(String fullPath, String segment,
607+
PointerParent parent) {
608+
JsonPointer curr = new JsonPointer(fullPath, segment, EMPTY);
609+
for (; parent != null; parent = parent.parent) {
610+
curr = new JsonPointer(parent.fullPath, parent.segment, curr);
611+
}
612+
return curr;
613+
}
614+
596615
/**
597616
* Method called to extract the next segment of the path, in case
598617
* where we seem to have encountered a (tilde-)escaped character
@@ -665,6 +684,28 @@ protected JsonPointer _constructHead(int suffixLength, JsonPointer last)
665684
_matchingElementIndex, next._constructHead(suffixLength, last));
666685
}
667686

687+
/*
688+
/**********************************************************
689+
/* Helper class used to replace call stack (2.14+)
690+
/**********************************************************
691+
*/
692+
693+
/**
694+
* Helper class used to replace call stack when parsing JsonPointer
695+
* expressions.
696+
*/
697+
private static class PointerParent {
698+
public final PointerParent parent;
699+
public final String fullPath;
700+
public final String segment;
701+
702+
PointerParent(PointerParent pp, String fp, String sgm) {
703+
parent = pp;
704+
fullPath = fp;
705+
segment = sgm;
706+
}
707+
}
708+
668709
/*
669710
/**********************************************************
670711
/* Support for JDK serialization (2.14+)

src/test/java/com/fasterxml/jackson/failing/Fuzz51806JsonPointerParse818Test.java renamed to src/test/java/com/fasterxml/jackson/core/fuzz/Fuzz51806JsonPointerParse818Test.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.failing;
1+
package com.fasterxml.jackson.core.fuzz;
22

33
import com.fasterxml.jackson.core.BaseTest;
44
import com.fasterxml.jackson.core.JsonPointer;

src/test/java/com/fasterxml/jackson/core/io/doubleparser/ParseSignificandWithSwarTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void doIllegalTest(String s) {
4444
public void doLegalTest(String s) {
4545
double actual = significandToDouble(s.getBytes(StandardCharsets.ISO_8859_1));
4646
double expected = Double.parseDouble(s);
47-
System.out.println(expected + " == " + actual);
47+
// System.out.println(expected + " == " + actual);
4848
assertEquals(expected, actual);
4949
}
5050

0 commit comments

Comments
 (0)