Fuzz51806JsonPointerParse818Test.java
package com.fasterxml.jackson.core.jsonptr;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.core.JUnit5TestBase;
import com.fasterxml.jackson.core.JsonPointer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
// For https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=51806
// (reported as [core#818]
class Fuzz51806JsonPointerParse818Test extends JUnit5TestBase
{
// Before fix, StackOverflowError with 6_000 or so,
// and OOME with 20_000.
// After fixes will get progressively slower so limit size to
// keep test runs from making suite too slow
private final static int TOO_DEEP_PATH = 25_000;
// Verify that a very deep/long (by number of segments) JsonPointer
// may still be parsed ok, for "simple" case (no quoted chars)
@Test
void jsonPointerParseTailSimple()
{
_testJsonPointer(_generatePath(TOO_DEEP_PATH, false));
}
@Test
void jsonPointerParseTailWithQuoted()
{
_testJsonPointer(_generatePath(TOO_DEEP_PATH, true));
}
private void _testJsonPointer(String pathExpr)
{
JsonPointer p = JsonPointer.compile(pathExpr);
assertNotNull(p);
// But also verify it didn't change
assertEquals(pathExpr, p.toString());
// And then verify segment by segment, easiest way is to
// check that tail segment is proper substring
JsonPointer curr = p;
while ((curr = curr.tail()) != null) {
String act = curr.toString();
String exp = pathExpr.substring(pathExpr.length() - act.length());
assertEquals(exp, act);
}
}
private String _generatePath(int depth, boolean escaped) {
StringBuilder sb = new StringBuilder(4 * depth);
for (int i = 0; i < depth; ++i) {
sb.append('/')
.append((char) ('a' + i%25))
.append(i);
if (escaped) {
switch (i & 7) {
case 1:
sb.append("~0x");
break;
case 4:
sb.append("~1y");
break;
}
}
}
return sb.toString();
}
}