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 = ▮
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