Coverage Report

Created: 2023-11-12 09:30

/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