Line data Source code
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 : // Authors: wink@google.com (Wink Saville),
32 : // kenton@google.com (Kenton Varda)
33 : // Based on original Protocol Buffers design by
34 : // Sanjay Ghemawat, Jeff Dean, and others.
35 :
36 : #include <google/protobuf/message_lite.h>
37 : #include <google/protobuf/arena.h>
38 : #include <google/protobuf/repeated_field.h>
39 : #include <string>
40 : #include <google/protobuf/stubs/logging.h>
41 : #include <google/protobuf/stubs/common.h>
42 : #include <google/protobuf/io/coded_stream.h>
43 : #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
44 : #include <google/protobuf/stubs/stl_util.h>
45 :
46 : namespace google {
47 : namespace protobuf {
48 :
49 7686911 : MessageLite::~MessageLite() {}
50 :
51 0 : string MessageLite::InitializationErrorString() const {
52 0 : return "(cannot determine missing fields for lite message)";
53 : }
54 :
55 : namespace {
56 :
57 : // When serializing, we first compute the byte size, then serialize the message.
58 : // If serialization produces a different number of bytes than expected, we
59 : // call this function, which crashes. The problem could be due to a bug in the
60 : // protobuf implementation but is more likely caused by concurrent modification
61 : // of the message. This function attempts to distinguish between the two and
62 : // provide a useful error message.
63 0 : void ByteSizeConsistencyError(int byte_size_before_serialization,
64 : int byte_size_after_serialization,
65 : int bytes_produced_by_serialization) {
66 0 : GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
67 0 : << "Protocol message was modified concurrently during serialization.";
68 0 : GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
69 : << "Byte size calculation and serialization were inconsistent. This "
70 : "may indicate a bug in protocol buffers or it may be caused by "
71 0 : "concurrent modification of the message.";
72 0 : GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
73 0 : }
74 :
75 0 : string InitializationErrorMessage(const char* action,
76 : const MessageLite& message) {
77 : // Note: We want to avoid depending on strutil in the lite library, otherwise
78 : // we'd use:
79 : //
80 : // return strings::Substitute(
81 : // "Can't $0 message of type \"$1\" because it is missing required "
82 : // "fields: $2",
83 : // action, message.GetTypeName(),
84 : // message.InitializationErrorString());
85 :
86 : string result;
87 : result += "Can't ";
88 : result += action;
89 : result += " message of type \"";
90 0 : result += message.GetTypeName();
91 : result += "\" because it is missing required fields: ";
92 0 : result += message.InitializationErrorString();
93 0 : return result;
94 : }
95 :
96 : // Several of the Parse methods below just do one thing and then call another
97 : // method. In a naive implementation, we might have ParseFromString() call
98 : // ParseFromArray() which would call ParseFromZeroCopyStream() which would call
99 : // ParseFromCodedStream() which would call MergeFromCodedStream() which would
100 : // call MergePartialFromCodedStream(). However, when parsing very small
101 : // messages, every function call introduces significant overhead. To avoid
102 : // this without reproducing code, we use these forced-inline helpers.
103 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
104 : io::CodedInputStream* input, MessageLite* message);
105 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
106 : io::CodedInputStream* input, MessageLite* message);
107 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
108 : io::CodedInputStream* input, MessageLite* message);
109 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
110 : const void* data, int size, MessageLite* message);
111 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
112 : const void* data, int size, MessageLite* message);
113 :
114 : inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
115 : MessageLite* message) {
116 2795551 : if (!message->MergePartialFromCodedStream(input)) return false;
117 2795949 : if (!message->IsInitialized()) {
118 0 : GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
119 : return false;
120 : }
121 : return true;
122 : }
123 :
124 : inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
125 : MessageLite* message) {
126 2795721 : message->Clear();
127 : return InlineMergeFromCodedStream(input, message);
128 : }
129 :
130 : inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
131 : MessageLite* message) {
132 0 : message->Clear();
133 0 : return message->MergePartialFromCodedStream(input);
134 : }
135 :
136 : inline bool InlineParseFromArray(
137 : const void* data, int size, MessageLite* message) {
138 830 : io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
139 1660 : return InlineParseFromCodedStream(&input, message) &&
140 1660 : input.ConsumedEntireMessage();
141 : }
142 :
143 : inline bool InlineParsePartialFromArray(
144 : const void* data, int size, MessageLite* message) {
145 0 : io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
146 0 : return InlineParsePartialFromCodedStream(&input, message) &&
147 0 : input.ConsumedEntireMessage();
148 : }
149 :
150 : } // namespace
151 :
152 :
153 0 : MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
154 0 : MessageLite* message = New();
155 0 : if (arena != NULL) {
156 0 : arena->Own(message);
157 : }
158 0 : return message;
159 : }
160 :
161 0 : bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
162 0 : return InlineMergeFromCodedStream(input, this);
163 : }
164 :
165 2794891 : bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
166 2794973 : return InlineParseFromCodedStream(input, this);
167 : }
168 :
169 0 : bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
170 0 : return InlineParsePartialFromCodedStream(input, this);
171 : }
172 :
173 8 : bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
174 8 : io::CodedInputStream decoder(input);
175 8 : return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
176 : }
177 :
178 0 : bool MessageLite::ParsePartialFromZeroCopyStream(
179 : io::ZeroCopyInputStream* input) {
180 0 : io::CodedInputStream decoder(input);
181 0 : return ParsePartialFromCodedStream(&decoder) &&
182 0 : decoder.ConsumedEntireMessage();
183 : }
184 :
185 0 : bool MessageLite::ParseFromBoundedZeroCopyStream(
186 : io::ZeroCopyInputStream* input, int size) {
187 0 : io::CodedInputStream decoder(input);
188 0 : decoder.PushLimit(size);
189 0 : return ParseFromCodedStream(&decoder) &&
190 0 : decoder.ConsumedEntireMessage() &&
191 0 : decoder.BytesUntilLimit() == 0;
192 : }
193 :
194 0 : bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
195 : io::ZeroCopyInputStream* input, int size) {
196 0 : io::CodedInputStream decoder(input);
197 0 : decoder.PushLimit(size);
198 0 : return ParsePartialFromCodedStream(&decoder) &&
199 0 : decoder.ConsumedEntireMessage() &&
200 0 : decoder.BytesUntilLimit() == 0;
201 : }
202 :
203 722 : bool MessageLite::ParseFromString(const string& data) {
204 1444 : return InlineParseFromArray(data.data(), data.size(), this);
205 : }
206 :
207 0 : bool MessageLite::ParsePartialFromString(const string& data) {
208 0 : return InlineParsePartialFromArray(data.data(), data.size(), this);
209 : }
210 :
211 108 : bool MessageLite::ParseFromArray(const void* data, int size) {
212 108 : return InlineParseFromArray(data, size, this);
213 : }
214 :
215 0 : bool MessageLite::ParsePartialFromArray(const void* data, int size) {
216 0 : return InlineParsePartialFromArray(data, size, this);
217 : }
218 :
219 :
220 : // ===================================================================
221 :
222 9 : uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
223 : // We only optimize this when using optimize_for = SPEED. In other cases
224 : // we just use the CodedOutputStream path.
225 9 : int size = GetCachedSize();
226 9 : io::ArrayOutputStream out(target, size);
227 18 : io::CodedOutputStream coded_out(&out);
228 9 : SerializeWithCachedSizes(&coded_out);
229 9 : GOOGLE_CHECK(!coded_out.HadError());
230 18 : return target + size;
231 : }
232 :
233 24 : bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
234 : GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
235 24 : return SerializePartialToCodedStream(output);
236 : }
237 :
238 24 : bool MessageLite::SerializePartialToCodedStream(
239 95 : io::CodedOutputStream* output) const {
240 24 : const int size = ByteSize(); // Force size to be cached.
241 24 : if (size < 0) {
242 : // Messages >2G cannot be serialized due to overflow computing ByteSize.
243 0 : GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
244 0 : return false;
245 : }
246 :
247 24 : uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
248 24 : if (buffer != NULL) {
249 5 : uint8* end = SerializeWithCachedSizesToArray(buffer);
250 5 : if (end - buffer != size) {
251 0 : ByteSizeConsistencyError(size, ByteSize(), end - buffer);
252 : }
253 : return true;
254 : } else {
255 57 : int original_byte_count = output->ByteCount();
256 19 : SerializeWithCachedSizes(output);
257 19 : if (output->HadError()) {
258 : return false;
259 : }
260 57 : int final_byte_count = output->ByteCount();
261 :
262 19 : if (final_byte_count - original_byte_count != size) {
263 0 : ByteSizeConsistencyError(size, ByteSize(),
264 0 : final_byte_count - original_byte_count);
265 : }
266 :
267 : return true;
268 : }
269 : }
270 :
271 24 : bool MessageLite::SerializeToZeroCopyStream(
272 : io::ZeroCopyOutputStream* output) const {
273 24 : io::CodedOutputStream encoder(output);
274 24 : return SerializeToCodedStream(&encoder);
275 : }
276 :
277 0 : bool MessageLite::SerializePartialToZeroCopyStream(
278 : io::ZeroCopyOutputStream* output) const {
279 0 : io::CodedOutputStream encoder(output);
280 0 : return SerializePartialToCodedStream(&encoder);
281 : }
282 :
283 776 : bool MessageLite::AppendToString(string* output) const {
284 : GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
285 776 : return AppendPartialToString(output);
286 : }
287 :
288 776 : bool MessageLite::AppendPartialToString(string* output) const {
289 776 : int old_size = output->size();
290 776 : int byte_size = ByteSize();
291 776 : if (byte_size < 0) {
292 : // Messages >2G cannot be serialized due to overflow computing ByteSize.
293 0 : GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
294 0 : return false;
295 : }
296 :
297 776 : STLStringResizeUninitialized(output, old_size + byte_size);
298 : uint8* start =
299 776 : reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
300 776 : uint8* end = SerializeWithCachedSizesToArray(start);
301 776 : if (end - start != byte_size) {
302 0 : ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
303 : }
304 : return true;
305 : }
306 :
307 78 : bool MessageLite::SerializeToString(string* output) const {
308 : output->clear();
309 78 : return AppendToString(output);
310 : }
311 :
312 0 : bool MessageLite::SerializePartialToString(string* output) const {
313 : output->clear();
314 0 : return AppendPartialToString(output);
315 : }
316 :
317 0 : bool MessageLite::SerializeToArray(void* data, int size) const {
318 : GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
319 0 : return SerializePartialToArray(data, size);
320 : }
321 :
322 0 : bool MessageLite::SerializePartialToArray(void* data, int size) const {
323 0 : int byte_size = ByteSize();
324 0 : if (size < byte_size) return false;
325 0 : uint8* start = reinterpret_cast<uint8*>(data);
326 0 : uint8* end = SerializeWithCachedSizesToArray(start);
327 0 : if (end - start != byte_size) {
328 0 : ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
329 : }
330 : return true;
331 : }
332 :
333 424 : string MessageLite::SerializeAsString() const {
334 : // If the compiler implements the (Named) Return Value Optimization,
335 : // the local variable 'output' will not actually reside on the stack
336 : // of this function, but will be overlaid with the object that the
337 : // caller supplied for the return value to be constructed in.
338 : string output;
339 424 : if (!AppendToString(&output))
340 : output.clear();
341 424 : return output;
342 : }
343 :
344 0 : string MessageLite::SerializePartialAsString() const {
345 : string output;
346 0 : if (!AppendPartialToString(&output))
347 : output.clear();
348 0 : return output;
349 : }
350 :
351 : namespace internal {
352 : template<>
353 0 : MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
354 : const MessageLite* prototype, google::protobuf::Arena* arena) {
355 0 : return prototype->New(arena);
356 : }
357 : template <>
358 0 : void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
359 : MessageLite* to) {
360 0 : to->CheckTypeAndMergeFrom(from);
361 0 : }
362 : } // namespace internal
363 :
364 : } // namespace protobuf
365 : } // namespace google
|