/proc/self/cwd/test/fuzz/mutable_visitor.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "test/fuzz/mutable_visitor.h" |
2 | | |
3 | | #include <vector> |
4 | | |
5 | | #include "source/common/protobuf/utility.h" |
6 | | #include "source/common/protobuf/visitor_helper.h" |
7 | | |
8 | | #include "absl/cleanup/cleanup.h" |
9 | | #include "udpa/type/v1/typed_struct.pb.h" |
10 | | #include "xds/type/v3/typed_struct.pb.h" |
11 | | |
12 | | namespace Envoy { |
13 | | namespace ProtobufMessage { |
14 | | namespace { |
15 | | |
16 | | void traverseMessageWorkerExt(ProtoVisitor& visitor, Protobuf::Message& message, |
17 | | std::vector<const Protobuf::Message*>& parents, |
18 | | bool was_any_or_top_level, bool recurse_into_any, |
19 | 807k | absl::string_view field_name) { |
20 | 807k | visitor.onEnterMessage(message, parents, was_any_or_top_level, field_name); |
21 | 807k | absl::Cleanup message_leaver = [&visitor, &parents, &message, was_any_or_top_level, field_name] { |
22 | 807k | visitor.onLeaveMessage(message, parents, was_any_or_top_level, field_name); |
23 | 807k | }; |
24 | | |
25 | | // If told to recurse into Any messages, do that here and skip the rest of the function. |
26 | 807k | if (recurse_into_any) { |
27 | 807k | std::unique_ptr<Protobuf::Message> inner_message; |
28 | 807k | absl::string_view target_type_url; |
29 | | |
30 | 807k | if (message.GetDescriptor()->full_name() == "google.protobuf.Any") { |
31 | 12.2k | auto* any_message = Protobuf::DynamicCastToGenerated<ProtobufWkt::Any>(&message); |
32 | 12.2k | inner_message = Helper::typeUrlToMessage(any_message->type_url()); |
33 | 12.2k | target_type_url = any_message->type_url(); |
34 | 12.2k | if (inner_message) { |
35 | 9.61k | MessageUtil::unpackTo(*any_message, *inner_message); |
36 | 9.61k | } |
37 | 795k | } else if (message.GetDescriptor()->full_name() == "xds.type.v3.TypedStruct") { |
38 | 0 | std::tie(inner_message, target_type_url) = |
39 | 0 | Helper::convertTypedStruct<xds::type::v3::TypedStruct>(message); |
40 | 795k | } else if (message.GetDescriptor()->full_name() == "udpa.type.v1.TypedStruct") { |
41 | 0 | std::tie(inner_message, target_type_url) = |
42 | 0 | Helper::convertTypedStruct<udpa::type::v1::TypedStruct>(message); |
43 | 0 | } |
44 | | |
45 | 807k | if (inner_message != nullptr) { |
46 | | // Push the Any message as a wrapper. |
47 | 9.61k | Helper::ScopedMessageParents scoped_parents(parents, message); |
48 | 9.61k | traverseMessageWorkerExt(visitor, *inner_message, parents, true, recurse_into_any, |
49 | 9.61k | absl::string_view()); |
50 | 9.61k | return; |
51 | 797k | } else if (!target_type_url.empty()) { |
52 | 0 | throw EnvoyException(fmt::format("Invalid type_url '{}' during traversal", target_type_url)); |
53 | 0 | } |
54 | 807k | } |
55 | | |
56 | 797k | const Protobuf::Descriptor* descriptor = message.GetDescriptor(); |
57 | 797k | const Protobuf::Reflection* reflection = message.GetReflection(); |
58 | 3.52M | for (int i = 0; i < descriptor->field_count(); ++i) { |
59 | 2.73M | const Protobuf::FieldDescriptor* field = descriptor->field(i); |
60 | 2.73M | visitor.onField(message, *field, parents); |
61 | | |
62 | | // If this is a message, recurse in to the sub-message. |
63 | 2.73M | if (field->cpp_type() == Protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { |
64 | 1.80M | Helper::ScopedMessageParents scoped_parents(parents, message); |
65 | | |
66 | 1.80M | if (field->is_repeated()) { |
67 | 164k | const int size = reflection->FieldSize(message, field); |
68 | 491k | for (int j = 0; j < size; ++j) { |
69 | 327k | traverseMessageWorkerExt(visitor, *reflection->MutableRepeatedMessage(&message, field, j), |
70 | 327k | parents, false, recurse_into_any, field->name()); |
71 | 327k | } |
72 | 1.63M | } else if (reflection->HasField(message, field)) { |
73 | 462k | traverseMessageWorkerExt(visitor, *reflection->MutableMessage(&message, field), parents, |
74 | 462k | false, recurse_into_any, field->name()); |
75 | 462k | } |
76 | 1.80M | } |
77 | 2.73M | } |
78 | 797k | } |
79 | | |
80 | | } // namespace |
81 | | |
82 | 8.13k | void traverseMessage(ProtoVisitor& visitor, Protobuf::Message& message, bool recurse_into_any) { |
83 | 8.13k | std::vector<const Protobuf::Message*> parents; |
84 | 8.13k | traverseMessageWorkerExt(visitor, message, parents, true, recurse_into_any, "envoy"); |
85 | 8.13k | } |
86 | | |
87 | | } // namespace ProtobufMessage |
88 | | } // namespace Envoy |