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