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