Skip to content

Commit 94c7f73

Browse files
protobuf-github-botkarenwuz
authored andcommitted
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 b369d7d commit 94c7f73

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
@@ -1532,6 +1532,11 @@ private void mergeAny(JsonElement json, Message.Builder builder)
15321532
Message.Builder contentBuilder =
15331533
DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
15341534
WellKnownTypeParser specialParser = wellKnownTypeParsers.get(contentType.getFullName());
1535+
1536+
if (currentDepth >= recursionLimit) {
1537+
throw new InvalidProtocolBufferException("Hit recursion limit.");
1538+
}
1539+
++currentDepth;
15351540
if (specialParser != null) {
15361541
JsonElement value = object.get("value");
15371542
if (value != null) {
@@ -1540,6 +1545,7 @@ private void mergeAny(JsonElement json, Message.Builder builder)
15401545
} else {
15411546
mergeMessage(json, contentBuilder, true);
15421547
}
1548+
--currentDepth;
15431549
builder.setField(valueField, contentBuilder.build().toByteString());
15441550
}
15451551

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
@@ -1697,7 +1697,40 @@ public void testRecursionLimit() throws Exception {
16971697
parser.merge(input, builder);
16981698
assertWithMessage("Exception is expected.").fail();
16991699
} catch (InvalidProtocolBufferException e) {
1700-
// Expected.
1700+
assertThat(e).hasMessageThat().contains("recursion");
1701+
}
1702+
}
1703+
1704+
@Test
1705+
public void testRecursionLimitAnyOfAny() throws Exception {
1706+
String input =
1707+
"{\n"
1708+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1709+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1710+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1711+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\", \"value\": {\n"
1712+
+ " \"@type\": \"type.googleapis.com/google.protobuf.Any\"}\n"
1713+
+ " }\n"
1714+
+ " }\n"
1715+
+ " }\n"
1716+
+ " }\n"
1717+
+ "}\n";
1718+
1719+
JsonFormat.TypeRegistry registry =
1720+
JsonFormat.TypeRegistry.newBuilder().add(Any.getDescriptor()).build();
1721+
1722+
JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
1723+
Any.Builder builder = Any.newBuilder();
1724+
parser.merge(input, builder); // Successfully parses with no default recursion limit.
1725+
Any unused = builder.build();
1726+
1727+
parser = JsonFormat.parser().usingTypeRegistry(registry).usingRecursionLimit(3);
1728+
builder = Any.newBuilder();
1729+
try {
1730+
parser.merge(input, builder);
1731+
assertWithMessage("Exception is expected.").fail();
1732+
} catch (InvalidProtocolBufferException e) {
1733+
assertThat(e).hasMessageThat().contains("recursion");
17011734
}
17021735
}
17031736

0 commit comments

Comments
 (0)