1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
32 #define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
33 
34 #include <cstddef>
35 #include <functional>
36 #include <string>
37 #include <type_traits>
38 #include <utility>
39 #include <vector>
40 
41 #include <google/protobuf/stubs/common.h>
42 #include <google/protobuf/arenastring.h>
43 #include <google/protobuf/descriptor.h>
44 #include <google/protobuf/map.h>
45 #include <google/protobuf/stubs/once.h>
46 #include <google/protobuf/repeated_field.h>
47 
48 
49 namespace google {
50 namespace protobuf {
51 namespace internal {
52 template <typename T>
53 struct ResolvedType {
54   using type = T;
55 };
56 }  // namespace internal
57 // Tracks the events of field accesses for all protos
58 // that are built with --inject_field_listener_events. This is a global
59 // interface which you must implement yourself and register with
60 // RegisterListener() function. All events consist of Descriptors,
61 // FieldAccessTypes and the underlying storage for tracking the memory which is
62 // accessed where possible and makes sense. Users are responsible for the
63 // implementations to be thread safe.
64 class FieldAccessListener {
65  public:
66   FieldAccessListener() = default;
67   virtual ~FieldAccessListener() = default;
68 
69   // The memory annotations of the proto fields that are touched by the
70   // accessors. They are returned as if the operation completes.
71   struct DataAnnotation {
72     DataAnnotation() = default;
DataAnnotationDataAnnotation73     DataAnnotation(const void* other_address, size_t other_size)
74         : address(other_address), size(other_size) {}
75     const void* address = nullptr;
76     size_t size = 0;
77   };
78   using AddressInfo = std::vector<DataAnnotation>;
79   using AddressInfoExtractor = std::function<AddressInfo()>;
80 
81   enum class FieldAccessType {
82     kAdd,          // add_<field>(f)
83     kAddMutable,   // add_<field>()
84     kGet,          // <field>() and <repeated_field>(i)
85     kClear,        // clear_<field>()
86     kHas,          // has_<field>()
87     kList,         // <repeated_field>()
88     kMutable,      // mutable_<field>()
89     kMutableList,  // mutable_<repeated_field>()
90     kRelease,      // release_<field>()
91     kSet,          // set_<field>() and set_<repeated_field>(i)
92     kSize,         // <repeated_field>_size()
93   };
94 
95   static FieldAccessListener* GetListener();
96 
97   // Registers the field listener, can be called only once, |listener| must
98   // outlive all proto accesses (in most cases, the lifetime of the program).
99   static void RegisterListener(FieldAccessListener* listener);
100 
101   // All field accessors noted in FieldAccessType have this call.
102   // |extractor| extracts the address info from the field
103   virtual void OnFieldAccess(const AddressInfoExtractor& extractor,
104                              const FieldDescriptor* descriptor,
105                              FieldAccessType access_type) = 0;
106 
107   // Side effect calls.
108   virtual void OnDeserializationAccess(const Message* message) = 0;
109   virtual void OnSerializationAccess(const Message* message) = 0;
110   virtual void OnReflectionAccess(const Descriptor* descriptor) = 0;
111   virtual void OnByteSizeAccess(const Message* message) = 0;
112   // We can probably add more if we need to, like {Merge,Copy}{From}Access.
113 
114   // Extracts all the addresses from the underlying fields.
115   template <typename T>
116   AddressInfo ExtractFieldInfo(const T* field_value);
117 
118 
119  private:
120   template <typename T>
121   AddressInfo ExtractFieldInfoSpecific(const T* field_value,
122                                        internal::ResolvedType<T>);
123 
124   AddressInfo ExtractFieldInfoSpecific(const Message* field_value,
125                                        internal::ResolvedType<Message>);
126 
127   AddressInfo ExtractFieldInfoSpecific(const std::string* field_value,
128                                        internal::ResolvedType<std::string>);
129 
130   AddressInfo ExtractFieldInfoSpecific(
131       const internal::ArenaStringPtr* field_value,
132       internal::ResolvedType<internal::ArenaStringPtr>);
133 
134   template <typename T>
135   AddressInfo ExtractFieldInfoSpecific(
136       const RepeatedField<T>* field_value,
137       internal::ResolvedType<RepeatedField<T>>);
138 
139   template <typename T>
140   AddressInfo ExtractFieldInfoSpecific(
141       const RepeatedPtrField<T>* field_value,
142       internal::ResolvedType<RepeatedPtrField<T>>);
143 
144   template <typename K, typename V>
145   AddressInfo ExtractFieldInfoSpecific(const Map<K, V>* field_value,
146                                        internal::ResolvedType<Map<K, V>>);
147 
148   static internal::once_flag register_once_;
149   static FieldAccessListener* field_listener_;
150   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldAccessListener);
151 };
152 
153 template <typename T>
ExtractFieldInfo(const T * field_value)154 inline FieldAccessListener::AddressInfo FieldAccessListener::ExtractFieldInfo(
155     const T* field_value) {
156   return ExtractFieldInfoSpecific(field_value, internal::ResolvedType<T>());
157 }
158 
159 
160 template <typename T>
161 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const T * field_value,internal::ResolvedType<T>)162 FieldAccessListener::ExtractFieldInfoSpecific(const T* field_value,
163                                               internal::ResolvedType<T>) {
164   static_assert(std::is_trivial<T>::value,
165                 "This overload should be chosen only for trivial types");
166   return FieldAccessListener::AddressInfo{FieldAccessListener::DataAnnotation(
167       static_cast<const void*>(field_value), sizeof(*field_value))};
168 }
169 
170 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const std::string * field_value,internal::ResolvedType<std::string>)171 FieldAccessListener::ExtractFieldInfoSpecific(
172     const std::string* field_value, internal::ResolvedType<std::string>) {
173   return FieldAccessListener::AddressInfo{FieldAccessListener::DataAnnotation(
174       static_cast<const void*>(field_value->c_str()), field_value->length())};
175 }
176 
177 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const internal::ArenaStringPtr * field_value,internal::ResolvedType<internal::ArenaStringPtr>)178 FieldAccessListener::ExtractFieldInfoSpecific(
179     const internal::ArenaStringPtr* field_value,
180     internal::ResolvedType<internal::ArenaStringPtr>) {
181   return FieldAccessListener::ExtractFieldInfoSpecific(
182       field_value->GetPointer(), internal::ResolvedType<std::string>());
183 }
184 
185 template <typename T>
186 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const RepeatedField<T> * field_value,internal::ResolvedType<RepeatedField<T>>)187 FieldAccessListener::ExtractFieldInfoSpecific(
188     const RepeatedField<T>* field_value,
189     internal::ResolvedType<RepeatedField<T>>) {
190   // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
191   FieldAccessListener::AddressInfo address_info;
192   address_info.reserve(field_value->size());
193   for (int i = 0, ie = field_value->size(); i < ie; ++i) {
194     auto sub = ExtractFieldInfoSpecific(&field_value->Get(i),
195                                         internal::ResolvedType<T>());
196     address_info.insert(address_info.end(), sub.begin(), sub.end());
197   }
198   return address_info;
199 }
200 
201 template <typename T>
202 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const RepeatedPtrField<T> * field_value,internal::ResolvedType<RepeatedPtrField<T>>)203 FieldAccessListener::ExtractFieldInfoSpecific(
204     const RepeatedPtrField<T>* field_value,
205     internal::ResolvedType<RepeatedPtrField<T>>) {
206   FieldAccessListener::AddressInfo address_info;
207   // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
208   address_info.reserve(field_value->size());
209   for (int i = 0, ie = field_value->size(); i < ie; ++i) {
210     auto sub = ExtractFieldInfoSpecific(&field_value->Get(i),
211                                         internal::ResolvedType<T>());
212     address_info.insert(address_info.end(), sub.begin(), sub.end());
213   }
214   return address_info;
215 }
216 
217 template <typename K, typename V>
218 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const Map<K,V> * field_value,internal::ResolvedType<Map<K,V>>)219 FieldAccessListener::ExtractFieldInfoSpecific(
220     const Map<K, V>* field_value, internal::ResolvedType<Map<K, V>>) {
221   // TODO(jianzhouzh): This can cause data races. Synchronize this if needed.
222   FieldAccessListener::AddressInfo address_info;
223   address_info.reserve(field_value->size());
224   for (auto it = field_value->begin(); it != field_value->end(); ++it) {
225     auto sub_first =
226         ExtractFieldInfoSpecific(&it->first, internal::ResolvedType<K>());
227     auto sub_second =
228         ExtractFieldInfoSpecific(&it->second, internal::ResolvedType<V>());
229     address_info.insert(address_info.end(), sub_first.begin(), sub_first.end());
230     address_info.insert(address_info.end(), sub_second.begin(),
231                         sub_second.end());
232   }
233   return address_info;
234 }
235 
236 inline FieldAccessListener::AddressInfo
ExtractFieldInfoSpecific(const Message * field_value,internal::ResolvedType<Message>)237 FieldAccessListener::ExtractFieldInfoSpecific(const Message* field_value,
238                                               internal::ResolvedType<Message>) {
239   // TODO(jianzhouzh): implement and adjust all annotations in the compiler.
240   return {};
241 }
242 
243 }  // namespace protobuf
244 }  // namespace google
245 
246 #endif  // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__
247