diff --git a/CVE-2025-52999.patch b/CVE-2025-52999.patch new file mode 100644 index 0000000000000000000000000000000000000000..cf521e355b41b0b1b312f5e6dabda040f2dd4990 --- /dev/null +++ b/CVE-2025-52999.patch @@ -0,0 +1,603 @@ +From 54f78a9cff5e3bace1cf8042ac1b4c3785dc9f5e Mon Sep 17 00:00:00 2001 +From: PJ Fanning +Date: Mon, 6 Mar 2023 01:25:05 +0100 +Subject: [PATCH] apply constraint to nesting depth (#943) + +--- + .../jackson/core/JsonStreamContext.java | 14 ++++ + .../jackson/core/StreamReadConstraints.java | 70 +++++++++++++++++-- + .../jackson/core/base/ParserBase.java | 10 +++ + .../jackson/core/json/JsonReadContext.java | 1 + + .../core/json/ReaderBasedJsonParser.java | 30 ++++---- + .../core/json/UTF8DataInputJsonParser.java | 26 +++---- + .../core/json/UTF8StreamJsonParser.java | 26 +++---- + .../json/async/NonBlockingJsonParserBase.java | 4 +- + .../jackson/core/fuzz/Fuzz34435ParseTest.java | 1 + + .../core/jsonptr/JsonPointerOOME736Test.java | 5 +- + .../jackson/core/read/ArrayParsingTest.java | 29 ++++++++ + 11 files changed, 166 insertions(+), 50 deletions(-) + +diff --git a/src/main/java/com/fasterxml/jackson/core/JsonStreamContext.java b/src/main/java/com/fasterxml/jackson/core/JsonStreamContext.java +index 9fbc1661..03720fef 100644 +--- a/src/main/java/com/fasterxml/jackson/core/JsonStreamContext.java ++++ b/src/main/java/com/fasterxml/jackson/core/JsonStreamContext.java +@@ -52,6 +52,12 @@ public abstract class JsonStreamContext + */ + protected int _index; + ++ /** ++ * The nesting depth is a count of objects and arrays that have not ++ * been closed, `{` and `[` respectively. ++ */ ++ protected int _nestingDepth; ++ + /* + /********************************************************** + /* Life-cycle +@@ -118,6 +124,14 @@ public abstract class JsonStreamContext + */ + public final boolean inObject() { return _type == TYPE_OBJECT; } + ++ /** ++ * The nesting depth is a count of objects and arrays that have not ++ * been closed, `{` and `[` respectively. ++ */ ++ public final int getNestingDepth() { ++ return _nestingDepth; ++ } ++ + /** + * @return Type description String + * +diff --git a/src/main/java/com/fasterxml/jackson/core/StreamReadConstraints.java b/src/main/java/com/fasterxml/jackson/core/StreamReadConstraints.java +index e6b2cc5a..2363c38d 100644 +--- a/src/main/java/com/fasterxml/jackson/core/StreamReadConstraints.java ++++ b/src/main/java/com/fasterxml/jackson/core/StreamReadConstraints.java +@@ -25,6 +25,11 @@ public class StreamReadConstraints + { + private static final long serialVersionUID = 1L; + ++ /** ++ * Default setting for maximum depth: see {@link Builder#maxNestingDepth(int)} for details. ++ */ ++ public static final int DEFAULT_MAX_DEPTH = 1000; ++ + /** + * Default setting for maximum number length: see {@link Builder#maxNumberLength(int)} for details. + */ +@@ -35,16 +40,37 @@ public class StreamReadConstraints + */ + public static final int DEFAULT_MAX_STRING_LEN = 1_000_000; + ++ protected final int _maxNestingDepth; + protected final int _maxNumLen; + protected final int _maxStringLen; + + private static final StreamReadConstraints DEFAULT = +- new StreamReadConstraints(DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN); ++ new StreamReadConstraints(DEFAULT_MAX_DEPTH, DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN); + + public static final class Builder { ++ private int maxNestingDepth; + private int maxNumLen; + private int maxStringLen; + ++ /** ++ * Sets the maximum nesting depth. The depth is a count of objects and arrays that have not ++ * been closed, `{` and `[` respectively. ++ * ++ * @param maxNestingDepth the maximum depth ++ * ++ * @return this builder ++ * @throws IllegalArgumentException if the maxNestingDepth is set to a negative value ++ * ++ * @since 2.15 ++ */ ++ public Builder maxNestingDepth(final int maxNestingDepth) { ++ if (maxNestingDepth < 0) { ++ throw new IllegalArgumentException("Cannot set maxNestingDepth to a negative value"); ++ } ++ this.maxNestingDepth = maxNestingDepth; ++ return this; ++ } ++ + /** + * Sets the maximum number length (in chars or bytes, depending on input context). + * The default is 1000. +@@ -90,21 +116,23 @@ public class StreamReadConstraints + } + + Builder() { +- this(DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN); ++ this(DEFAULT_MAX_DEPTH, DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN); + } + +- Builder(final int maxNumLen, final int maxStringLen) { ++ Builder(final int maxNestingDepth, final int maxNumLen, final int maxStringLen) { ++ this.maxNestingDepth = maxNestingDepth; + this.maxNumLen = maxNumLen; + this.maxStringLen = maxStringLen; + } + + Builder(StreamReadConstraints src) { ++ maxNestingDepth = src._maxNestingDepth; + maxNumLen = src._maxNumLen; + maxStringLen = src._maxStringLen; + } + + public StreamReadConstraints build() { +- return new StreamReadConstraints(maxNumLen, maxStringLen); ++ return new StreamReadConstraints(maxNestingDepth, maxNumLen, maxStringLen); + } + } + +@@ -114,7 +142,8 @@ public class StreamReadConstraints + /********************************************************************** + */ + +- StreamReadConstraints(final int maxNumLen, final int maxStringLen) { ++ StreamReadConstraints(final int maxNestingDepth, final int maxNumLen, final int maxStringLen) { ++ _maxNestingDepth = maxNestingDepth; + _maxNumLen = maxNumLen; + _maxStringLen = maxStringLen; + } +@@ -141,6 +170,16 @@ public class StreamReadConstraints + /********************************************************************** + */ + ++ /** ++ * Accessor for maximum depth. ++ * see {@link Builder#maxNestingDepth(int)} for details. ++ * ++ * @return Maximum allowed depth ++ */ ++ public int getMaxNestingDepth() { ++ return _maxNestingDepth; ++ } ++ + /** + * Accessor for maximum length of numbers to decode. + * see {@link Builder#maxNumberLength(int)} for details. +@@ -169,7 +208,7 @@ public class StreamReadConstraints + + /** + * Convenience method that can be used to verify that a floating-point +- * number of specified length does not exceed maximum specific by this ++ * number of specified length does not exceed maximum specified by this + * constraints object: if it does, a + * {@link StreamConstraintsException} + * is thrown. +@@ -223,4 +262,23 @@ public class StreamReadConstraints + length, _maxStringLen)); + } + } ++ ++ /** ++ * Convenience method that can be used to verify that the ++ * nesting depth does not exceed the maximum specified by this ++ * constraints object: if it does, a ++ * {@link StreamConstraintsException} ++ * is thrown. ++ * ++ * @param depth count of unclosed objects and arrays ++ * ++ * @throws StreamConstraintsException If depth exceeds maximum ++ */ ++ public void validateNestingDepth(int depth) throws StreamConstraintsException ++ { ++ if (depth > _maxNestingDepth) { ++ throw new StreamConstraintsException(String.format("Depth (%d) exceeds the maximum allowed nesting depth (%d)", ++ depth, _maxNestingDepth)); ++ } ++ } + } +diff --git a/src/main/java/com/fasterxml/jackson/core/base/ParserBase.java b/src/main/java/com/fasterxml/jackson/core/base/ParserBase.java +index 8af25657..41ea412f 100644 +--- a/src/main/java/com/fasterxml/jackson/core/base/ParserBase.java ++++ b/src/main/java/com/fasterxml/jackson/core/base/ParserBase.java +@@ -1536,4 +1536,14 @@ public abstract class ParserBase extends ParserMinimalBase + + // Can't declare as deprecated, for now, but shouldn't be needed + protected void _finishString() throws IOException { } ++ ++ protected final void createChildArrayContext(final int lineNr, final int colNr) throws IOException { ++ _parsingContext = _parsingContext.createChildArrayContext(lineNr, colNr); ++ _streamReadConstraints.validateNestingDepth(_parsingContext.getNestingDepth()); ++ } ++ ++ protected final void createChildObjectContext(final int lineNr, final int colNr) throws IOException { ++ _parsingContext = _parsingContext.createChildObjectContext(lineNr, colNr); ++ _streamReadConstraints.validateNestingDepth(_parsingContext.getNestingDepth()); ++ } + } +diff --git a/src/main/java/com/fasterxml/jackson/core/json/JsonReadContext.java b/src/main/java/com/fasterxml/jackson/core/json/JsonReadContext.java +index 576fefbf..e2f95a7a 100644 +--- a/src/main/java/com/fasterxml/jackson/core/json/JsonReadContext.java ++++ b/src/main/java/com/fasterxml/jackson/core/json/JsonReadContext.java +@@ -61,6 +61,7 @@ public final class JsonReadContext extends JsonStreamContext + _lineNr = lineNr; + _columnNr = colNr; + _index = -1; ++ _nestingDepth = parent == null ? 0 : parent._nestingDepth + 1; + } + + /** +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 232843ac..ccbfa7d2 100644 +--- a/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java ++++ b/src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java +@@ -752,13 +752,13 @@ public class ReaderBasedJsonParser + break; + case '[': + if (!inObject) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } + t = JsonToken.START_ARRAY; + break; + case '{': + if (!inObject) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + t = JsonToken.START_OBJECT; + break; +@@ -817,7 +817,7 @@ public class ReaderBasedJsonParser + return t; + } + +- private final JsonToken _nextAfterName() ++ private final JsonToken _nextAfterName() throws IOException + { + _nameCopied = false; // need to invalidate if it was copied + JsonToken t = _nextToken; +@@ -827,9 +827,9 @@ public class ReaderBasedJsonParser + + // Also: may need to start new context? + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return (_currToken = t); + } +@@ -1165,10 +1165,10 @@ public class ReaderBasedJsonParser + } + switch (i) { + case '[': +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_ARRAY); + case '{': +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_OBJECT); + case 't': + _matchToken("true", 1); +@@ -1235,9 +1235,9 @@ public class ReaderBasedJsonParser + return _textBuffer.contentsAsString(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +@@ -1258,9 +1258,9 @@ public class ReaderBasedJsonParser + return getIntValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -1281,9 +1281,9 @@ public class ReaderBasedJsonParser + return getLongValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -1307,9 +1307,9 @@ public class ReaderBasedJsonParser + return Boolean.FALSE; + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java +index cee350da..6d93fab5 100644 +--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java ++++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java +@@ -716,10 +716,10 @@ public class UTF8DataInputJsonParser + } + switch (i) { + case '[': +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_ARRAY); + case '{': +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_OBJECT); + case 't': + _matchToken("true", 1); +@@ -754,7 +754,7 @@ public class UTF8DataInputJsonParser + return (_currToken = _handleUnexpectedValue(i)); + } + +- private final JsonToken _nextAfterName() ++ private final JsonToken _nextAfterName() throws IOException + { + _nameCopied = false; // need to invalidate if it was copied + JsonToken t = _nextToken; +@@ -762,9 +762,9 @@ public class UTF8DataInputJsonParser + + // Also: may need to start new context? + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return (_currToken = t); + } +@@ -908,9 +908,9 @@ public class UTF8DataInputJsonParser + return _textBuffer.contentsAsString(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +@@ -930,9 +930,9 @@ public class UTF8DataInputJsonParser + return getIntValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -952,9 +952,9 @@ public class UTF8DataInputJsonParser + return getLongValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -977,9 +977,9 @@ public class UTF8DataInputJsonParser + return Boolean.FALSE; + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java +index a7c08dae..2cea491b 100644 +--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java ++++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java +@@ -869,10 +869,10 @@ public class UTF8StreamJsonParser + } + switch (i) { + case '[': +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_ARRAY); + case '{': +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_OBJECT); + case 't': + _matchTrue(); +@@ -907,7 +907,7 @@ public class UTF8StreamJsonParser + return (_currToken = _handleUnexpectedValue(i)); + } + +- private final JsonToken _nextAfterName() ++ private final JsonToken _nextAfterName() throws IOException + { + _nameCopied = false; // need to invalidate if it was copied + JsonToken t = _nextToken; +@@ -917,9 +917,9 @@ public class UTF8StreamJsonParser + + // Also: may need to start new context? + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return (_currToken = t); + } +@@ -1334,9 +1334,9 @@ public class UTF8StreamJsonParser + return _textBuffer.contentsAsString(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +@@ -1357,9 +1357,9 @@ public class UTF8StreamJsonParser + return getIntValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -1380,9 +1380,9 @@ public class UTF8StreamJsonParser + return getLongValue(); + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } +@@ -1406,9 +1406,9 @@ public class UTF8StreamJsonParser + return Boolean.FALSE; + } + if (t == JsonToken.START_ARRAY) { +- _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); ++ createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { +- _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); ++ createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } +diff --git a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java +index 66e72abd..f37bb3fc 100644 +--- a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java ++++ b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java +@@ -579,7 +579,7 @@ public abstract class NonBlockingJsonParserBase + + protected final JsonToken _startArrayScope() throws IOException + { +- _parsingContext = _parsingContext.createChildArrayContext(-1, -1); ++ createChildArrayContext(-1, -1); + _majorState = MAJOR_ARRAY_ELEMENT_FIRST; + _majorStateAfterValue = MAJOR_ARRAY_ELEMENT_NEXT; + return (_currToken = JsonToken.START_ARRAY); +@@ -587,7 +587,7 @@ public abstract class NonBlockingJsonParserBase + + protected final JsonToken _startObjectScope() throws IOException + { +- _parsingContext = _parsingContext.createChildObjectContext(-1, -1); ++ createChildObjectContext(-1, -1); + _majorState = MAJOR_OBJECT_FIELD_FIRST; + _majorStateAfterValue = MAJOR_OBJECT_FIELD_NEXT; + return (_currToken = JsonToken.START_OBJECT); +diff --git a/src/test/java/com/fasterxml/jackson/core/fuzz/Fuzz34435ParseTest.java b/src/test/java/com/fasterxml/jackson/core/fuzz/Fuzz34435ParseTest.java +index e83cf3dc..d3689a52 100644 +--- a/src/test/java/com/fasterxml/jackson/core/fuzz/Fuzz34435ParseTest.java ++++ b/src/test/java/com/fasterxml/jackson/core/fuzz/Fuzz34435ParseTest.java +@@ -17,6 +17,7 @@ public class Fuzz34435ParseTest extends BaseTest + .enable(JsonReadFeature.ALLOW_YAML_COMMENTS) + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .enable(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES) ++ .streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(Integer.MAX_VALUE).build()) + .build(); + + JsonParser p = f.createParser(/*ObjectReadContext.empty(), */ DOC); +diff --git a/src/test/java/com/fasterxml/jackson/core/jsonptr/JsonPointerOOME736Test.java b/src/test/java/com/fasterxml/jackson/core/jsonptr/JsonPointerOOME736Test.java +index b4547bc5..d2f4e0bf 100644 +--- a/src/test/java/com/fasterxml/jackson/core/jsonptr/JsonPointerOOME736Test.java ++++ b/src/test/java/com/fasterxml/jackson/core/jsonptr/JsonPointerOOME736Test.java +@@ -10,7 +10,10 @@ public class JsonPointerOOME736Test extends BaseTest + int MAX_DEPTH = 120_000; + // Create nesting of 120k arrays + String INPUT = new String(new char[MAX_DEPTH]).replace("\0", "["); +- JsonParser parser = createParser(MODE_READER, INPUT); ++ final JsonFactory f = JsonFactory.builder() ++ .streamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(Integer.MAX_VALUE).build()) ++ .build(); ++ JsonParser parser = createParser(f, MODE_READER, INPUT); + try { + while (true) { + parser.nextToken(); +diff --git a/src/test/java/com/fasterxml/jackson/core/read/ArrayParsingTest.java b/src/test/java/com/fasterxml/jackson/core/read/ArrayParsingTest.java +index f7067e41..98fe9023 100644 +--- a/src/test/java/com/fasterxml/jackson/core/read/ArrayParsingTest.java ++++ b/src/test/java/com/fasterxml/jackson/core/read/ArrayParsingTest.java +@@ -1,6 +1,7 @@ + package com.fasterxml.jackson.core.read; + + import com.fasterxml.jackson.core.*; ++import com.fasterxml.jackson.core.exc.StreamConstraintsException; + import com.fasterxml.jackson.core.json.JsonReadFeature; + + /** +@@ -106,6 +107,20 @@ public class ArrayParsingTest + _testNotMissingValueByEnablingFeature(false); + } + ++ public void testDeepNesting() throws Exception ++ { ++ final String DOC = createDeepNestedDoc(1050); ++ try (JsonParser jp = createParserUsingStream(new JsonFactory(), DOC, "UTF-8")) { ++ JsonToken jt; ++ while ((jt = jp.nextToken()) != null) { ++ ++ } ++ fail("expected StreamConstraintsException"); ++ } catch (StreamConstraintsException e) { ++ assertEquals("Depth (1001) exceeds the maximum allowed nesting depth (1000)", e.getMessage()); ++ } ++ } ++ + private void _testMissingValueByEnablingFeature(boolean useStream) throws Exception { + String DOC = "[ \"a\",,,,\"abc\", ] "; + +@@ -182,4 +197,18 @@ public class ArrayParsingTest + + jp.close(); + } ++ ++ private String createDeepNestedDoc(final int depth) { ++ StringBuilder sb = new StringBuilder(); ++ sb.append("["); ++ for (int i = 0; i < depth; i++) { ++ sb.append("{ \"a\": ["); ++ } ++ sb.append(" \"val\" "); ++ for (int i = 0; i < depth; i++) { ++ sb.append("]}"); ++ } ++ sb.append("]"); ++ return sb.toString(); ++ } + } +-- +2.20.1 + diff --git a/jackson-core-2.15.0.tar.gz b/jackson-core-2.15.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bc717465987466b6e9f9580f2e2e244af4d5f6ea Binary files /dev/null and b/jackson-core-2.15.0.tar.gz differ diff --git a/jackson-core-2.9.8.tar.gz b/jackson-core-2.9.8.tar.gz deleted file mode 100644 index 548fcd693b5602e71f79b357b1a9dabfd63940cd..0000000000000000000000000000000000000000 Binary files a/jackson-core-2.9.8.tar.gz and /dev/null differ diff --git a/jackson-core.spec b/jackson-core.spec index 27d711012dfb15b6ee615adb78fe8262f148b50b..30e48fa71c0b5b2efdbc82a0b44d5ab426b09667 100644 --- a/jackson-core.spec +++ b/jackson-core.spec @@ -1,6 +1,6 @@ Name: jackson-core -Version: 2.9.8 -Release: 2 +Version: 2.15.0 +Release: 1 Summary: Core part of Jackson License: ASL 2.0 URL: https://github.com/FasterXML/jackson-core/ @@ -32,6 +32,7 @@ sed -i 's/\r//' LICENSE NOTICE %mvn_file : %{name} %patch01 -p1 +%patch02 -p1 %build %mvn_build @@ -47,6 +48,9 @@ sed -i 's/\r//' LICENSE NOTICE %license LICENSE NOTICE %changelog +* Thu Aug 28 2025 Yu Peng - 2.15.0-1 +- Upgrade to 2.15.0 to Fix CVE-2025-52999 + * Mon Dec 02 2024 zhaosaisai - 2.9.8-2 - backport Fix Non-blocking parser reports incorrect locations