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