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