Skip to content

Commit 33b16e8

Browse files
Correctly apply JSON recursion limit when parsing an Any-of-Any.
Without this check, an any-of-any-of-any-of-... wouldn't apply the recursion check as intended and cound be arbitrarily deep. Fixes #25071 PiperOrigin-RevId: 850485466
1 parent d6d1407 commit 33b16e8

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

java/util/src/main/java/com/google/protobuf/util/JsonFormat.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,11 @@ private void mergeAny(JsonElement json, Message.Builder builder)
15271527
Message.Builder contentBuilder =
15281528
DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
15291529
WellKnownTypeParser specialParser = wellKnownTypeParsers.get(contentType.getFullName());
1530+
1531+
if (currentDepth >= recursionLimit) {
1532+
throw new InvalidProtocolBufferException("Hit recursion limit.");
1533+
}
1534+
++currentDepth;
15301535
if (specialParser != null) {
15311536
JsonElement value = object.get("value");
15321537
if (value != null) {
@@ -1535,6 +1540,7 @@ private void mergeAny(JsonElement json, Message.Builder builder)
15351540
} else {
15361541
mergeMessage(json, contentBuilder, true);
15371542
}
1543+
--currentDepth;
15381544
builder.setField(valueField, contentBuilder.build().toByteString());
15391545
}
15401546

java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,40 @@ public void testRecursionLimit() throws Exception {
17121712
parser.merge(input, builder);
17131713
assertWithMessage("Exception is expected.").fail();
17141714
} catch (InvalidProtocolBufferException e) {
1715-
// Expected.
1715+
assertThat(e).hasMessageThat().contains("recursion");
1716+
}
1717+
}
1718+
1719+
@Test
1720+
public void testRecursionLimitAnyOfAny() throws Exception {
1721+
String input =
1722+
"{\n"
1723+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1724+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1725+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1726+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1727+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\"}\n"
1728+
+ " }\n"
1729+
+ " }\n"
1730+
+ " }\n"
1731+
+ " }\n"
1732+
+ "}\n";
1733+
1734+
JsonFormat.TypeRegistry registry =
1735+
JsonFormat.TypeRegistry.newBuilder().add(Any.getDescriptor()).build();
1736+
1737+
JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
1738+
Any.Builder builder = Any.newBuilder();
1739+
parser.merge(input, builder); // Successfully parses with no default recursion limit.
1740+
Any unused = builder.build();
1741+
1742+
parser = JsonFormat.parser().usingTypeRegistry(registry).usingRecursionLimit(3);
1743+
builder = Any.newBuilder();
1744+
try {
1745+
parser.merge(input, builder);
1746+
assertWithMessage("Exception is expected.").fail();
1747+
} catch (InvalidProtocolBufferException e) {
1748+
assertThat(e).hasMessageThat().contains("recursion");
17161749
}
17171750
}
17181751

0 commit comments

Comments
 (0)