Coverage Report

Created: 2024-09-19 09:45

/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
1.24M
                              absl::string_view field_name) {
20
1.24M
  visitor.onEnterMessage(message, parents, was_any_or_top_level, field_name);
21
1.24M
  absl::Cleanup message_leaver = [&visitor, &parents, &message, was_any_or_top_level, field_name] {
22
1.24M
    visitor.onLeaveMessage(message, parents, was_any_or_top_level, field_name);
23
1.24M
  };
24
25
  // If told to recurse into Any messages, do that here and skip the rest of the function.
26
1.24M
  if (recurse_into_any) {
27
1.24M
    std::unique_ptr<Protobuf::Message> inner_message;
28
1.24M
    absl::string_view target_type_url;
29
30
1.24M
    if (message.GetDescriptor()->full_name() == "google.protobuf.Any") {
31
13.1k
      auto* any_message = Protobuf::DynamicCastToGenerated<ProtobufWkt::Any>(&message);
32
13.1k
      inner_message = Helper::typeUrlToMessage(any_message->type_url());
33
13.1k
      target_type_url = any_message->type_url();
34
13.1k
      if (inner_message) {
35
10.7k
        THROW_IF_NOT_OK(MessageUtil::unpackTo(*any_message, *inner_message));
36
10.7k
      }
37
1.22M
    } 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).value();
40
1.22M
    } 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)).value();
43
0
    }
44
45
1.24M
    if (inner_message != nullptr) {
46
      // Push the Any message as a wrapper.
47
10.7k
      Helper::ScopedMessageParents scoped_parents(parents, message);
48
10.7k
      traverseMessageWorkerExt(visitor, *inner_message, parents, true, recurse_into_any,
49
10.7k
                               absl::string_view());
50
10.7k
      return;
51
1.23M
    } else if (!target_type_url.empty()) {
52
0
      throw EnvoyException(fmt::format("Invalid type_url '{}' during traversal", target_type_url));
53
0
    }
54
1.24M
  }
55
56
1.23M
  const Protobuf::Descriptor* descriptor = message.GetDescriptor();
57
1.23M
  const Protobuf::Reflection* reflection = message.GetReflection();
58
5.90M
  for (int i = 0; i < descriptor->field_count(); ++i) {
59
4.67M
    const Protobuf::FieldDescriptor* field = descriptor->field(i);
60
4.67M
    visitor.onField(message, *field, parents);
61
62
    // If this is a message, recurse in to the sub-message.
63
4.67M
    if (field->cpp_type() == Protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
64
3.06M
      Helper::ScopedMessageParents scoped_parents(parents, message);
65
66
3.06M
      if (field->is_repeated()) {
67
381k
        const int size = reflection->FieldSize(message, field);
68
877k
        for (int j = 0; j < size; ++j) {
69
495k
          traverseMessageWorkerExt(visitor, *reflection->MutableRepeatedMessage(&message, field, j),
70
495k
                                   parents, false, recurse_into_any, field->name());
71
495k
        }
72
2.67M
      } else if (reflection->HasField(message, field)) {
73
726k
        traverseMessageWorkerExt(visitor, *reflection->MutableMessage(&message, field), parents,
74
726k
                                 false, recurse_into_any, field->name());
75
726k
      }
76
3.06M
    }
77
4.67M
  }
78
1.23M
}
79
80
} // namespace
81
82
8.40k
void traverseMessage(ProtoVisitor& visitor, Protobuf::Message& message, bool recurse_into_any) {
83
8.40k
  std::vector<const Protobuf::Message*> parents;
84
8.40k
  traverseMessageWorkerExt(visitor, message, parents, true, recurse_into_any, "envoy");
85
8.40k
}
86
87
} // namespace ProtobufMessage
88
} // namespace Envoy