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