Avoid checking the recursion when fields domains are customized through the policy. We already avoid recursion checks when individual fields are customized, but the field domain customization can happen through the policy. We don't need to check for recursion in such cases, because the recursion will be checked inside the inner domain. PiperOrigin-RevId: 561046789
diff --git a/doc/domains-reference.md b/doc/domains-reference.md index 504ddcb..fa3c30a 100644 --- a/doc/domains-reference.md +++ b/doc/domains-reference.md
@@ -508,9 +508,9 @@ Notice that `With[Optional|Repeated]Fields[Unset|AlwaysSet]` and `WithRepeatedFields[Min|Max]?Size` work recursively and apply to subprotos as -well, but calling `With[Optional|Repeated]FieldsAlwaysSet` or -`WithRepeatedFields[Min]?Size(X)` with `X > 0` on recursively defined protos -causes a failure. +well, unless subproto domains are explicitly defined. Also, calling +`With[Optional|Repeated]FieldsAlwaysSet` or `WithRepeatedFields[Min]?Size(X)` +with `X > 0` on recursively defined protos causes a failure. #### Customizing Oneof Fields
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc index 7e25074..070451e 100644 --- a/e2e_tests/functional_test.cc +++ b/e2e_tests/functional_test.cc
@@ -533,16 +533,6 @@ EXPECT_THAT(status, Eq(ExitCode(0))); } -TEST(UnitTestModeTest, - FailsWithFalsePositiveRecursiveCheckIfRequiredSubDomainsAreEmpty) { - auto [status, std_out, std_err] = - RunWith(GetGTestFilterFlag("MySuite.FailsIfProtoIsDetectedAsRecursive")); - // TODO(b/297064918): FailsIfProtoIsDetectedAsRecursive should pass, and we - // should assert ExitCode(0). - EXPECT_THAT(status, Eq(Signal(SIGABRT))); - EXPECT_THAT(std_err, HasSubstr("recursive fields")); -} - TEST(UnitTestModeTest, DetectsRecursiveStructureIfOptionalsSetByDefault) { auto [status, std_out, std_err] = RunWith(GetGTestFilterFlag("MySuite.FailsIfCantInitializeProto"));
diff --git a/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc b/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc index 93d06c7..a74a24d 100644 --- a/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc +++ b/e2e_tests/testdata/fuzz_tests_for_functional_testing.cc
@@ -418,15 +418,6 @@ return absl::StrContains(field->name(), "parent"); } -// TODO(b/297064918): The runtime will claim that the domain below is recursive, -// even though the recursive chain has been capped with an arbitrary proto. -void FailsIfProtoIsDetectedAsRecursive(const IRObjectTestProto& proto) {} -FUZZ_TEST(MySuite, FailsIfProtoIsDetectedAsRecursive) - .WithDomains( - Arbitrary<IRObjectTestProto>() - .WithFieldsAlwaysSet() - .WithRepeatedProtobufFields(Arbitrary<IRObjectTestProto>())); - void FailsIfCantInitializeProto(const TestProtobufWithRecursion& proto) {} FUZZ_TEST(MySuite, FailsIfCantInitializeProto) .WithDomains(Arbitrary<TestProtobufWithRecursion>() @@ -446,8 +437,10 @@ .WithProtobufField( "child", Arbitrary<TestProtobufWithRecursion::ChildProto>() - .WithOptionalFieldsUnset(IsInt32) - .WithOptionalFieldsAlwaysSet(IsParent))); + .WithFieldsAlwaysSet() + .WithProtobufFields( + IsParent, + Arbitrary<TestProtobufWithRecursion>()))); bool AreRepeatedFieldsSizesCorrect(absl::FunctionRef<bool(int)> is_size_correct, const TestProtobuf& proto) {
diff --git a/fuzztest/internal/domains/protobuf_domain_impl.h b/fuzztest/internal/domains/protobuf_domain_impl.h index f6c1249..8f1115c 100644 --- a/fuzztest/internal/domains/protobuf_domain_impl.h +++ b/fuzztest/internal/domains/protobuf_domain_impl.h
@@ -1433,6 +1433,11 @@ if (field->containing_oneof()) continue; const auto* child = field->message_type(); if (!child) continue; + if (policy_.GetDefaultDomainForProtobufs(field) != std::nullopt) { + // If this field is recursive, it will be detected when initializing + // its default domain. Otherwise, this field can always be set safely. + continue; + } if (consider_non_terminating_recursions) { const bool should_be_set = IsRequired(field) ||