Skip to content

Commit

Permalink
Fix string-based creators with UNWRAP_SINGLE_VALUE_ARRAYS
Browse files Browse the repository at this point in the history
- it seems that the DoS fix in `BeanDeserializer` incorrectly advanced the parser. I've fixed this, but this is potentially security-sensitive, so please take a careful look if this is right :)
- I also changed `FactoryBasedEnumDeserializer` to handle unwrapping of strings properly. I haven't touched  the error handling when there is another token, that is handled by the branch with the comment `Could argue we should throw an exception but...`. imo that should throw an exception, can we change that in a minor release?

Fixes FasterXML#3655
  • Loading branch information
yawkat committed Nov 15, 2022
1 parent 960b91c commit 8015834
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,8 @@ protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt
final boolean unwrap = ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);

if (unwrap || (act != CoercionAction.Fail)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
JsonToken unwrappedToken = p.nextToken();
if (unwrappedToken == JsonToken.END_ARRAY) {
switch (act) {
case AsEmpty:
return getEmptyValue(ctxt);
Expand All @@ -631,7 +631,7 @@ protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt
if (unwrap) {
// 23-Aug-2022, tatu: To prevent unbounded nested arrays, we better
// check there is NOT another START_ARRAY lurking there..
if (p.nextToken() == JsonToken.START_ARRAY) {
if (unwrappedToken == JsonToken.START_ARRAY) {
JavaType targetType = getValueType(ctxt);
return ctxt.handleUnexpectedToken(targetType, JsonToken.START_ARRAY, p,
"Cannot deserialize value of type %s from deeply-nested Array: only single wrapper allowed with `%s`",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,23 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
// 14-Jan-2022, tatu: as per [databind#3369] need to consider structured
// value types (Object, Array) as well.
JsonToken t = p.currentToken();
boolean unwrapping = false;
if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
t = p.nextToken();
unwrapping = true;
}
if ((t != null) && !t.isScalarValue()) {
// Could argue we should throw an exception but...
value = "";
p.skipChildren();
} else {
value = p.getValueAsString();
}
if (unwrapping) {
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
}
} else { // zero-args; just skip whatever value there may be
p.skipChildren();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ private TestEnumFromInt(int id) {
}
}

protected enum TestEnumFromString
{
ENUM_A, ENUM_B, ENUM_C;

@JsonCreator public static TestEnumFromString fromId(String id) {
return valueOf(id);
}
}

static enum EnumWithPropertiesModeJsonCreator {
TEST1,
TEST2,
Expand Down Expand Up @@ -344,4 +353,24 @@ public void testPropertyCreatorEnum3280() throws Exception
assertEquals(Enum3280.x, r.readValue("{\"a\":[], \"b\":\"x\"}"));
assertEquals(Enum3280.x, r.readValue("{\"a\":{}, \"b\":\"x\"}"));
}

// for [databind#3655]
public void testEnumsFromIntsUnwrapped() throws Exception
{
Object ob = newJsonMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
.readValue("[1]", TestEnumFromInt.class);
assertEquals(TestEnumFromInt.class, ob.getClass());
assertSame(TestEnumFromInt.ENUM_A, ob);
}

// for [databind#3655]
public void testEnumsFromStringUnwrapped() throws Exception
{
Object ob = newJsonMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
.readValue("[\"ENUM_A\"]", TestEnumFromString.class);
assertEquals(TestEnumFromString.class, ob.getClass());
assertSame(TestEnumFromString.ENUM_A, ob);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,12 @@ public void testDeserializationFromString() throws Exception {
assertEquals("DELEG:testProduct",
MAPPER.readValue(q("testProduct"), Product1853.class).getName());
}

public void testDeserializationFromWrappedString() throws Exception {
assertEquals("DELEG:testProduct",
newJsonMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
.readValue("[\"testProduct\"]", Product1853.class).getName());
}
}

0 comments on commit 8015834

Please sign in to comment.