Line data Source code
1 : /* pb_encode.c -- encode a protobuf using minimal resources
2 : *
3 : * 2011 Petteri Aimonen <jpa@kapsi.fi>
4 : */
5 :
6 : #include "pb_firedancer.h"
7 : #include "pb_encode.h"
8 : #include "pb_common.h"
9 :
10 : /* Use the GCC warn_unused_result attribute to check that all return values
11 : * are propagated correctly. On other compilers, gcc before 3.4.0 and iar
12 : * before 9.40.1 just ignore the annotation.
13 : */
14 : #if (defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))) || \
15 : (defined(__IAR_SYSTEMS_ICC__) && (__VER__ >= 9040001))
16 : #define checkreturn __attribute__((warn_unused_result))
17 : #else
18 : #define checkreturn
19 : #endif
20 :
21 : /**************************************
22 : * Declarations internal to this file *
23 : **************************************/
24 : static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
25 : static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field);
26 : static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field);
27 : static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field);
28 : static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field);
29 : static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field);
30 : static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field);
31 : static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
32 : static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high);
33 : static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field);
34 : static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field);
35 : static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field);
36 : static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
37 : static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field);
38 : static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field);
39 : static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
40 :
41 : #ifdef PB_WITHOUT_64BIT
42 : #define pb_int64_t int32_t
43 : #define pb_uint64_t uint32_t
44 : #else
45 583776 : #define pb_int64_t int64_t
46 18882432 : #define pb_uint64_t uint64_t
47 : #endif
48 :
49 : /*******************************
50 : * pb_ostream_t implementation *
51 : *******************************/
52 :
53 : static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
54 20821122 : {
55 20821122 : pb_byte_t *dest = (pb_byte_t*)stream->state;
56 20821122 : stream->state = dest + count;
57 :
58 20821122 : memcpy(dest, buf, count * sizeof(pb_byte_t));
59 :
60 20821122 : return true;
61 20821122 : }
62 :
63 : pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
64 791418 : {
65 791418 : pb_ostream_t stream;
66 791418 : #ifdef PB_BUFFER_ONLY
67 : /* In PB_BUFFER_ONLY configuration the callback pointer is just int*.
68 : * NULL pointer marks a sizing field, so put a non-NULL value to mark a buffer stream.
69 : */
70 791418 : static const int marker = 0;
71 791418 : stream.callback = ▮
72 : #else
73 : stream.callback = &buf_write;
74 : #endif
75 791418 : stream.state = buf;
76 791418 : stream.max_size = bufsize;
77 791418 : stream.bytes_written = 0;
78 791418 : #ifndef PB_NO_ERRMSG
79 791418 : stream.errmsg = NULL;
80 791418 : #endif
81 791418 : return stream;
82 791418 : }
83 :
84 : bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
85 34589640 : {
86 34589640 : if (count > 0 && stream->callback != NULL)
87 20821122 : {
88 20821122 : if (stream->bytes_written + count < stream->bytes_written ||
89 20821122 : stream->bytes_written + count > stream->max_size)
90 0 : {
91 0 : PB_RETURN_ERROR(stream, "stream full");
92 0 : }
93 :
94 20821122 : #ifdef PB_BUFFER_ONLY
95 20821122 : if (!buf_write(stream, buf, count))
96 0 : PB_RETURN_ERROR(stream, "io error");
97 : #else
98 : if (!stream->callback(stream, buf, count))
99 : PB_RETURN_ERROR(stream, "io error");
100 : #endif
101 20821122 : }
102 :
103 34589640 : stream->bytes_written += count;
104 34589640 : return true;
105 34589640 : }
106 :
107 : /*************************
108 : * Encode a single field *
109 : *************************/
110 :
111 : /* Read a bool value without causing undefined behavior even if the value
112 : * is invalid. See issue #434 and
113 : * https://stackoverflow.com/questions/27661768/weird-results-for-conditional
114 : */
115 : static bool safe_read_bool(const void *pSize)
116 3449004 : {
117 3449004 : const char *p = (const char *)pSize;
118 3449004 : size_t i;
119 5543040 : for (i = 0; i < sizeof(bool); i++)
120 3449004 : {
121 3449004 : if (p[i] != 0)
122 1354968 : return true;
123 3449004 : }
124 2094036 : return false;
125 3449004 : }
126 :
127 : /* Encode a static array. Handles the size calculations and possible packing. */
128 : static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field)
129 140718 : {
130 140718 : pb_size_t i;
131 140718 : pb_size_t count;
132 140718 : #ifndef PB_ENCODE_ARRAYS_UNPACKED
133 140718 : size_t size;
134 140718 : #endif
135 :
136 140718 : count = *(pb_size_t*)field->pSize;
137 :
138 140718 : if (count == 0)
139 0 : return true;
140 :
141 140718 : if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
142 0 : PB_RETURN_ERROR(stream, "array max size exceeded");
143 :
144 140718 : #ifndef PB_ENCODE_ARRAYS_UNPACKED
145 : /* We always pack arrays if the datatype allows it. */
146 140718 : if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
147 1176 : {
148 1176 : if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
149 0 : return false;
150 :
151 : /* Determine the total size of packed array. */
152 1176 : if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
153 0 : {
154 0 : size = 4 * (size_t)count;
155 0 : }
156 1176 : else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
157 0 : {
158 0 : size = 8 * (size_t)count;
159 0 : }
160 1176 : else
161 1176 : {
162 1176 : pb_ostream_t sizestream = PB_OSTREAM_SIZING;
163 1176 : void *pData_orig = field->pData;
164 322104 : for (i = 0; i < count; i++)
165 320928 : {
166 320928 : if (!pb_enc_varint(&sizestream, field))
167 0 : PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream));
168 320928 : field->pData = (char*)field->pData + field->data_size;
169 320928 : }
170 1176 : field->pData = pData_orig;
171 1176 : size = sizestream.bytes_written;
172 1176 : }
173 :
174 1176 : if (!pb_encode_varint(stream, (pb_uint64_t)size))
175 0 : return false;
176 :
177 1176 : if (stream->callback == NULL)
178 0 : return pb_write(stream, NULL, size); /* Just sizing.. */
179 :
180 : /* Write the data */
181 322104 : for (i = 0; i < count; i++)
182 320928 : {
183 320928 : if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
184 0 : {
185 0 : if (!pb_enc_fixed(stream, field))
186 0 : return false;
187 0 : }
188 320928 : else
189 320928 : {
190 320928 : if (!pb_enc_varint(stream, field))
191 0 : return false;
192 320928 : }
193 :
194 320928 : field->pData = (char*)field->pData + field->data_size;
195 320928 : }
196 1176 : }
197 139542 : else /* Unpacked fields */
198 139542 : #endif
199 139542 : {
200 1271478 : for (i = 0; i < count; i++)
201 1131936 : {
202 : /* Normally the data is stored directly in the array entries, but
203 : * for pointer-type string and bytes fields, the array entries are
204 : * actually pointers themselves also. So we have to dereference once
205 : * more to get to the actual data. */
206 1131936 : if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
207 1131936 : (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
208 1131936 : PB_LTYPE(field->type) == PB_LTYPE_BYTES))
209 0 : {
210 0 : bool status;
211 0 : void *pData_orig = field->pData;
212 0 : field->pData = *(void* const*)field->pData;
213 :
214 0 : if (!field->pData)
215 0 : {
216 : /* Null pointer in array is treated as empty string / bytes */
217 0 : status = pb_encode_tag_for_field(stream, field) &&
218 0 : pb_encode_varint(stream, 0);
219 0 : }
220 0 : else
221 0 : {
222 0 : status = encode_basic_field(stream, field);
223 0 : }
224 :
225 0 : field->pData = pData_orig;
226 :
227 0 : if (!status)
228 0 : return false;
229 0 : }
230 1131936 : else
231 1131936 : {
232 1131936 : if (!encode_basic_field(stream, field))
233 0 : return false;
234 1131936 : }
235 1131936 : field->pData = (char*)field->pData + field->data_size;
236 1131936 : }
237 139542 : }
238 :
239 140718 : return true;
240 140718 : }
241 :
242 : /* In proto3, all fields are optional and are only encoded if their value is "non-zero".
243 : * This function implements the check for the zero value. */
244 : static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field)
245 21846564 : {
246 21846564 : pb_type_t type = field->type;
247 :
248 21846564 : if (PB_ATYPE(type) == PB_ATYPE_STATIC)
249 21846564 : {
250 21846564 : if (PB_HTYPE(type) == PB_HTYPE_REQUIRED)
251 0 : {
252 : /* Required proto2 fields inside proto3 submessage, pretty rare case */
253 0 : return false;
254 0 : }
255 21846564 : else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
256 0 : {
257 : /* Repeated fields inside proto3 submessage: present if count != 0 */
258 0 : return *(const pb_size_t*)field->pSize == 0;
259 0 : }
260 21846564 : else if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
261 0 : {
262 : /* Oneof fields */
263 0 : return *(const pb_size_t*)field->pSize == 0;
264 0 : }
265 21846564 : else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL)
266 0 : {
267 : /* Proto2 optional fields inside proto3 message, or proto3
268 : * submessage fields. */
269 0 : return safe_read_bool(field->pSize) == false;
270 0 : }
271 21846564 : else if (field->descriptor->default_value)
272 0 : {
273 : /* Proto3 messages do not have default values, but proto2 messages
274 : * can contain optional fields without has_fields (generator option 'proto3').
275 : * In this case they must always be encoded, to make sure that the
276 : * non-zero default value is overwritten.
277 : */
278 0 : return false;
279 0 : }
280 :
281 : /* Rest is proto3 singular fields */
282 21846564 : if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
283 17658492 : {
284 : /* Simple integer / float fields */
285 17658492 : pb_size_t i;
286 17658492 : const char *p = (const char*)field->pData;
287 100184376 : for (i = 0; i < field->data_size; i++)
288 88890150 : {
289 88890150 : if (p[i] != 0)
290 6364266 : {
291 6364266 : return false;
292 6364266 : }
293 88890150 : }
294 :
295 11294226 : return true;
296 17658492 : }
297 4188072 : else if (PB_LTYPE(type) == PB_LTYPE_BYTES)
298 0 : {
299 0 : const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData;
300 0 : return bytes->size == 0;
301 0 : }
302 4188072 : else if (PB_LTYPE(type) == PB_LTYPE_STRING)
303 0 : {
304 0 : return *(const char*)field->pData == '\0';
305 0 : }
306 4188072 : else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES)
307 4188072 : {
308 : /* Fixed length bytes is only empty if its length is fixed
309 : * as 0. Which would be pretty strange, but we can check
310 : * it anyway. */
311 4188072 : return field->data_size == 0;
312 4188072 : }
313 0 : else if (PB_LTYPE_IS_SUBMSG(type))
314 0 : {
315 : /* Check all fields in the submessage to find if any of them
316 : * are non-zero. The comparison cannot be done byte-per-byte
317 : * because the C struct may contain padding bytes that must
318 : * be skipped. Note that usually proto3 submessages have
319 : * a separate has_field that is checked earlier in this if.
320 : */
321 0 : pb_field_iter_t iter;
322 0 : if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData))
323 0 : {
324 0 : do
325 0 : {
326 0 : if (!pb_check_proto3_default_value(&iter))
327 0 : {
328 0 : return false;
329 0 : }
330 0 : } while (pb_field_iter_next(&iter));
331 0 : }
332 0 : return true;
333 0 : }
334 21846564 : }
335 0 : else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
336 0 : {
337 0 : return field->pData == NULL;
338 0 : }
339 0 : else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
340 0 : {
341 0 : if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
342 0 : {
343 0 : const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
344 0 : return extension == NULL;
345 0 : }
346 0 : else if (field->descriptor->field_callback == pb_default_field_callback)
347 0 : {
348 0 : pb_callback_t *pCallback = (pb_callback_t*)field->pData;
349 0 : return pCallback->funcs.encode == NULL;
350 0 : }
351 0 : else
352 0 : {
353 0 : return field->descriptor->field_callback == NULL;
354 0 : }
355 0 : }
356 :
357 0 : return false; /* Not typically reached, safe default for weird special cases. */
358 21846564 : }
359 :
360 : /* Encode a field with static or pointer allocation, i.e. one whose data
361 : * is available to the encoder directly. */
362 : static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field)
363 13813878 : {
364 13813878 : if (!field->pData)
365 0 : {
366 : /* Missing pointer field */
367 0 : return true;
368 0 : }
369 :
370 13813878 : if (!pb_encode_tag_for_field(stream, field))
371 0 : return false;
372 :
373 13813878 : switch (PB_LTYPE(field->type))
374 13813878 : {
375 1354968 : case PB_LTYPE_BOOL:
376 1354968 : return pb_enc_bool(stream, field);
377 :
378 583776 : case PB_LTYPE_VARINT:
379 5009298 : case PB_LTYPE_UVARINT:
380 5009298 : case PB_LTYPE_SVARINT:
381 5009298 : return pb_enc_varint(stream, field);
382 :
383 0 : case PB_LTYPE_FIXED32:
384 0 : case PB_LTYPE_FIXED64:
385 0 : return pb_enc_fixed(stream, field);
386 :
387 2129604 : case PB_LTYPE_BYTES:
388 2129604 : return pb_enc_bytes(stream, field);
389 :
390 0 : case PB_LTYPE_STRING:
391 0 : return pb_enc_string(stream, field);
392 :
393 1131936 : case PB_LTYPE_SUBMESSAGE:
394 1131936 : case PB_LTYPE_SUBMSG_W_CB:
395 1131936 : return pb_enc_submessage(stream, field);
396 :
397 4188072 : case PB_LTYPE_FIXED_LENGTH_BYTES:
398 4188072 : return pb_enc_fixed_length_bytes(stream, field);
399 :
400 0 : default:
401 0 : PB_RETURN_ERROR(stream, "invalid field type");
402 13813878 : }
403 13813878 : }
404 :
405 : /* Encode a field with callback semantics. This means that a user function is
406 : * called to provide and encode the actual data. */
407 : static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field)
408 0 : {
409 0 : if (field->descriptor->field_callback != NULL)
410 0 : {
411 0 : if (!field->descriptor->field_callback(NULL, stream, field))
412 0 : PB_RETURN_ERROR(stream, "callback error");
413 0 : }
414 0 : return true;
415 0 : }
416 :
417 : /* Encode a single field of any callback, pointer or static type. */
418 : static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field)
419 30452316 : {
420 : /* Check field presence */
421 30452316 : if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
422 0 : {
423 0 : if (*(const pb_size_t*)field->pSize != field->tag)
424 0 : {
425 : /* Different type oneof field */
426 0 : return true;
427 0 : }
428 0 : }
429 30452316 : else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
430 29660898 : {
431 29660898 : if (field->pSize)
432 2094036 : {
433 2094036 : if (safe_read_bool(field->pSize) == false)
434 2094036 : {
435 : /* Missing optional field */
436 2094036 : return true;
437 2094036 : }
438 2094036 : }
439 27566862 : else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC)
440 21846564 : {
441 : /* Proto3 singular field */
442 21846564 : if (pb_check_proto3_default_value(field))
443 11294226 : return true;
444 21846564 : }
445 29660898 : }
446 :
447 17064054 : if (!field->pData)
448 4241394 : {
449 4241394 : if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED)
450 0 : PB_RETURN_ERROR(stream, "missing required field");
451 :
452 : /* Pointer field set to NULL */
453 4241394 : return true;
454 4241394 : }
455 :
456 : /* Then encode field contents */
457 12822660 : if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK)
458 0 : {
459 0 : return encode_callback_field(stream, field);
460 0 : }
461 12822660 : else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
462 140718 : {
463 140718 : return encode_array(stream, field);
464 140718 : }
465 12681942 : else
466 12681942 : {
467 12681942 : return encode_basic_field(stream, field);
468 12681942 : }
469 12822660 : }
470 :
471 : /* Default handler for extension fields. Expects to have a pb_msgdesc_t
472 : * pointer in the extension->type->arg field, pointing to a message with
473 : * only one field in it. */
474 : static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension)
475 0 : {
476 0 : pb_field_iter_t iter;
477 :
478 0 : if (!pb_field_iter_begin_extension_const(&iter, extension))
479 0 : PB_RETURN_ERROR(stream, "invalid extension");
480 :
481 0 : return encode_field(stream, &iter);
482 0 : }
483 :
484 :
485 : /* Walk through all the registered extensions and give them a chance
486 : * to encode themselves. */
487 : static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field)
488 0 : {
489 0 : const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
490 :
491 0 : while (extension)
492 0 : {
493 0 : bool status;
494 0 : if (extension->type->encode)
495 0 : status = extension->type->encode(stream, extension);
496 0 : else
497 0 : status = default_extension_encoder(stream, extension);
498 :
499 0 : if (!status)
500 0 : return false;
501 :
502 0 : extension = extension->next;
503 0 : }
504 :
505 0 : return true;
506 0 : }
507 :
508 : /*********************
509 : * Encode all fields *
510 : *********************/
511 :
512 : bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
513 3055290 : {
514 3055290 : pb_field_iter_t iter;
515 3055290 : if (!pb_field_iter_begin_const(&iter, fields, src_struct))
516 0 : return true; /* Empty message type */
517 :
518 30452316 : do {
519 30452316 : if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
520 0 : {
521 : /* Special case for the extension field placeholder */
522 0 : if (!encode_extension_field(stream, &iter))
523 0 : return false;
524 0 : }
525 30452316 : else
526 30452316 : {
527 : /* Regular field */
528 30452316 : if (!encode_field(stream, &iter))
529 0 : return false;
530 30452316 : }
531 30452316 : } while (pb_field_iter_next(&iter));
532 :
533 3055290 : return true;
534 3055290 : }
535 :
536 : bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags)
537 0 : {
538 0 : if ((flags & PB_ENCODE_DELIMITED) != 0)
539 0 : {
540 0 : return pb_encode_submessage(stream, fields, src_struct);
541 0 : }
542 0 : else if ((flags & PB_ENCODE_NULLTERMINATED) != 0)
543 0 : {
544 0 : const pb_byte_t zero = 0;
545 :
546 0 : if (!pb_encode(stream, fields, src_struct))
547 0 : return false;
548 :
549 0 : return pb_write(stream, &zero, 1);
550 0 : }
551 0 : else
552 0 : {
553 0 : return pb_encode(stream, fields, src_struct);
554 0 : }
555 0 : }
556 :
557 : bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct)
558 0 : {
559 0 : pb_ostream_t stream = PB_OSTREAM_SIZING;
560 :
561 0 : if (!pb_encode(&stream, fields, src_struct))
562 0 : return false;
563 :
564 0 : *size = stream.bytes_written;
565 0 : return true;
566 0 : }
567 :
568 : /********************
569 : * Helper functions *
570 : ********************/
571 :
572 : /* This function avoids 64-bit shifts as they are quite slow on many platforms. */
573 : static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high)
574 6123864 : {
575 6123864 : size_t i = 0;
576 6123864 : pb_byte_t buffer[10];
577 6123864 : pb_byte_t byte = (pb_byte_t)(low & 0x7F);
578 6123864 : low >>= 7;
579 :
580 23812242 : while (i < 4 && (low != 0 || high != 0))
581 17688378 : {
582 17688378 : byte |= 0x80;
583 17688378 : buffer[i++] = byte;
584 17688378 : byte = (pb_byte_t)(low & 0x7F);
585 17688378 : low >>= 7;
586 17688378 : }
587 :
588 6123864 : if (high)
589 3266250 : {
590 3266250 : byte = (pb_byte_t)(byte | ((high & 0x07) << 4));
591 3266250 : high >>= 3;
592 :
593 15749754 : while (high)
594 12483504 : {
595 12483504 : byte |= 0x80;
596 12483504 : buffer[i++] = byte;
597 12483504 : byte = (pb_byte_t)(high & 0x7F);
598 12483504 : high >>= 7;
599 12483504 : }
600 3266250 : }
601 :
602 6123864 : buffer[i++] = byte;
603 :
604 6123864 : return pb_write(stream, buffer, i);
605 6123864 : }
606 :
607 : bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value)
608 28271964 : {
609 28271964 : if (value <= 0x7F)
610 22148100 : {
611 : /* Fast path: single byte */
612 22148100 : pb_byte_t byte = (pb_byte_t)value;
613 22148100 : return pb_write(stream, &byte, 1);
614 22148100 : }
615 6123864 : else
616 6123864 : {
617 : #ifdef PB_WITHOUT_64BIT
618 : return pb_encode_varint_32(stream, value, 0);
619 : #else
620 6123864 : return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32));
621 6123864 : #endif
622 6123864 : }
623 28271964 : }
624 :
625 : bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value)
626 0 : {
627 0 : pb_uint64_t zigzagged;
628 0 : pb_uint64_t mask = ((pb_uint64_t)-1) >> 1; /* Satisfy clang -fsanitize=integer */
629 0 : if (value < 0)
630 0 : zigzagged = ~(((pb_uint64_t)value & mask) << 1);
631 0 : else
632 0 : zigzagged = (pb_uint64_t)value << 1;
633 :
634 0 : return pb_encode_varint(stream, zigzagged);
635 0 : }
636 :
637 : bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
638 0 : {
639 0 : #if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
640 : /* Fast path if we know that we're on little endian */
641 0 : return pb_write(stream, (const pb_byte_t*)value, 4);
642 : #else
643 : uint32_t val = *(const uint32_t*)value;
644 : pb_byte_t bytes[4];
645 : bytes[0] = (pb_byte_t)(val & 0xFF);
646 : bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
647 : bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
648 : bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
649 : return pb_write(stream, bytes, 4);
650 : #endif
651 0 : }
652 :
653 : #ifndef PB_WITHOUT_64BIT
654 : bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
655 0 : {
656 0 : #if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
657 : /* Fast path if we know that we're on little endian */
658 0 : return pb_write(stream, (const pb_byte_t*)value, 8);
659 : #else
660 : uint64_t val = *(const uint64_t*)value;
661 : pb_byte_t bytes[8];
662 : bytes[0] = (pb_byte_t)(val & 0xFF);
663 : bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
664 : bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
665 : bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
666 : bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
667 : bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
668 : bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
669 : bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
670 : return pb_write(stream, bytes, 8);
671 : #endif
672 0 : }
673 : #endif
674 :
675 : bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
676 13815054 : {
677 13815054 : pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype;
678 13815054 : return pb_encode_varint(stream, tag);
679 13815054 : }
680 :
681 : bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field )
682 13813878 : {
683 13813878 : pb_wire_type_t wiretype;
684 13813878 : switch (PB_LTYPE(field->type))
685 13813878 : {
686 1354968 : case PB_LTYPE_BOOL:
687 1938744 : case PB_LTYPE_VARINT:
688 6364266 : case PB_LTYPE_UVARINT:
689 6364266 : case PB_LTYPE_SVARINT:
690 6364266 : wiretype = PB_WT_VARINT;
691 6364266 : break;
692 :
693 0 : case PB_LTYPE_FIXED32:
694 0 : wiretype = PB_WT_32BIT;
695 0 : break;
696 :
697 0 : case PB_LTYPE_FIXED64:
698 0 : wiretype = PB_WT_64BIT;
699 0 : break;
700 :
701 2129604 : case PB_LTYPE_BYTES:
702 2129604 : case PB_LTYPE_STRING:
703 3261540 : case PB_LTYPE_SUBMESSAGE:
704 3261540 : case PB_LTYPE_SUBMSG_W_CB:
705 7449612 : case PB_LTYPE_FIXED_LENGTH_BYTES:
706 7449612 : wiretype = PB_WT_STRING;
707 7449612 : break;
708 :
709 0 : default:
710 0 : PB_RETURN_ERROR(stream, "invalid field type");
711 13813878 : }
712 :
713 13813878 : return pb_encode_tag(stream, wiretype, field->tag);
714 13813878 : }
715 :
716 : bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
717 6317676 : {
718 6317676 : if (!pb_encode_varint(stream, (pb_uint64_t)size))
719 0 : return false;
720 :
721 6317676 : return pb_write(stream, buffer, size);
722 6317676 : }
723 :
724 : bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
725 1131936 : {
726 : /* First calculate the message size using a non-writing substream. */
727 1131936 : pb_ostream_t substream = PB_OSTREAM_SIZING;
728 1131936 : size_t size;
729 1131936 : bool status;
730 :
731 1131936 : if (!pb_encode(&substream, fields, src_struct))
732 0 : {
733 0 : #ifndef PB_NO_ERRMSG
734 0 : stream->errmsg = substream.errmsg;
735 0 : #endif
736 0 : return false;
737 0 : }
738 :
739 1131936 : size = substream.bytes_written;
740 :
741 1131936 : if (!pb_encode_varint(stream, (pb_uint64_t)size))
742 0 : return false;
743 :
744 1131936 : if (stream->callback == NULL)
745 0 : return pb_write(stream, NULL, size); /* Just sizing */
746 :
747 1131936 : if (stream->bytes_written + size > stream->max_size)
748 0 : PB_RETURN_ERROR(stream, "stream full");
749 :
750 : /* Use a substream to verify that a callback doesn't write more than
751 : * what it did the first time. */
752 1131936 : substream.callback = stream->callback;
753 1131936 : substream.state = stream->state;
754 1131936 : substream.max_size = size;
755 1131936 : substream.bytes_written = 0;
756 1131936 : #ifndef PB_NO_ERRMSG
757 1131936 : substream.errmsg = NULL;
758 1131936 : #endif
759 :
760 1131936 : status = pb_encode(&substream, fields, src_struct);
761 :
762 1131936 : stream->bytes_written += substream.bytes_written;
763 1131936 : stream->state = substream.state;
764 1131936 : #ifndef PB_NO_ERRMSG
765 1131936 : stream->errmsg = substream.errmsg;
766 1131936 : #endif
767 :
768 1131936 : if (substream.bytes_written != size)
769 0 : PB_RETURN_ERROR(stream, "submsg size changed");
770 :
771 1131936 : return status;
772 1131936 : }
773 :
774 : /* Field encoders */
775 :
776 : static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field)
777 1354968 : {
778 1354968 : uint32_t value = safe_read_bool(field->pData) ? 1 : 0;
779 1354968 : PB_UNUSED(field);
780 1354968 : return pb_encode_varint(stream, value);
781 1354968 : }
782 :
783 : static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field)
784 5651154 : {
785 5651154 : if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT)
786 5067378 : {
787 : /* Perform unsigned integer extension */
788 5067378 : pb_uint64_t value = 0;
789 :
790 5067378 : if (field->data_size == sizeof(uint_least8_t))
791 0 : value = *(const uint_least8_t*)field->pData;
792 5067378 : else if (field->data_size == sizeof(uint_least16_t))
793 0 : value = *(const uint_least16_t*)field->pData;
794 5067378 : else if (field->data_size == sizeof(uint32_t))
795 12792 : value = *(const uint32_t*)field->pData;
796 5054586 : else if (field->data_size == sizeof(pb_uint64_t))
797 5054586 : value = *(const pb_uint64_t*)field->pData;
798 0 : else
799 0 : PB_RETURN_ERROR(stream, "invalid data_size");
800 :
801 5067378 : return pb_encode_varint(stream, value);
802 5067378 : }
803 583776 : else
804 583776 : {
805 : /* Perform signed integer extension */
806 583776 : pb_int64_t value = 0;
807 :
808 583776 : if (field->data_size == sizeof(int_least8_t))
809 0 : value = *(const int_least8_t*)field->pData;
810 583776 : else if (field->data_size == sizeof(int_least16_t))
811 0 : value = *(const int_least16_t*)field->pData;
812 583776 : else if (field->data_size == sizeof(int32_t))
813 104784 : value = *(const int32_t*)field->pData;
814 478992 : else if (field->data_size == sizeof(pb_int64_t))
815 478992 : value = *(const pb_int64_t*)field->pData;
816 0 : else
817 0 : PB_RETURN_ERROR(stream, "invalid data_size");
818 :
819 583776 : if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT)
820 0 : return pb_encode_svarint(stream, value);
821 : #ifdef PB_WITHOUT_64BIT
822 : else if (value < 0)
823 : return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1);
824 : #endif
825 583776 : else
826 583776 : return pb_encode_varint(stream, (pb_uint64_t)value);
827 :
828 583776 : }
829 5651154 : }
830 :
831 : static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field)
832 0 : {
833 : #ifdef PB_CONVERT_DOUBLE_FLOAT
834 : if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
835 : {
836 : return pb_encode_float_as_double(stream, *(float*)field->pData);
837 : }
838 : #endif
839 :
840 0 : if (field->data_size == sizeof(uint32_t))
841 0 : {
842 0 : return pb_encode_fixed32(stream, field->pData);
843 0 : }
844 0 : #ifndef PB_WITHOUT_64BIT
845 0 : else if (field->data_size == sizeof(uint64_t))
846 0 : {
847 0 : return pb_encode_fixed64(stream, field->pData);
848 0 : }
849 0 : #endif
850 0 : else
851 0 : {
852 0 : PB_RETURN_ERROR(stream, "invalid data_size");
853 0 : }
854 0 : }
855 :
856 : static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
857 2129604 : {
858 2129604 : const pb_bytes_array_t *bytes = NULL;
859 :
860 2129604 : bytes = (const pb_bytes_array_t*)field->pData;
861 :
862 2129604 : if (bytes == NULL)
863 0 : {
864 : /* Treat null pointer as an empty bytes field */
865 0 : return pb_encode_string(stream, NULL, 0);
866 0 : }
867 :
868 2129604 : if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
869 2129604 : bytes->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
870 0 : {
871 0 : PB_RETURN_ERROR(stream, "bytes size exceeded");
872 0 : }
873 :
874 2129604 : return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size);
875 2129604 : }
876 :
877 : static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field)
878 0 : {
879 0 : size_t size = 0;
880 0 : size_t max_size = (size_t)field->data_size;
881 0 : const char *str = (const char*)field->pData;
882 :
883 0 : if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
884 0 : {
885 0 : max_size = (size_t)-1;
886 0 : }
887 0 : else
888 0 : {
889 : /* pb_dec_string() assumes string fields end with a null
890 : * terminator when the type isn't PB_ATYPE_POINTER, so we
891 : * shouldn't allow more than max-1 bytes to be written to
892 : * allow space for the null terminator.
893 : */
894 0 : if (max_size == 0)
895 0 : PB_RETURN_ERROR(stream, "zero-length string");
896 :
897 0 : max_size -= 1;
898 0 : }
899 :
900 :
901 0 : if (str == NULL)
902 0 : {
903 0 : size = 0; /* Treat null pointer as an empty string */
904 0 : }
905 0 : else
906 0 : {
907 0 : const char *p = str;
908 :
909 : /* strnlen() is not always available, so just use a loop */
910 0 : while (size < max_size && *p != '\0')
911 0 : {
912 0 : size++;
913 0 : p++;
914 0 : }
915 :
916 0 : if (*p != '\0')
917 0 : {
918 0 : PB_RETURN_ERROR(stream, "unterminated string");
919 0 : }
920 0 : }
921 :
922 : #ifdef PB_VALIDATE_UTF8
923 : if (!pb_validate_utf8(str))
924 : PB_RETURN_ERROR(stream, "invalid utf8");
925 : #endif
926 :
927 0 : return pb_encode_string(stream, (const pb_byte_t*)str, size);
928 0 : }
929 :
930 : static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field)
931 1131936 : {
932 1131936 : if (field->submsg_desc == NULL)
933 0 : PB_RETURN_ERROR(stream, "invalid field descriptor");
934 :
935 1131936 : if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL)
936 0 : {
937 : /* Message callback is stored right before pSize. */
938 0 : pb_callback_t *callback = (pb_callback_t*)field->pSize - 1;
939 0 : if (callback->funcs.encode)
940 0 : {
941 0 : if (!callback->funcs.encode(stream, field, &callback->arg))
942 0 : return false;
943 0 : }
944 0 : }
945 :
946 1131936 : return pb_encode_submessage(stream, field->submsg_desc, field->pData);
947 1131936 : }
948 :
949 : static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
950 4188072 : {
951 4188072 : return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size);
952 4188072 : }
953 :
954 : #ifdef PB_CONVERT_DOUBLE_FLOAT
955 : bool pb_encode_float_as_double(pb_ostream_t *stream, float value)
956 : {
957 : union { float f; uint32_t i; } in;
958 : uint_least8_t sign;
959 : int exponent;
960 : uint64_t mantissa;
961 :
962 : in.f = value;
963 :
964 : /* Decompose input value */
965 : sign = (uint_least8_t)((in.i >> 31) & 1);
966 : exponent = (int)((in.i >> 23) & 0xFF) - 127;
967 : mantissa = in.i & 0x7FFFFF;
968 :
969 : if (exponent == 128)
970 : {
971 : /* Special value (NaN etc.) */
972 : exponent = 1024;
973 : }
974 : else if (exponent == -127)
975 : {
976 : if (!mantissa)
977 : {
978 : /* Zero */
979 : exponent = -1023;
980 : }
981 : else
982 : {
983 : /* Denormalized */
984 : mantissa <<= 1;
985 : while (!(mantissa & 0x800000))
986 : {
987 : mantissa <<= 1;
988 : exponent--;
989 : }
990 : mantissa &= 0x7FFFFF;
991 : }
992 : }
993 :
994 : /* Combine fields */
995 : mantissa <<= 29;
996 : mantissa |= (uint64_t)(exponent + 1023) << 52;
997 : mantissa |= (uint64_t)sign << 63;
998 :
999 : return pb_encode_fixed64(stream, &mantissa);
1000 : }
1001 : #endif
|