1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include "google/protobuf/unknown_field_set.h"
13
14 #include <cstring>
15 #include <string>
16 #include <utility>
17
18 #include "absl/log/absl_check.h"
19 #include "absl/strings/cord.h"
20 #include "absl/strings/internal/resize_uninitialized.h"
21 #include "absl/strings/string_view.h"
22 #include "google/protobuf/extension_set.h"
23 #include "google/protobuf/generated_message_tctable_impl.h"
24 #include "google/protobuf/io/coded_stream.h"
25 #include "google/protobuf/io/zero_copy_stream.h"
26 #include "google/protobuf/io/zero_copy_stream_impl.h"
27 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
28 #include "google/protobuf/parse_context.h"
29 #include "google/protobuf/wire_format.h"
30 #include "google/protobuf/wire_format_lite.h"
31
32 // Must be included last.
33 #include "google/protobuf/port_def.inc"
34
35 namespace google {
36 namespace protobuf {
37
ClearFallback()38 void UnknownFieldSet::ClearFallback() {
39 ABSL_DCHECK(!fields_.empty());
40 if (arena() == nullptr) {
41 int n = fields_.size();
42 do {
43 (fields_)[--n].Delete();
44 } while (n > 0);
45 }
46 fields_.Clear();
47 }
48
MergeFrom(const UnknownFieldSet & other)49 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
50 int other_field_count = other.field_count();
51 if (other_field_count > 0) {
52 fields_.Reserve(fields_.size() + other_field_count);
53 for (auto elem : other.fields_) {
54 fields_.Add(elem.DeepCopy(arena()));
55 }
56 }
57 }
58
59 // A specialized MergeFrom for performance when we are merging from an UFS that
60 // is temporary and can be destroyed in the process.
MergeFromAndDestroy(UnknownFieldSet * other)61 void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
62 if (arena() != other->arena()) {
63 MergeFrom(*other);
64 } else if (fields_.empty()) {
65 fields_.Swap(&other->fields_);
66 } else {
67 fields_.MergeFrom(other->fields_);
68 other->fields_.Clear();
69 }
70 }
71
MergeToInternalMetadata(const UnknownFieldSet & other,internal::InternalMetadata * metadata)72 void UnknownFieldSet::MergeToInternalMetadata(
73 const UnknownFieldSet& other, internal::InternalMetadata* metadata) {
74 metadata->mutable_unknown_fields<UnknownFieldSet>()->MergeFrom(other);
75 }
76
SpaceUsedExcludingSelfLong() const77 size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const {
78 if (fields_.empty()) return 0;
79
80 size_t total_size = fields_.SpaceUsedExcludingSelfLong();
81
82 for (const UnknownField& field : fields_) {
83 switch (field.type()) {
84 case UnknownField::TYPE_LENGTH_DELIMITED:
85 total_size += sizeof(*field.data_.string_value) +
86 internal::StringSpaceUsedExcludingSelfLong(
87 *field.data_.string_value);
88 break;
89 case UnknownField::TYPE_GROUP:
90 total_size += field.data_.group_->SpaceUsedLong();
91 break;
92 default:
93 break;
94 }
95 }
96 return total_size;
97 }
98
SpaceUsedLong() const99 size_t UnknownFieldSet::SpaceUsedLong() const {
100 return sizeof(*this) + SpaceUsedExcludingSelf();
101 }
102
AddVarint(int number,uint64_t value)103 void UnknownFieldSet::AddVarint(int number, uint64_t value) {
104 auto& field = *fields_.Add();
105 field.number_ = number;
106 field.SetType(UnknownField::TYPE_VARINT);
107 field.data_.varint_ = value;
108 }
109
AddFixed32(int number,uint32_t value)110 void UnknownFieldSet::AddFixed32(int number, uint32_t value) {
111 auto& field = *fields_.Add();
112 field.number_ = number;
113 field.SetType(UnknownField::TYPE_FIXED32);
114 field.data_.fixed32_ = value;
115 }
116
AddFixed64(int number,uint64_t value)117 void UnknownFieldSet::AddFixed64(int number, uint64_t value) {
118 auto& field = *fields_.Add();
119 field.number_ = number;
120 field.SetType(UnknownField::TYPE_FIXED64);
121 field.data_.fixed64_ = value;
122 }
123
AddLengthDelimited(int number,const absl::Cord & value)124 void UnknownFieldSet::AddLengthDelimited(int number, const absl::Cord& value) {
125 absl::CopyCordToString(value, AddLengthDelimited(number));
126 }
127
128 template <int&...>
AddLengthDelimited(int number,std::string && value)129 void UnknownFieldSet::AddLengthDelimited(int number, std::string&& value) {
130 auto& field = *fields_.Add();
131 field.number_ = number;
132 field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
133 field.data_.string_value =
134 Arena::Create<std::string>(arena(), std::move(value));
135 }
136 template void UnknownFieldSet::AddLengthDelimited(int, std::string&&);
137
AddLengthDelimited(int number)138 std::string* UnknownFieldSet::AddLengthDelimited(int number) {
139 auto& field = *fields_.Add();
140 field.number_ = number;
141 field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
142 field.data_.string_value = Arena::Create<std::string>(arena());
143 return field.data_.string_value;
144 }
145
AddGroup(int number)146 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
147 auto& field = *fields_.Add();
148 field.number_ = number;
149 field.SetType(UnknownField::TYPE_GROUP);
150 field.data_.group_ = Arena::Create<UnknownFieldSet>(arena());
151 return field.data_.group_;
152 }
153
AddField(const UnknownField & field)154 void UnknownFieldSet::AddField(const UnknownField& field) {
155 fields_.Add(field.DeepCopy(arena()));
156 }
157
DeleteSubrange(int start,int num)158 void UnknownFieldSet::DeleteSubrange(int start, int num) {
159 if (arena() == nullptr) {
160 // Delete the specified fields.
161 for (int i = 0; i < num; ++i) {
162 (fields_)[i + start].Delete();
163 }
164 }
165 fields_.ExtractSubrange(start, num, nullptr);
166 }
167
DeleteByNumber(int number)168 void UnknownFieldSet::DeleteByNumber(int number) {
169 size_t left = 0; // The number of fields left after deletion.
170 for (size_t i = 0; i < fields_.size(); ++i) {
171 UnknownField* field = &(fields_)[i];
172 if (field->number() == number) {
173 if (arena() == nullptr) {
174 field->Delete();
175 }
176 } else {
177 if (i != left) {
178 (fields_)[left] = (fields_)[i];
179 }
180 ++left;
181 }
182 }
183 fields_.Truncate(left);
184 }
185
MergeFromCodedStream(io::CodedInputStream * input)186 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
187 UnknownFieldSet other;
188 if (internal::WireFormat::SkipMessage(input, &other) &&
189 input->ConsumedEntireMessage()) {
190 MergeFromAndDestroy(&other);
191 return true;
192 } else {
193 return false;
194 }
195 }
196
ParseFromCodedStream(io::CodedInputStream * input)197 bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
198 Clear();
199 return MergeFromCodedStream(input);
200 }
201
ParseFromZeroCopyStream(io::ZeroCopyInputStream * input)202 bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
203 io::CodedInputStream coded_input(input);
204 return (ParseFromCodedStream(&coded_input) &&
205 coded_input.ConsumedEntireMessage());
206 }
207
ParseFromArray(const void * data,int size)208 bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
209 io::ArrayInputStream input(data, size);
210 return ParseFromZeroCopyStream(&input);
211 }
212
SerializeToString(std::string * output) const213 bool UnknownFieldSet::SerializeToString(std::string* output) const {
214 const size_t size =
215 google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this);
216 absl::strings_internal::STLStringResizeUninitializedAmortized(output, size);
217 google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
218 *this, reinterpret_cast<uint8_t*>(const_cast<char*>(output->data())));
219 return true;
220 }
221
SerializeToCodedStream(io::CodedOutputStream * output) const222 bool UnknownFieldSet::SerializeToCodedStream(
223 io::CodedOutputStream* output) const {
224 google::protobuf::internal::WireFormat::SerializeUnknownFields(*this, output);
225 return !output->HadError();
226 }
227
SerializeToCord(absl::Cord * output) const228 bool UnknownFieldSet::SerializeToCord(absl::Cord* output) const {
229 const size_t size =
230 google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this);
231 io::CordOutputStream cord_output_stream(size);
232 {
233 io::CodedOutputStream coded_output_stream(&cord_output_stream);
234 if (!SerializeToCodedStream(&coded_output_stream)) return false;
235 }
236 *output = cord_output_stream.Consume();
237 return true;
238 }
239
Delete()240 void UnknownField::Delete() {
241 switch (type()) {
242 case UnknownField::TYPE_LENGTH_DELIMITED:
243 delete data_.string_value;
244 break;
245 case UnknownField::TYPE_GROUP:
246 delete data_.group_;
247 break;
248 default:
249 break;
250 }
251 }
252
DeepCopy(Arena * arena) const253 UnknownField UnknownField::DeepCopy(Arena* arena) const {
254 UnknownField copy = *this;
255 switch (type()) {
256 case UnknownField::TYPE_LENGTH_DELIMITED:
257 copy.data_.string_value =
258 Arena::Create<std::string>(arena, *data_.string_value);
259 break;
260 case UnknownField::TYPE_GROUP: {
261 UnknownFieldSet* group = Arena::Create<UnknownFieldSet>(arena);
262 group->MergeFrom(*data_.group_);
263 copy.data_.group_ = group;
264 break;
265 }
266 default:
267 break;
268 }
269 return copy;
270 }
271
SwapSlow(UnknownFieldSet * other)272 void UnknownFieldSet::SwapSlow(UnknownFieldSet* other) {
273 UnknownFieldSet tmp;
274 tmp.MergeFrom(*this);
275 this->Clear();
276 this->MergeFrom(*other);
277 other->Clear();
278 other->MergeFrom(tmp);
279 }
280
InternalSerializeLengthDelimitedNoTag(uint8_t * target,io::EpsCopyOutputStream * stream) const281 uint8_t* UnknownField::InternalSerializeLengthDelimitedNoTag(
282 uint8_t* target, io::EpsCopyOutputStream* stream) const {
283 ABSL_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
284 const absl::string_view data = *data_.string_value;
285 target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
286 target = stream->WriteRaw(data.data(), data.size(), target);
287 return target;
288 }
289
290 namespace internal {
291
292 class UnknownFieldParserHelper {
293 public:
UnknownFieldParserHelper(UnknownFieldSet * unknown)294 explicit UnknownFieldParserHelper(UnknownFieldSet* unknown)
295 : unknown_(unknown) {}
296
AddVarint(uint32_t num,uint64_t value)297 void AddVarint(uint32_t num, uint64_t value) {
298 unknown_->AddVarint(num, value);
299 }
AddFixed64(uint32_t num,uint64_t value)300 void AddFixed64(uint32_t num, uint64_t value) {
301 unknown_->AddFixed64(num, value);
302 }
ParseLengthDelimited(uint32_t num,const char * ptr,ParseContext * ctx)303 const char* ParseLengthDelimited(uint32_t num, const char* ptr,
304 ParseContext* ctx) {
305 std::string* s = unknown_->AddLengthDelimited(num);
306 int size = ReadSize(&ptr);
307 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
308 return ctx->ReadString(ptr, size, s);
309 }
ParseGroup(uint32_t num,const char * ptr,ParseContext * ctx)310 const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) {
311 return ctx->ParseGroupInlined(ptr, num * 8 + 3, [&](const char* ptr) {
312 UnknownFieldParserHelper child(unknown_->AddGroup(num));
313 return WireFormatParser(child, ptr, ctx);
314 });
315 }
AddFixed32(uint32_t num,uint32_t value)316 void AddFixed32(uint32_t num, uint32_t value) {
317 unknown_->AddFixed32(num, value);
318 }
319
320 private:
321 UnknownFieldSet* unknown_;
322 };
323
UnknownGroupParse(UnknownFieldSet * unknown,const char * ptr,ParseContext * ctx)324 const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr,
325 ParseContext* ctx) {
326 UnknownFieldParserHelper field_parser(unknown);
327 return WireFormatParser(field_parser, ptr, ctx);
328 }
329
UnknownFieldParse(uint64_t tag,UnknownFieldSet * unknown,const char * ptr,ParseContext * ctx)330 const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown,
331 const char* ptr, ParseContext* ctx) {
332 UnknownFieldParserHelper field_parser(unknown);
333 return FieldParser(tag, field_parser, ptr, ctx);
334 }
335
336 } // namespace internal
337 } // namespace protobuf
338 } // namespace google
339
340 #include "google/protobuf/port_undef.inc"
341