Fix CVE-2020-36518,CVE-2022-42003 and CVE-2022-42004

(cherry picked from commit b7eead59adebf0ae27240f330fec6206b26e672b)
This commit is contained in:
starlet-dx 2023-12-13 10:42:14 +08:00 committed by openeuler-sync-bot
parent c42234bf5b
commit 42795e37e0
4 changed files with 664 additions and 1 deletions

346
CVE-2020-36518.patch Normal file
View File

@ -0,0 +1,346 @@
From: Markus Koschany <apo@debian.org>
Date: Tue, 15 Nov 2022 12:51:57 +0100
Subject: CVE-2020-36518
Bug-Debian: https://bugs.debian.org/1007109
Origin: https://github.com/FasterXML/jackson-databind/commit/83b928dab9ba6ef81cf48987fcd12071e1ddb0c9
Origin: https://github.com/FasterXML/jackson-databind/commit/fcfc4998ec23f0b1f7f8a9521c2b317b6c25892b
---
.../deser/std/UntypedObjectDeserializer.java | 140 +++++++++++----------
.../deser/DeepNestingUntypedDeserTest.java | 70 +++++++++++
2 files changed, 147 insertions(+), 63 deletions(-)
create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/DeepNestingUntypedDeserTest.java
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
index 67be238..41f6dd9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/UntypedObjectDeserializer.java
@@ -220,10 +220,9 @@ public class UntypedObjectDeserializer
*/
@Override
public boolean isCachable() {
- /* 26-Mar-2015, tatu: With respect to [databind#735], there are concerns over
- * cachability. It seems like we SHOULD be safe here; but just in case there
- * are problems with false sharing, this may need to be revisited.
- */
+ // 26-Mar-2015, tatu: With respect to [databind#735], there are concerns over
+ // cachability. It seems like we SHOULD be safe here; but just in case there
+ // are problems with false sharing, this may need to be revisited.
return true;
}
@@ -266,9 +265,8 @@ public class UntypedObjectDeserializer
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
- /* Caller may want to get all integral values returned as {@link java.math.BigInteger},
- * or {@link java.lang.Long} for consistency
- */
+ // Caller may want to get all integral values returned as {@link java.math.BigInteger},
+ // or {@link java.lang.Long} for consistency
if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
return _coerceIntegral(p, ctxt);
}
@@ -599,10 +597,9 @@ public class UntypedObjectDeserializer
}
/*
- /**********************************************************
- /* Separate "vanilla" implementation for common case of
- /* no custom deserializer overrides
- /**********************************************************
+ /**********************************************************************
+ /* Separate "vanilla" implementation for common case of no deser overrides
+ /**********************************************************************
*/
@JacksonStdImpl
@@ -611,11 +608,13 @@ public class UntypedObjectDeserializer
{
private static final long serialVersionUID = 1L;
+ // Arbitrarily chosen.
+ // Introduced to resolve CVE-2020-36518 and as a temporary hotfix for #2816
+ private static final int MAX_DEPTH = 1000;
+
public final static Vanilla std = new Vanilla();
- /**
- * @since 2.9
- */
+ // @since 2.9
protected final boolean _nonMerging;
public Vanilla() { this(false); }
@@ -639,65 +638,77 @@ public class UntypedObjectDeserializer
return _nonMerging ? Boolean.FALSE : null;
}
- @Override
- public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
+ @Override
+ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+ return deserialize(p, ctxt, 0);
+ }
+
+ private Object deserialize(JsonParser p, DeserializationContext ctxt, int depth) throws IOException
{
- switch (p.getCurrentTokenId()) {
- case JsonTokenId.ID_START_OBJECT:
- {
+ switch (p.currentTokenId()) {
+ case JsonTokenId.ID_START_OBJECT: {
JsonToken t = p.nextToken();
if (t == JsonToken.END_OBJECT) {
- return new LinkedHashMap<String,Object>(2);
+ return new LinkedHashMap<String, Object>(2);
}
}
- case JsonTokenId.ID_FIELD_NAME:
- return mapObject(p, ctxt);
- case JsonTokenId.ID_START_ARRAY:
- {
+ case JsonTokenId.ID_FIELD_NAME:
+ if (depth > MAX_DEPTH) {
+ throw new JsonParseException(p, "JSON is too deeply nested.");
+ }
+
+ return mapObject(p, ctxt, depth);
+ case JsonTokenId.ID_START_ARRAY: {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) { // and empty one too
- if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
+ if (ctxt.isEnabled(
+ DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return NO_OBJECTS;
}
return new ArrayList<Object>(2);
}
}
- if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
- return mapArrayToArray(p, ctxt);
- }
- return mapArray(p, ctxt);
- case JsonTokenId.ID_EMBEDDED_OBJECT:
- return p.getEmbeddedObject();
- case JsonTokenId.ID_STRING:
- return p.getText();
- case JsonTokenId.ID_NUMBER_INT:
- if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
- return _coerceIntegral(p, ctxt);
+ if (depth > MAX_DEPTH) {
+ throw new JsonParseException(p, "JSON is too deeply nested.");
}
- return p.getNumberValue(); // should be optimal, whatever it is
- case JsonTokenId.ID_NUMBER_FLOAT:
- if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
- return p.getDecimalValue();
+ if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
+ return mapArrayToArray(p, ctxt, depth);
}
- return p.getNumberValue();
+ return mapArray(p, ctxt, depth);
+ case JsonTokenId.ID_EMBEDDED_OBJECT:
+ return p.getEmbeddedObject();
+ case JsonTokenId.ID_STRING:
+ return p.getText();
+
+ case JsonTokenId.ID_NUMBER_INT:
+ if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
+ return _coerceIntegral(p, ctxt);
+ }
+ return p.getNumberValue(); // should be optimal, whatever it is
- case JsonTokenId.ID_TRUE:
- return Boolean.TRUE;
- case JsonTokenId.ID_FALSE:
- return Boolean.FALSE;
+ case JsonTokenId.ID_NUMBER_FLOAT:
+ if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
+ return p.getDecimalValue();
+ }
+ return p.getNumberValue();
- case JsonTokenId.ID_END_OBJECT:
- // 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
- // if caller has advanced to the first token of Object, but for empty Object
- return new LinkedHashMap<String,Object>(2);
+ case JsonTokenId.ID_TRUE:
+ return Boolean.TRUE;
+ case JsonTokenId.ID_FALSE:
+ return Boolean.FALSE;
- case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs
- return null;
+ case JsonTokenId.ID_END_OBJECT:
+ // 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
+ // if caller has advanced to the first token of Object, but for empty Object
+ return new LinkedHashMap<String, Object>(2);
- //case JsonTokenId.ID_END_ARRAY: // invalid
- default:
+ case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs
+ return null;
+
+ //case JsonTokenId.ID_END_ARRAY: // invalid
+ default:
}
return ctxt.handleUnexpectedToken(Object.class, p);
}
@@ -806,15 +817,16 @@ public class UntypedObjectDeserializer
return deserialize(p, ctxt);
}
- protected Object mapArray(JsonParser p, DeserializationContext ctxt) throws IOException
+ protected Object mapArray(JsonParser p, DeserializationContext ctxt, int depth) throws IOException
{
- Object value = deserialize(p, ctxt);
+ ++depth;
+ Object value = deserialize(p, ctxt, depth);
if (p.nextToken() == JsonToken.END_ARRAY) {
ArrayList<Object> l = new ArrayList<Object>(2);
l.add(value);
return l;
}
- Object value2 = deserialize(p, ctxt);
+ Object value2 = deserialize(p, ctxt, depth);
if (p.nextToken() == JsonToken.END_ARRAY) {
ArrayList<Object> l = new ArrayList<Object>(2);
l.add(value);
@@ -828,7 +840,7 @@ public class UntypedObjectDeserializer
values[ptr++] = value2;
int totalSize = ptr;
do {
- value = deserialize(p, ctxt);
+ value = deserialize(p, ctxt, depth);
++totalSize;
if (ptr >= values.length) {
values = buffer.appendCompletedChunk(values);
@@ -845,12 +857,13 @@ public class UntypedObjectDeserializer
/**
* Method called to map a JSON Array into a Java Object array (Object[]).
*/
- protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt) throws IOException {
+ protected Object[] mapArrayToArray(JsonParser p, DeserializationContext ctxt, int depth) throws IOException {
+ ++depth;
ObjectBuffer buffer = ctxt.leaseObjectBuffer();
Object[] values = buffer.resetAndStart();
int ptr = 0;
do {
- Object value = deserialize(p, ctxt);
+ Object value = deserialize(p, ctxt, depth);
if (ptr >= values.length) {
values = buffer.appendCompletedChunk(values);
ptr = 0;
@@ -863,12 +876,13 @@ public class UntypedObjectDeserializer
/**
* Method called to map a JSON Object into a Java value.
*/
- protected Object mapObject(JsonParser p, DeserializationContext ctxt) throws IOException
+ protected Object mapObject(JsonParser p, DeserializationContext ctxt, int depth) throws IOException
{
+ ++depth;
// will point to FIELD_NAME at this point, guaranteed
String key1 = p.getText();
p.nextToken();
- Object value1 = deserialize(p, ctxt);
+ Object value1 = deserialize(p, ctxt, depth);
String key2 = p.nextFieldName();
if (key2 == null) { // single entry; but we want modifiable
@@ -877,7 +891,7 @@ public class UntypedObjectDeserializer
return result;
}
p.nextToken();
- Object value2 = deserialize(p, ctxt);
+ Object value2 = deserialize(p, ctxt, depth);
String key = p.nextFieldName();
if (key == null) {
@@ -892,7 +906,7 @@ public class UntypedObjectDeserializer
result.put(key2, value2);
do {
p.nextToken();
- result.put(key, deserialize(p, ctxt));
+ result.put(key, deserialize(p, ctxt, depth));
} while ((key = p.nextFieldName()) != null);
return result;
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/DeepNestingUntypedDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/DeepNestingUntypedDeserTest.java
new file mode 100644
index 0000000..ad0194d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/DeepNestingUntypedDeserTest.java
@@ -0,0 +1,70 @@
+package com.fasterxml.jackson.databind.deser;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.List;
+import java.util.Map;
+
+public class DeepNestingUntypedDeserTest extends BaseMapTest
+{
+ // 28-Mar-2021, tatu: Currently 3000 fails for untyped/Object,
+ // 4000 for untyped/Array
+ private final static int TOO_DEEP_NESTING = 4000;
+ private final static int NOT_TOO_DEEP = 1000;
+
+ private final ObjectMapper MAPPER = new ObjectMapper();
+
+ public void testTooDeepUntypedWithArray() throws Exception
+ {
+ final String doc = _nestedDoc(TOO_DEEP_NESTING, "[ ", "] ");
+ try {
+ MAPPER.readValue(doc, Object.class);
+ fail("Should have thrown an exception.");
+ } catch (JsonParseException jpe) {
+ assertTrue(jpe.getMessage().startsWith("JSON is too deeply nested."));
+ }
+ }
+
+ public void testUntypedWithArray() throws Exception
+ {
+ final String doc = _nestedDoc(NOT_TOO_DEEP, "[ ", "] ");
+ Object ob = MAPPER.readValue(doc, Object.class);
+ assertTrue(ob instanceof List<?>);
+ }
+
+ public void testTooDeepUntypedWithObject() throws Exception
+ {
+ final String doc = "{"+_nestedDoc(TOO_DEEP_NESTING, "\"x\":{", "} ") + "}";
+ try {
+ MAPPER.readValue(doc, Object.class);
+ fail("Should have thrown an exception.");
+ } catch (JsonParseException jpe) {
+ assertTrue(jpe.getMessage().startsWith("JSON is too deeply nested."));
+ }
+ }
+
+ public void testUntypedWithObject() throws Exception
+ {
+ final String doc = "{"+_nestedDoc(NOT_TOO_DEEP, "\"x\":{", "} ") + "}";
+ Object ob = MAPPER.readValue(doc, Object.class);
+ assertTrue(ob instanceof Map<?, ?>);
+ }
+
+ private String _nestedDoc(int nesting, String open, String close) {
+ StringBuilder sb = new StringBuilder(nesting * (open.length() + close.length()));
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(open);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(close);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+}

230
CVE-2022-42003.patch Normal file
View File

@ -0,0 +1,230 @@
From: Markus Koschany <apo@debian.org>
Date: Mon, 14 Nov 2022 22:40:03 +0100
Subject: CVE-2022-42003
Origin: https://github.com/FasterXML/jackson-databind/commit/d78d00ee7b5245b93103fef3187f70543d67ca33
---
.../databind/deser/std/StdDeserializer.java | 48 ++++++++---
.../dos/DeepArrayWrappingForDeser3590Test.java | 93 ++++++++++++++++++++++
2 files changed, 129 insertions(+), 12 deletions(-)
create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3590Test.java
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
index 9a6f482..cf46afc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
@@ -178,7 +178,9 @@ public abstract class StdDeserializer<T>
}
// [databind#381]
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- p.nextToken();
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return (boolean) handleNestedArrayForSingle(p, ctxt);
+ }
final boolean parsed = _parseBooleanPrimitive(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -250,7 +252,9 @@ public abstract class StdDeserializer<T>
return 0;
case JsonTokenId.ID_START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- p.nextToken();
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return (int) handleNestedArrayForSingle(p, ctxt);
+ }
final int parsed = _parseIntPrimitive(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -310,7 +314,9 @@ public abstract class StdDeserializer<T>
return 0L;
case JsonTokenId.ID_START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- p.nextToken();
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return (long) handleNestedArrayForSingle(p, ctxt);
+ }
final long parsed = _parseLongPrimitive(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -356,7 +362,9 @@ public abstract class StdDeserializer<T>
return 0.0f;
case JsonTokenId.ID_START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- p.nextToken();
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return (float) handleNestedArrayForSingle(p, ctxt);
+ }
final float parsed = _parseFloatPrimitive(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -417,7 +425,9 @@ public abstract class StdDeserializer<T>
return 0.0;
case JsonTokenId.ID_START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- p.nextToken();
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return (double) handleNestedArrayForSingle(p, ctxt);
+ }
final double parsed = _parseDoublePrimitive(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -498,6 +508,9 @@ public abstract class StdDeserializer<T>
}
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ if (t == JsonToken.START_ARRAY) {
+ return (java.util.Date) handleNestedArrayForSingle(p, ctxt);
+ }
final Date parsed = _parseDate(p, ctxt);
_verifyEndArrayForSingle(p, ctxt);
return parsed;
@@ -662,11 +675,11 @@ public abstract class StdDeserializer<T>
}
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- final T parsed = deserialize(p, ctxt);
+ final T parsed = _deserializeWrappedValue(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
- return parsed;
+ return parsed;
}
} else {
t = p.getCurrentToken();
@@ -689,12 +702,8 @@ public abstract class StdDeserializer<T>
// 23-Mar-2017, tatu: Let's specifically block recursive resolution to avoid
// either supporting nested arrays, or to cause infinite looping.
if (p.hasToken(JsonToken.START_ARRAY)) {
- String msg = String.format(
-"Cannot deserialize instance of %s out of %s token: nested Arrays not allowed with %s",
- ClassUtil.nameOf(_valueClass), JsonToken.START_ARRAY,
- "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
@SuppressWarnings("unchecked")
- T result = (T) ctxt.handleUnexpectedToken(_valueClass, p.getCurrentToken(), p, msg);
+ T result = (T) handleNestedArrayForSingle(p, ctxt);
return result;
}
return (T) deserialize(p, ctxt);
@@ -1169,6 +1178,21 @@ handledType().getName());
// but for now just fall through
}
+ /**
+ * Helper method called when detecting a deep(er) nesting of Arrays when trying
+ * to unwrap value for {@code DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS}.
+ *
+ * @since 2.14
+ */
+ protected Object handleNestedArrayForSingle(JsonParser p, DeserializationContext ctxt) throws IOException
+ {
+ String msg = String.format(
+"Cannot deserialize instance of %s out of %s token: nested Arrays not allowed with %s",
+ ClassUtil.nameOf(_valueClass), JsonToken.START_ARRAY,
+ "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
+ return ctxt.handleUnexpectedToken(_valueClass, p.currentToken(), p, msg);
+ }
+
protected void _verifyEndArrayForSingle(JsonParser p, DeserializationContext ctxt) throws IOException
{
JsonToken t = p.nextToken();
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3590Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3590Test.java
new file mode 100644
index 0000000..8dfddcc
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3590Test.java
@@ -0,0 +1,93 @@
+package com.fasterxml.jackson.databind.deser.dos;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+
+public class DeepArrayWrappingForDeser3590Test extends BaseMapTest
+{
+ // 05-Sep-2022, tatu: Before fix, failed with 5000
+ private final static int TOO_DEEP_NESTING = 9999;
+
+ private final static String TOO_DEEP_DOC = _nestedDoc(TOO_DEEP_NESTING, "[ ", "] ", "123");
+
+ public void testArrayWrappingForBoolean() throws Exception
+ {
+ _testArrayWrappingFor(Boolean.class);
+ _testArrayWrappingFor(Boolean.TYPE);
+ }
+
+ public void testArrayWrappingForByte() throws Exception
+ {
+ _testArrayWrappingFor(Byte.class);
+ _testArrayWrappingFor(Byte.TYPE);
+ }
+
+ public void testArrayWrappingForShort() throws Exception
+ {
+ _testArrayWrappingFor(Short.class);
+ _testArrayWrappingFor(Short.TYPE);
+ }
+
+ public void testArrayWrappingForInt() throws Exception
+ {
+ _testArrayWrappingFor(Integer.class);
+ _testArrayWrappingFor(Integer.TYPE);
+ }
+
+ public void testArrayWrappingForLong() throws Exception
+ {
+ _testArrayWrappingFor(Long.class);
+ _testArrayWrappingFor(Long.TYPE);
+ }
+
+ public void testArrayWrappingForFloat() throws Exception
+ {
+ _testArrayWrappingFor(Float.class);
+ _testArrayWrappingFor(Float.TYPE);
+ }
+
+ public void testArrayWrappingForDouble() throws Exception
+ {
+ _testArrayWrappingFor(Double.class);
+ _testArrayWrappingFor(Double.TYPE);
+ }
+
+ public void testArrayWrappingForDate() throws Exception
+ {
+ _testArrayWrappingFor(Date.class);
+ }
+
+ private void _testArrayWrappingFor(Class<?> cls) throws Exception
+ {
+ final ObjectMapper MAPPER = new ObjectMapper();
+ MAPPER.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+ try {
+ MAPPER.readValue(TOO_DEEP_DOC, cls);
+ fail("Should not pass");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "Cannot deserialize");
+ verifyException(e, "nested Arrays not allowed");
+ }
+ }
+
+ private static String _nestedDoc(int nesting, String open, String close, String content) {
+ StringBuilder sb = new StringBuilder(nesting * (open.length() + close.length()));
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(open);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ sb.append("\n").append(content).append("\n");
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(close);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+}

78
CVE-2022-42004.patch Normal file
View File

@ -0,0 +1,78 @@
From: Markus Koschany <apo@debian.org>
Date: Mon, 14 Nov 2022 22:40:58 +0100
Subject: CVE-2022-42004
Origin: https://github.com/FasterXML/jackson-databind/commit/063183589218fec19a9293ed2f17ec53ea80ba88
---
.../databind/deser/BeanDeserializerBase.java | 6 +--
.../dos/DeepArrayWrappingForDeser3582Test.java | 44 ++++++++++++++++++++++
2 files changed, 47 insertions(+), 3 deletions(-)
create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3582Test.java
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
index 6ce41f7..639d8c9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
@@ -1440,9 +1440,9 @@ public abstract class BeanDeserializerBase
return bean;
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
- JsonToken t = p.nextToken();
- if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
- return null;
+ if (p.nextToken() == JsonToken.START_ARRAY) {
+ return ctxt.handleUnexpectedToken(handledType(), JsonToken.START_ARRAY, p,
+"Cannot deserialize value of type %s from deeply-nested JSON Array: only single wrapper allowed with DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
}
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3582Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3582Test.java
new file mode 100644
index 0000000..2147cf1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepArrayWrappingForDeser3582Test.java
@@ -0,0 +1,44 @@
+package com.fasterxml.jackson.databind.deser.dos;
+
+import java.io.IOException;
+import com.fasterxml.jackson.databind.*;
+
+public class DeepArrayWrappingForDeser3582Test extends BaseMapTest
+{
+ // 23-Aug-2022, tatu: Before fix, failed with 5000
+ private final static int TOO_DEEP_NESTING = 9999;
+
+ public void testArrayWrapping() throws Exception
+ {
+ final String doc = _nestedDoc(TOO_DEEP_NESTING, "[ ", "] ", "{}");
+ final ObjectMapper MAPPER = new ObjectMapper();
+ MAPPER.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
+ try {
+ MAPPER.readValue(doc, Point.class);
+ fail("Should not pass");
+ } catch (IOException e) {
+ verifyException(e, "Cannot deserialize");
+ verifyException(e, "nested JSON Array");
+ verifyException(e, "only single");
+ }
+ }
+
+ private String _nestedDoc(int nesting, String open, String close, String content) {
+ StringBuilder sb = new StringBuilder(nesting * (open.length() + close.length()));
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(open);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ sb.append("\n").append(content).append("\n");
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(close);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+}

View File

@ -1,6 +1,6 @@
Name: jackson-databind
Version: 2.9.8
Release: 9
Release: 10
Summary: General data-binding package for Jackson (2.x)
License: ASL 2.0 and LGPLv2+
URL: https://github.com/FasterXML/jackson-databind/
@ -48,6 +48,12 @@ Patch0038: CVE-2020-36179-36180-36181-36182.patch
Patch0039: CVE-2020-36183.patch
Patch0040: CVE-2021-20190.patch
Patch0041: CVE-2019-17531.patch
# https://github.com/FasterXML/jackson-databind/commit/fcfc4998ec23f0b1f7f8a9521c2b317b6c25892b
Patch0042: CVE-2020-36518.patch
# https://github.com/FasterXML/jackson-databind/commit/d78d00ee7b5245b93103fef3187f70543d67ca33
Patch0043: CVE-2022-42003.patch
# https://github.com/FasterXML/jackson-databind/commit/063183589218fec19a9293ed2f17ec53ea80ba88
Patch0044: CVE-2022-42004.patch
BuildRequires: maven-local mvn(com.fasterxml.jackson.core:jackson-annotations) >= %{version}
BuildRequires: mvn(com.fasterxml.jackson.core:jackson-core) >= %{version}
@ -100,6 +106,9 @@ rm src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest
%license LICENSE NOTICE
%changelog
* Wed Dec 13 2023 yaoxin <yao_xin001@hoperun.com> - 2.9.8-10
- Fix CVE-2020-36518,CVE-2022-42003 and CVE-2022-42004
* Fri Mar 11 2022 yaoxin <yaoxin30@huawei.com> - 2.9.8-9
- Fix CVE-2019-17531