Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/lib/protobuf-c/protobuf-c.c
1532 views
1
/*
2
* Copyright (c) 2008-2025, Dave Benson and the protobuf-c authors.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are
7
* met:
8
*
9
* * Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
*
12
* * Redistributions in binary form must reproduce the above
13
* copyright notice, this list of conditions and the following disclaimer
14
* in the documentation and/or other materials provided with the
15
* distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
/*! \file
31
* Support library for `protoc-gen-c` generated code.
32
*
33
* This file implements the public API used by the code generated
34
* by `protoc-gen-c`.
35
*
36
* \authors Dave Benson and the protobuf-c authors
37
*
38
* \copyright 2008-2025. Licensed under the terms of the [BSD-2-Clause] license.
39
*/
40
41
/**
42
* \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
43
* even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
44
*
45
* \todo Use size_t consistently.
46
*/
47
48
#include <config.h>
49
50
#include <stdlib.h> /* for malloc, free */
51
#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
52
#if defined(HAVE_ENDIAN_H)
53
# include <endian.h>
54
#elif defined(HAVE_SYS_ENDIAN_H)
55
# include <sys/endian.h>
56
#elif defined(HAVE_MACHINE_ENDIAN_H)
57
# include <machine/endian.h>
58
#else
59
# include <compat/endian.h>
60
#endif
61
62
#include <protobuf-c/protobuf-c.h>
63
64
#if BYTE_ORDER == BIG_ENDIAN
65
# define WORDS_BIGENDIAN
66
#endif
67
68
#define TRUE 1
69
#define FALSE 0
70
71
#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
72
73
/* Workaround for Microsoft compilers. */
74
#ifdef _MSC_VER
75
# define inline __inline
76
#endif
77
78
/**
79
* \defgroup internal Internal functions and macros
80
*
81
* These are not exported by the library but are useful to developers working
82
* on `libprotobuf-c` itself.
83
*/
84
85
/**
86
* \defgroup macros Utility macros for manipulating structures
87
*
88
* Macros and constants used to manipulate the base "classes" generated by
89
* `protobuf-c`. They also define limits and check correctness.
90
*
91
* \ingroup internal
92
* @{
93
*/
94
95
/** The maximum length of a 64-bit integer in varint encoding. */
96
#define MAX_UINT64_ENCODED_SIZE 10
97
98
#ifndef PROTOBUF_C_UNPACK_ERROR
99
# define PROTOBUF_C_UNPACK_ERROR(...)
100
#endif
101
102
#if !defined(_WIN32) || !defined(PROTOBUF_C_USE_SHARED_LIB)
103
const char protobuf_c_empty_string[] = "";
104
#endif
105
106
/**
107
* Internal `ProtobufCMessage` manipulation macro.
108
*
109
* Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
110
* STRUCT_MEMBER_PTR().
111
*/
112
#define STRUCT_MEMBER_P(struct_p, struct_offset) \
113
((void *) ((uint8_t *) (struct_p) + (struct_offset)))
114
115
/**
116
* Return field in a `ProtobufCMessage` based on offset.
117
*
118
* Take a pointer to a `ProtobufCMessage` and find the field at the offset.
119
* Cast it to the passed type.
120
*/
121
#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
122
(*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
123
124
/**
125
* Return field in a `ProtobufCMessage` based on offset.
126
*
127
* Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
128
* it to a pointer to the passed type.
129
*/
130
#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
131
((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
132
133
/* Assertions for magic numbers. */
134
135
#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
136
assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
137
138
#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
139
assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
140
141
#define ASSERT_IS_MESSAGE(message) \
142
ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
143
144
#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
145
assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
146
147
/**@}*/
148
149
/* --- version --- */
150
151
const char *
152
protobuf_c_version(void)
153
{
154
return PROTOBUF_C_VERSION;
155
}
156
157
uint32_t
158
protobuf_c_version_number(void)
159
{
160
return PROTOBUF_C_VERSION_NUMBER;
161
}
162
163
/* --- allocator --- */
164
165
static void *
166
system_alloc(void *allocator_data, size_t size)
167
{
168
(void)allocator_data;
169
return malloc(size);
170
}
171
172
static void
173
system_free(void *allocator_data, void *data)
174
{
175
(void)allocator_data;
176
free(data);
177
}
178
179
static inline void *
180
do_alloc(ProtobufCAllocator *allocator, size_t size)
181
{
182
return allocator->alloc(allocator->allocator_data, size);
183
}
184
185
static inline void
186
do_free(ProtobufCAllocator *allocator, void *data)
187
{
188
if (data != NULL)
189
allocator->free(allocator->allocator_data, data);
190
}
191
192
/*
193
* This allocator uses the system's malloc() and free(). It is the default
194
* allocator used if NULL is passed as the ProtobufCAllocator to an exported
195
* function.
196
*/
197
static ProtobufCAllocator protobuf_c__allocator = {
198
.alloc = &system_alloc,
199
.free = &system_free,
200
.allocator_data = NULL,
201
};
202
203
/* === buffer-simple === */
204
205
void
206
protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
207
size_t len, const uint8_t *data)
208
{
209
ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
210
size_t new_len = simp->len + len;
211
212
if (new_len > simp->alloced) {
213
ProtobufCAllocator *allocator = simp->allocator;
214
size_t new_alloced = simp->alloced * 2;
215
uint8_t *new_data;
216
217
if (allocator == NULL)
218
allocator = &protobuf_c__allocator;
219
while (new_alloced < new_len)
220
new_alloced += new_alloced;
221
new_data = do_alloc(allocator, new_alloced);
222
if (!new_data)
223
return;
224
memcpy(new_data, simp->data, simp->len);
225
if (simp->must_free_data)
226
do_free(allocator, simp->data);
227
else
228
simp->must_free_data = TRUE;
229
simp->data = new_data;
230
simp->alloced = new_alloced;
231
}
232
memcpy(simp->data + simp->len, data, len);
233
simp->len = new_len;
234
}
235
236
/**
237
* \defgroup packedsz protobuf_c_message_get_packed_size() implementation
238
*
239
* Routines mainly used by protobuf_c_message_get_packed_size().
240
*
241
* \ingroup internal
242
* @{
243
*/
244
245
/**
246
* Return the number of bytes required to store the tag for the field. Includes
247
* 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
248
*
249
* \param number
250
* Field tag to encode.
251
* \return
252
* Number of bytes required.
253
*/
254
static inline size_t
255
get_tag_size(uint32_t number)
256
{
257
if (number < (1UL << 4)) {
258
return 1;
259
} else if (number < (1UL << 11)) {
260
return 2;
261
} else if (number < (1UL << 18)) {
262
return 3;
263
} else if (number < (1UL << 25)) {
264
return 4;
265
} else {
266
return 5;
267
}
268
}
269
270
/**
271
* Return the number of bytes required to store a variable-length unsigned
272
* 32-bit integer in base-128 varint encoding.
273
*
274
* \param v
275
* Value to encode.
276
* \return
277
* Number of bytes required.
278
*/
279
static inline size_t
280
uint32_size(uint32_t v)
281
{
282
if (v < (1UL << 7)) {
283
return 1;
284
} else if (v < (1UL << 14)) {
285
return 2;
286
} else if (v < (1UL << 21)) {
287
return 3;
288
} else if (v < (1UL << 28)) {
289
return 4;
290
} else {
291
return 5;
292
}
293
}
294
295
/**
296
* Return the number of bytes required to store a variable-length signed 32-bit
297
* integer in base-128 varint encoding.
298
*
299
* \param v
300
* Value to encode.
301
* \return
302
* Number of bytes required.
303
*/
304
static inline size_t
305
int32_size(int32_t v)
306
{
307
if (v < 0) {
308
return 10;
309
} else if (v < (1L << 7)) {
310
return 1;
311
} else if (v < (1L << 14)) {
312
return 2;
313
} else if (v < (1L << 21)) {
314
return 3;
315
} else if (v < (1L << 28)) {
316
return 4;
317
} else {
318
return 5;
319
}
320
}
321
322
/**
323
* Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
324
* integer.
325
*
326
* \param v
327
* Value to encode.
328
* \return
329
* ZigZag encoded integer.
330
*/
331
static inline uint32_t
332
zigzag32(int32_t v)
333
{
334
// Note: Using unsigned types prevents undefined behavior
335
return ((uint32_t)v << 1) ^ -((uint32_t)v >> 31);
336
}
337
338
/**
339
* Return the number of bytes required to store a signed 32-bit integer,
340
* converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
341
* varint encoding.
342
*
343
* \param v
344
* Value to encode.
345
* \return
346
* Number of bytes required.
347
*/
348
static inline size_t
349
sint32_size(int32_t v)
350
{
351
return uint32_size(zigzag32(v));
352
}
353
354
/**
355
* Return the number of bytes required to store a 64-bit unsigned integer in
356
* base-128 varint encoding.
357
*
358
* \param v
359
* Value to encode.
360
* \return
361
* Number of bytes required.
362
*/
363
static inline size_t
364
uint64_size(uint64_t v)
365
{
366
uint32_t upper_v = (uint32_t) (v >> 32);
367
368
if (upper_v == 0) {
369
return uint32_size((uint32_t) v);
370
} else if (upper_v < (1UL << 3)) {
371
return 5;
372
} else if (upper_v < (1UL << 10)) {
373
return 6;
374
} else if (upper_v < (1UL << 17)) {
375
return 7;
376
} else if (upper_v < (1UL << 24)) {
377
return 8;
378
} else if (upper_v < (1UL << 31)) {
379
return 9;
380
} else {
381
return 10;
382
}
383
}
384
385
/**
386
* Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
387
* integer.
388
*
389
* \param v
390
* Value to encode.
391
* \return
392
* ZigZag encoded integer.
393
*/
394
static inline uint64_t
395
zigzag64(int64_t v)
396
{
397
// Note: Using unsigned types prevents undefined behavior
398
return ((uint64_t)v << 1) ^ -((uint64_t)v >> 63);
399
}
400
401
/**
402
* Return the number of bytes required to store a signed 64-bit integer,
403
* converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
404
* varint encoding.
405
*
406
* \param v
407
* Value to encode.
408
* \return
409
* Number of bytes required.
410
*/
411
static inline size_t
412
sint64_size(int64_t v)
413
{
414
return uint64_size(zigzag64(v));
415
}
416
417
/**
418
* Calculate the serialized size of a single required message field, including
419
* the space needed by the preceding tag.
420
*
421
* \param field
422
* Field descriptor for member.
423
* \param member
424
* Field to encode.
425
* \return
426
* Number of bytes required.
427
*/
428
static size_t
429
required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
430
const void *member)
431
{
432
size_t rv = get_tag_size(field->id);
433
434
switch (field->type) {
435
case PROTOBUF_C_TYPE_SINT32:
436
return rv + sint32_size(*(const int32_t *) member);
437
case PROTOBUF_C_TYPE_ENUM:
438
case PROTOBUF_C_TYPE_INT32:
439
return rv + int32_size(*(const int32_t *) member);
440
case PROTOBUF_C_TYPE_UINT32:
441
return rv + uint32_size(*(const uint32_t *) member);
442
case PROTOBUF_C_TYPE_SINT64:
443
return rv + sint64_size(*(const int64_t *) member);
444
case PROTOBUF_C_TYPE_INT64:
445
case PROTOBUF_C_TYPE_UINT64:
446
return rv + uint64_size(*(const uint64_t *) member);
447
case PROTOBUF_C_TYPE_SFIXED32:
448
case PROTOBUF_C_TYPE_FIXED32:
449
return rv + 4;
450
case PROTOBUF_C_TYPE_SFIXED64:
451
case PROTOBUF_C_TYPE_FIXED64:
452
return rv + 8;
453
case PROTOBUF_C_TYPE_BOOL:
454
return rv + 1;
455
case PROTOBUF_C_TYPE_FLOAT:
456
return rv + 4;
457
case PROTOBUF_C_TYPE_DOUBLE:
458
return rv + 8;
459
case PROTOBUF_C_TYPE_STRING: {
460
const char *str = *(char * const *) member;
461
size_t len = str ? strlen(str) : 0;
462
return rv + uint32_size(len) + len;
463
}
464
case PROTOBUF_C_TYPE_BYTES: {
465
size_t len = ((const ProtobufCBinaryData *) member)->len;
466
return rv + uint32_size(len) + len;
467
}
468
case PROTOBUF_C_TYPE_MESSAGE: {
469
const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
470
size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
471
return rv + uint32_size(subrv) + subrv;
472
}
473
}
474
PROTOBUF_C__ASSERT_NOT_REACHED();
475
return 0;
476
}
477
478
/**
479
* Calculate the serialized size of a single oneof message field, including
480
* the space needed by the preceding tag. Returns 0 if the oneof field isn't
481
* selected or is not set.
482
*
483
* \param field
484
* Field descriptor for member.
485
* \param oneof_case
486
* Enum value that selects the field in the oneof.
487
* \param member
488
* Field to encode.
489
* \return
490
* Number of bytes required.
491
*/
492
static size_t
493
oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field,
494
uint32_t oneof_case,
495
const void *member)
496
{
497
if (oneof_case != field->id) {
498
return 0;
499
}
500
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
501
field->type == PROTOBUF_C_TYPE_STRING)
502
{
503
const void *ptr = *(const void * const *) member;
504
if (ptr == NULL || ptr == field->default_value)
505
return 0;
506
}
507
return required_field_get_packed_size(field, member);
508
}
509
510
/**
511
* Calculate the serialized size of a single optional message field, including
512
* the space needed by the preceding tag. Returns 0 if the optional field isn't
513
* set.
514
*
515
* \param field
516
* Field descriptor for member.
517
* \param has
518
* True if the field exists, false if not.
519
* \param member
520
* Field to encode.
521
* \return
522
* Number of bytes required.
523
*/
524
static size_t
525
optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
526
const protobuf_c_boolean has,
527
const void *member)
528
{
529
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
530
field->type == PROTOBUF_C_TYPE_STRING)
531
{
532
const void *ptr = *(const void * const *) member;
533
if (ptr == NULL || ptr == field->default_value)
534
return 0;
535
} else {
536
if (!has)
537
return 0;
538
}
539
return required_field_get_packed_size(field, member);
540
}
541
542
static protobuf_c_boolean
543
field_is_zeroish(const ProtobufCFieldDescriptor *field,
544
const void *member)
545
{
546
protobuf_c_boolean ret = FALSE;
547
548
switch (field->type) {
549
case PROTOBUF_C_TYPE_BOOL:
550
ret = (0 == *(const protobuf_c_boolean *) member);
551
break;
552
case PROTOBUF_C_TYPE_ENUM:
553
case PROTOBUF_C_TYPE_SINT32:
554
case PROTOBUF_C_TYPE_INT32:
555
case PROTOBUF_C_TYPE_UINT32:
556
case PROTOBUF_C_TYPE_SFIXED32:
557
case PROTOBUF_C_TYPE_FIXED32:
558
ret = (0 == *(const uint32_t *) member);
559
break;
560
case PROTOBUF_C_TYPE_SINT64:
561
case PROTOBUF_C_TYPE_INT64:
562
case PROTOBUF_C_TYPE_UINT64:
563
case PROTOBUF_C_TYPE_SFIXED64:
564
case PROTOBUF_C_TYPE_FIXED64:
565
ret = (0 == *(const uint64_t *) member);
566
break;
567
case PROTOBUF_C_TYPE_FLOAT:
568
ret = (0 == *(const float *) member);
569
break;
570
case PROTOBUF_C_TYPE_DOUBLE:
571
ret = (0 == *(const double *) member);
572
break;
573
case PROTOBUF_C_TYPE_STRING:
574
ret = (NULL == *(const char * const *) member) ||
575
('\0' == **(const char * const *) member);
576
break;
577
case PROTOBUF_C_TYPE_BYTES:
578
case PROTOBUF_C_TYPE_MESSAGE:
579
ret = (NULL == *(const void * const *) member);
580
break;
581
default:
582
ret = TRUE;
583
break;
584
}
585
586
return ret;
587
}
588
589
/**
590
* Calculate the serialized size of a single unlabeled message field, including
591
* the space needed by the preceding tag. Returns 0 if the field isn't set or
592
* if it is set to a "zeroish" value (null pointer or 0 for numerical values).
593
* Unlabeled fields are supported only in proto3.
594
*
595
* \param field
596
* Field descriptor for member.
597
* \param member
598
* Field to encode.
599
* \return
600
* Number of bytes required.
601
*/
602
static size_t
603
unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field,
604
const void *member)
605
{
606
if (field_is_zeroish(field, member))
607
return 0;
608
return required_field_get_packed_size(field, member);
609
}
610
611
/**
612
* Calculate the serialized size of repeated message fields, which may consist
613
* of any number of values (including 0). Includes the space needed by the
614
* preceding tags (as needed).
615
*
616
* \param field
617
* Field descriptor for member.
618
* \param count
619
* Number of repeated field members.
620
* \param member
621
* Field to encode.
622
* \return
623
* Number of bytes required.
624
*/
625
static size_t
626
repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
627
size_t count, const void *member)
628
{
629
size_t header_size;
630
size_t rv = 0;
631
unsigned i;
632
void *array = *(void * const *) member;
633
634
if (count == 0)
635
return 0;
636
header_size = get_tag_size(field->id);
637
if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
638
header_size *= count;
639
640
switch (field->type) {
641
case PROTOBUF_C_TYPE_SINT32:
642
for (i = 0; i < count; i++)
643
rv += sint32_size(((int32_t *) array)[i]);
644
break;
645
case PROTOBUF_C_TYPE_ENUM:
646
case PROTOBUF_C_TYPE_INT32:
647
for (i = 0; i < count; i++)
648
rv += int32_size(((int32_t *) array)[i]);
649
break;
650
case PROTOBUF_C_TYPE_UINT32:
651
for (i = 0; i < count; i++)
652
rv += uint32_size(((uint32_t *) array)[i]);
653
break;
654
case PROTOBUF_C_TYPE_SINT64:
655
for (i = 0; i < count; i++)
656
rv += sint64_size(((int64_t *) array)[i]);
657
break;
658
case PROTOBUF_C_TYPE_INT64:
659
case PROTOBUF_C_TYPE_UINT64:
660
for (i = 0; i < count; i++)
661
rv += uint64_size(((uint64_t *) array)[i]);
662
break;
663
case PROTOBUF_C_TYPE_SFIXED32:
664
case PROTOBUF_C_TYPE_FIXED32:
665
case PROTOBUF_C_TYPE_FLOAT:
666
rv += 4 * count;
667
break;
668
case PROTOBUF_C_TYPE_SFIXED64:
669
case PROTOBUF_C_TYPE_FIXED64:
670
case PROTOBUF_C_TYPE_DOUBLE:
671
rv += 8 * count;
672
break;
673
case PROTOBUF_C_TYPE_BOOL:
674
rv += count;
675
break;
676
case PROTOBUF_C_TYPE_STRING:
677
for (i = 0; i < count; i++) {
678
size_t len = strlen(((char **) array)[i]);
679
rv += uint32_size(len) + len;
680
}
681
break;
682
case PROTOBUF_C_TYPE_BYTES:
683
for (i = 0; i < count; i++) {
684
size_t len = ((ProtobufCBinaryData *) array)[i].len;
685
rv += uint32_size(len) + len;
686
}
687
break;
688
case PROTOBUF_C_TYPE_MESSAGE:
689
for (i = 0; i < count; i++) {
690
size_t len = protobuf_c_message_get_packed_size(
691
((ProtobufCMessage **) array)[i]);
692
rv += uint32_size(len) + len;
693
}
694
break;
695
}
696
697
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
698
header_size += uint32_size(rv);
699
return header_size + rv;
700
}
701
702
/**
703
* Calculate the serialized size of an unknown field, i.e. one that is passed
704
* through mostly uninterpreted. This is required for forward compatibility if
705
* new fields are added to the message descriptor.
706
*
707
* \param field
708
* Unknown field type.
709
* \return
710
* Number of bytes required.
711
*/
712
static inline size_t
713
unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
714
{
715
return get_tag_size(field->tag) + field->len;
716
}
717
718
/**@}*/
719
720
/*
721
* Calculate the serialized size of the message.
722
*/
723
size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
724
{
725
unsigned i;
726
size_t rv = 0;
727
728
ASSERT_IS_MESSAGE(message);
729
for (i = 0; i < message->descriptor->n_fields; i++) {
730
const ProtobufCFieldDescriptor *field =
731
message->descriptor->fields + i;
732
const void *member =
733
((const char *) message) + field->offset;
734
const void *qmember =
735
((const char *) message) + field->quantifier_offset;
736
737
if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
738
rv += required_field_get_packed_size(field, member);
739
} else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
740
field->label == PROTOBUF_C_LABEL_NONE) &&
741
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
742
rv += oneof_field_get_packed_size(
743
field,
744
*(const uint32_t *) qmember,
745
member
746
);
747
} else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
748
rv += optional_field_get_packed_size(
749
field,
750
*(protobuf_c_boolean *) qmember,
751
member
752
);
753
} else if (field->label == PROTOBUF_C_LABEL_NONE) {
754
rv += unlabeled_field_get_packed_size(
755
field,
756
member
757
);
758
} else {
759
rv += repeated_field_get_packed_size(
760
field,
761
*(const size_t *) qmember,
762
member
763
);
764
}
765
}
766
for (i = 0; i < message->n_unknown_fields; i++)
767
rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
768
return rv;
769
}
770
771
/**
772
* \defgroup pack protobuf_c_message_pack() implementation
773
*
774
* Routines mainly used by protobuf_c_message_pack().
775
*
776
* \ingroup internal
777
* @{
778
*/
779
780
/**
781
* Pack an unsigned 32-bit integer in base-128 varint encoding and return the
782
* number of bytes written, which must be 5 or less.
783
*
784
* \param value
785
* Value to encode.
786
* \param[out] out
787
* Packed value.
788
* \return
789
* Number of bytes written to `out`.
790
*/
791
static inline size_t
792
uint32_pack(uint32_t value, uint8_t *out)
793
{
794
unsigned rv = 0;
795
796
if (value >= 0x80) {
797
out[rv++] = value | 0x80;
798
value >>= 7;
799
if (value >= 0x80) {
800
out[rv++] = value | 0x80;
801
value >>= 7;
802
if (value >= 0x80) {
803
out[rv++] = value | 0x80;
804
value >>= 7;
805
if (value >= 0x80) {
806
out[rv++] = value | 0x80;
807
value >>= 7;
808
}
809
}
810
}
811
}
812
/* assert: value<128 */
813
out[rv++] = value;
814
return rv;
815
}
816
817
/**
818
* Pack a signed 32-bit integer and return the number of bytes written,
819
* passed as unsigned to avoid implementation-specific behavior.
820
* Negative numbers are encoded as two's complement 64-bit integers.
821
*
822
* \param value
823
* Value to encode.
824
* \param[out] out
825
* Packed value.
826
* \return
827
* Number of bytes written to `out`.
828
*/
829
static inline size_t
830
int32_pack(uint32_t value, uint8_t *out)
831
{
832
if ((int32_t)value < 0) {
833
out[0] = value | 0x80;
834
out[1] = (value >> 7) | 0x80;
835
out[2] = (value >> 14) | 0x80;
836
out[3] = (value >> 21) | 0x80;
837
out[4] = (value >> 28) | 0xf0;
838
out[5] = out[6] = out[7] = out[8] = 0xff;
839
out[9] = 0x01;
840
return 10;
841
} else {
842
return uint32_pack(value, out);
843
}
844
}
845
846
/**
847
* Pack a signed 32-bit integer using ZigZag encoding and return the number of
848
* bytes written.
849
*
850
* \param value
851
* Value to encode.
852
* \param[out] out
853
* Packed value.
854
* \return
855
* Number of bytes written to `out`.
856
*/
857
static inline size_t
858
sint32_pack(int32_t value, uint8_t *out)
859
{
860
return uint32_pack(zigzag32(value), out);
861
}
862
863
/**
864
* Pack a 64-bit unsigned integer using base-128 varint encoding and return the
865
* number of bytes written.
866
*
867
* \param value
868
* Value to encode.
869
* \param[out] out
870
* Packed value.
871
* \return
872
* Number of bytes written to `out`.
873
*/
874
static size_t
875
uint64_pack(uint64_t value, uint8_t *out)
876
{
877
uint32_t hi = (uint32_t) (value >> 32);
878
uint32_t lo = (uint32_t) value;
879
unsigned rv;
880
881
if (hi == 0)
882
return uint32_pack((uint32_t) lo, out);
883
out[0] = (lo) | 0x80;
884
out[1] = (lo >> 7) | 0x80;
885
out[2] = (lo >> 14) | 0x80;
886
out[3] = (lo >> 21) | 0x80;
887
if (hi < 8) {
888
out[4] = (hi << 4) | (lo >> 28);
889
return 5;
890
} else {
891
out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
892
hi >>= 3;
893
}
894
rv = 5;
895
while (hi >= 128) {
896
out[rv++] = hi | 0x80;
897
hi >>= 7;
898
}
899
out[rv++] = hi;
900
return rv;
901
}
902
903
/**
904
* Pack a 64-bit signed integer in ZigZag encoding and return the number of
905
* bytes written.
906
*
907
* \param value
908
* Value to encode.
909
* \param[out] out
910
* Packed value.
911
* \return
912
* Number of bytes written to `out`.
913
*/
914
static inline size_t
915
sint64_pack(int64_t value, uint8_t *out)
916
{
917
return uint64_pack(zigzag64(value), out);
918
}
919
920
/**
921
* Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
922
* types fixed32, sfixed32, float. Similar to "htole32".
923
*
924
* \param value
925
* Value to encode.
926
* \param[out] out
927
* Packed value.
928
* \return
929
* Number of bytes written to `out`.
930
*/
931
static inline size_t
932
fixed32_pack(uint32_t value, void *out)
933
{
934
#if !defined(WORDS_BIGENDIAN)
935
memcpy(out, &value, 4);
936
#else
937
uint8_t *buf = out;
938
939
buf[0] = value;
940
buf[1] = value >> 8;
941
buf[2] = value >> 16;
942
buf[3] = value >> 24;
943
#endif
944
return 4;
945
}
946
947
/**
948
* Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
949
* types fixed64, sfixed64, double. Similar to "htole64".
950
*
951
* \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
952
* version would be appreciated, plus a way to decide to use 64-bit math where
953
* convenient.
954
*
955
* \param value
956
* Value to encode.
957
* \param[out] out
958
* Packed value.
959
* \return
960
* Number of bytes written to `out`.
961
*/
962
static inline size_t
963
fixed64_pack(uint64_t value, void *out)
964
{
965
#if !defined(WORDS_BIGENDIAN)
966
memcpy(out, &value, 8);
967
#else
968
fixed32_pack(value, out);
969
fixed32_pack(value >> 32, ((char *) out) + 4);
970
#endif
971
return 8;
972
}
973
974
/**
975
* Pack a boolean value as an integer and return the number of bytes written.
976
*
977
* \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
978
* that is idiomatic C++ in some STL implementations.
979
*
980
* \param value
981
* Value to encode.
982
* \param[out] out
983
* Packed value.
984
* \return
985
* Number of bytes written to `out`.
986
*/
987
static inline size_t
988
boolean_pack(protobuf_c_boolean value, uint8_t *out)
989
{
990
*out = value ? TRUE : FALSE;
991
return 1;
992
}
993
994
/**
995
* Pack a NUL-terminated C string and return the number of bytes written. The
996
* output includes a length delimiter.
997
*
998
* The NULL pointer is treated as an empty string. This isn't really necessary,
999
* but it allows people to leave required strings blank. (See Issue #13 in the
1000
* bug tracker for a little more explanation).
1001
*
1002
* \param str
1003
* String to encode.
1004
* \param[out] out
1005
* Packed value.
1006
* \return
1007
* Number of bytes written to `out`.
1008
*/
1009
static inline size_t
1010
string_pack(const char *str, uint8_t *out)
1011
{
1012
if (str == NULL) {
1013
out[0] = 0;
1014
return 1;
1015
} else {
1016
size_t len = strlen(str);
1017
size_t rv = uint32_pack(len, out);
1018
memcpy(out + rv, str, len);
1019
return rv + len;
1020
}
1021
}
1022
1023
/**
1024
* Pack a ProtobufCBinaryData and return the number of bytes written. The output
1025
* includes a length delimiter.
1026
*
1027
* \param bd
1028
* ProtobufCBinaryData to encode.
1029
* \param[out] out
1030
* Packed value.
1031
* \return
1032
* Number of bytes written to `out`.
1033
*/
1034
static inline size_t
1035
binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
1036
{
1037
size_t len = bd->len;
1038
size_t rv = uint32_pack(len, out);
1039
memcpy(out + rv, bd->data, len);
1040
return rv + len;
1041
}
1042
1043
/**
1044
* Pack a ProtobufCMessage and return the number of bytes written. The output
1045
* includes a length delimiter.
1046
*
1047
* \param message
1048
* ProtobufCMessage object to pack.
1049
* \param[out] out
1050
* Packed message.
1051
* \return
1052
* Number of bytes written to `out`.
1053
*/
1054
static inline size_t
1055
prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
1056
{
1057
if (message == NULL) {
1058
out[0] = 0;
1059
return 1;
1060
} else {
1061
size_t rv = protobuf_c_message_pack(message, out + 1);
1062
uint32_t rv_packed_size = uint32_size(rv);
1063
if (rv_packed_size != 1)
1064
memmove(out + rv_packed_size, out + 1, rv);
1065
return uint32_pack(rv, out) + rv;
1066
}
1067
}
1068
1069
/**
1070
* Pack a field tag.
1071
*
1072
* Wire-type will be added in required_field_pack().
1073
*
1074
* \todo Just call uint64_pack on 64-bit platforms.
1075
*
1076
* \param id
1077
* Tag value to encode.
1078
* \param[out] out
1079
* Packed value.
1080
* \return
1081
* Number of bytes written to `out`.
1082
*/
1083
static size_t
1084
tag_pack(uint32_t id, uint8_t *out)
1085
{
1086
if (id < (1UL << (32 - 3)))
1087
return uint32_pack(id << 3, out);
1088
else
1089
return uint64_pack(((uint64_t) id) << 3, out);
1090
}
1091
1092
/**
1093
* Pack a required field and return the number of bytes written.
1094
*
1095
* \param field
1096
* Field descriptor.
1097
* \param member
1098
* The field member.
1099
* \param[out] out
1100
* Packed value.
1101
* \return
1102
* Number of bytes written to `out`.
1103
*/
1104
static size_t
1105
required_field_pack(const ProtobufCFieldDescriptor *field,
1106
const void *member, uint8_t *out)
1107
{
1108
size_t rv = tag_pack(field->id, out);
1109
1110
switch (field->type) {
1111
case PROTOBUF_C_TYPE_SINT32:
1112
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1113
return rv + sint32_pack(*(const int32_t *) member, out + rv);
1114
case PROTOBUF_C_TYPE_ENUM:
1115
case PROTOBUF_C_TYPE_INT32:
1116
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1117
return rv + int32_pack(*(const int32_t *) member, out + rv);
1118
case PROTOBUF_C_TYPE_UINT32:
1119
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1120
return rv + uint32_pack(*(const uint32_t *) member, out + rv);
1121
case PROTOBUF_C_TYPE_SINT64:
1122
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1123
return rv + sint64_pack(*(const int64_t *) member, out + rv);
1124
case PROTOBUF_C_TYPE_INT64:
1125
case PROTOBUF_C_TYPE_UINT64:
1126
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1127
return rv + uint64_pack(*(const uint64_t *) member, out + rv);
1128
case PROTOBUF_C_TYPE_SFIXED32:
1129
case PROTOBUF_C_TYPE_FIXED32:
1130
case PROTOBUF_C_TYPE_FLOAT:
1131
out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1132
return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
1133
case PROTOBUF_C_TYPE_SFIXED64:
1134
case PROTOBUF_C_TYPE_FIXED64:
1135
case PROTOBUF_C_TYPE_DOUBLE:
1136
out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1137
return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
1138
case PROTOBUF_C_TYPE_BOOL:
1139
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1140
return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
1141
case PROTOBUF_C_TYPE_STRING:
1142
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1143
return rv + string_pack(*(char *const *) member, out + rv);
1144
case PROTOBUF_C_TYPE_BYTES:
1145
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1146
return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
1147
case PROTOBUF_C_TYPE_MESSAGE:
1148
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1149
return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
1150
}
1151
PROTOBUF_C__ASSERT_NOT_REACHED();
1152
return 0;
1153
}
1154
1155
/**
1156
* Pack a oneof field and return the number of bytes written. Only packs the
1157
* field that is selected by the case enum.
1158
*
1159
* \param field
1160
* Field descriptor.
1161
* \param oneof_case
1162
* Enum value that selects the field in the oneof.
1163
* \param member
1164
* The field member.
1165
* \param[out] out
1166
* Packed value.
1167
* \return
1168
* Number of bytes written to `out`.
1169
*/
1170
static size_t
1171
oneof_field_pack(const ProtobufCFieldDescriptor *field,
1172
uint32_t oneof_case,
1173
const void *member, uint8_t *out)
1174
{
1175
if (oneof_case != field->id) {
1176
return 0;
1177
}
1178
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1179
field->type == PROTOBUF_C_TYPE_STRING)
1180
{
1181
const void *ptr = *(const void * const *) member;
1182
if (ptr == NULL || ptr == field->default_value)
1183
return 0;
1184
}
1185
return required_field_pack(field, member, out);
1186
}
1187
1188
/**
1189
* Pack an optional field and return the number of bytes written.
1190
*
1191
* \param field
1192
* Field descriptor.
1193
* \param has
1194
* Whether the field is set.
1195
* \param member
1196
* The field member.
1197
* \param[out] out
1198
* Packed value.
1199
* \return
1200
* Number of bytes written to `out`.
1201
*/
1202
static size_t
1203
optional_field_pack(const ProtobufCFieldDescriptor *field,
1204
const protobuf_c_boolean has,
1205
const void *member, uint8_t *out)
1206
{
1207
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1208
field->type == PROTOBUF_C_TYPE_STRING)
1209
{
1210
const void *ptr = *(const void * const *) member;
1211
if (ptr == NULL || ptr == field->default_value)
1212
return 0;
1213
} else {
1214
if (!has)
1215
return 0;
1216
}
1217
return required_field_pack(field, member, out);
1218
}
1219
1220
/**
1221
* Pack an unlabeled field and return the number of bytes written.
1222
*
1223
* \param field
1224
* Field descriptor.
1225
* \param member
1226
* The field member.
1227
* \param[out] out
1228
* Packed value.
1229
* \return
1230
* Number of bytes written to `out`.
1231
*/
1232
static size_t
1233
unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
1234
const void *member, uint8_t *out)
1235
{
1236
if (field_is_zeroish(field, member))
1237
return 0;
1238
return required_field_pack(field, member, out);
1239
}
1240
1241
/**
1242
* Given a field type, return the in-memory size.
1243
*
1244
* \todo Implement as a table lookup.
1245
*
1246
* \param type
1247
* Field type.
1248
* \return
1249
* Size of the field.
1250
*/
1251
static inline size_t
1252
sizeof_elt_in_repeated_array(ProtobufCType type)
1253
{
1254
switch (type) {
1255
case PROTOBUF_C_TYPE_SINT32:
1256
case PROTOBUF_C_TYPE_INT32:
1257
case PROTOBUF_C_TYPE_UINT32:
1258
case PROTOBUF_C_TYPE_SFIXED32:
1259
case PROTOBUF_C_TYPE_FIXED32:
1260
case PROTOBUF_C_TYPE_FLOAT:
1261
case PROTOBUF_C_TYPE_ENUM:
1262
return 4;
1263
case PROTOBUF_C_TYPE_SINT64:
1264
case PROTOBUF_C_TYPE_INT64:
1265
case PROTOBUF_C_TYPE_UINT64:
1266
case PROTOBUF_C_TYPE_SFIXED64:
1267
case PROTOBUF_C_TYPE_FIXED64:
1268
case PROTOBUF_C_TYPE_DOUBLE:
1269
return 8;
1270
case PROTOBUF_C_TYPE_BOOL:
1271
return sizeof(protobuf_c_boolean);
1272
case PROTOBUF_C_TYPE_STRING:
1273
case PROTOBUF_C_TYPE_MESSAGE:
1274
return sizeof(void *);
1275
case PROTOBUF_C_TYPE_BYTES:
1276
return sizeof(ProtobufCBinaryData);
1277
}
1278
PROTOBUF_C__ASSERT_NOT_REACHED();
1279
return 0;
1280
}
1281
1282
/**
1283
* Pack an array of 32-bit quantities.
1284
*
1285
* \param[out] out
1286
* Destination.
1287
* \param[in] in
1288
* Source.
1289
* \param[in] n
1290
* Number of elements in the source array.
1291
*/
1292
static void
1293
copy_to_little_endian_32(void *out, const void *in, const unsigned n)
1294
{
1295
#if !defined(WORDS_BIGENDIAN)
1296
memcpy(out, in, n * 4);
1297
#else
1298
unsigned i;
1299
const uint32_t *ini = in;
1300
for (i = 0; i < n; i++)
1301
fixed32_pack(ini[i], (uint32_t *) out + i);
1302
#endif
1303
}
1304
1305
/**
1306
* Pack an array of 64-bit quantities.
1307
*
1308
* \param[out] out
1309
* Destination.
1310
* \param[in] in
1311
* Source.
1312
* \param[in] n
1313
* Number of elements in the source array.
1314
*/
1315
static void
1316
copy_to_little_endian_64(void *out, const void *in, const unsigned n)
1317
{
1318
#if !defined(WORDS_BIGENDIAN)
1319
memcpy(out, in, n * 8);
1320
#else
1321
unsigned i;
1322
const uint64_t *ini = in;
1323
for (i = 0; i < n; i++)
1324
fixed64_pack(ini[i], (uint64_t *) out + i);
1325
#endif
1326
}
1327
1328
/**
1329
* Get the minimum number of bytes required to pack a field value of a
1330
* particular type.
1331
*
1332
* \param type
1333
* Field type.
1334
* \return
1335
* Number of bytes.
1336
*/
1337
static unsigned
1338
get_type_min_size(ProtobufCType type)
1339
{
1340
if (type == PROTOBUF_C_TYPE_SFIXED32 ||
1341
type == PROTOBUF_C_TYPE_FIXED32 ||
1342
type == PROTOBUF_C_TYPE_FLOAT)
1343
{
1344
return 4;
1345
}
1346
if (type == PROTOBUF_C_TYPE_SFIXED64 ||
1347
type == PROTOBUF_C_TYPE_FIXED64 ||
1348
type == PROTOBUF_C_TYPE_DOUBLE)
1349
{
1350
return 8;
1351
}
1352
return 1;
1353
}
1354
1355
/**
1356
* Packs the elements of a repeated field and returns the serialised field and
1357
* its length.
1358
*
1359
* \param field
1360
* Field descriptor.
1361
* \param count
1362
* Number of elements in the repeated field array.
1363
* \param member
1364
* Pointer to the elements for this repeated field.
1365
* \param[out] out
1366
* Serialised representation of the repeated field.
1367
* \return
1368
* Number of bytes serialised to `out`.
1369
*/
1370
static size_t
1371
repeated_field_pack(const ProtobufCFieldDescriptor *field,
1372
size_t count, const void *member, uint8_t *out)
1373
{
1374
void *array = *(void * const *) member;
1375
unsigned i;
1376
1377
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1378
unsigned header_len;
1379
unsigned len_start;
1380
unsigned min_length;
1381
unsigned payload_len;
1382
unsigned length_size_min;
1383
unsigned actual_length_size;
1384
uint8_t *payload_at;
1385
1386
if (count == 0)
1387
return 0;
1388
header_len = tag_pack(field->id, out);
1389
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1390
len_start = header_len;
1391
min_length = get_type_min_size(field->type) * count;
1392
length_size_min = uint32_size(min_length);
1393
header_len += length_size_min;
1394
payload_at = out + header_len;
1395
1396
switch (field->type) {
1397
case PROTOBUF_C_TYPE_SFIXED32:
1398
case PROTOBUF_C_TYPE_FIXED32:
1399
case PROTOBUF_C_TYPE_FLOAT:
1400
copy_to_little_endian_32(payload_at, array, count);
1401
payload_at += count * 4;
1402
break;
1403
case PROTOBUF_C_TYPE_SFIXED64:
1404
case PROTOBUF_C_TYPE_FIXED64:
1405
case PROTOBUF_C_TYPE_DOUBLE:
1406
copy_to_little_endian_64(payload_at, array, count);
1407
payload_at += count * 8;
1408
break;
1409
case PROTOBUF_C_TYPE_ENUM:
1410
case PROTOBUF_C_TYPE_INT32: {
1411
const int32_t *arr = (const int32_t *) array;
1412
for (i = 0; i < count; i++)
1413
payload_at += int32_pack(arr[i], payload_at);
1414
break;
1415
}
1416
case PROTOBUF_C_TYPE_SINT32: {
1417
const int32_t *arr = (const int32_t *) array;
1418
for (i = 0; i < count; i++)
1419
payload_at += sint32_pack(arr[i], payload_at);
1420
break;
1421
}
1422
case PROTOBUF_C_TYPE_SINT64: {
1423
const int64_t *arr = (const int64_t *) array;
1424
for (i = 0; i < count; i++)
1425
payload_at += sint64_pack(arr[i], payload_at);
1426
break;
1427
}
1428
case PROTOBUF_C_TYPE_UINT32: {
1429
const uint32_t *arr = (const uint32_t *) array;
1430
for (i = 0; i < count; i++)
1431
payload_at += uint32_pack(arr[i], payload_at);
1432
break;
1433
}
1434
case PROTOBUF_C_TYPE_INT64:
1435
case PROTOBUF_C_TYPE_UINT64: {
1436
const uint64_t *arr = (const uint64_t *) array;
1437
for (i = 0; i < count; i++)
1438
payload_at += uint64_pack(arr[i], payload_at);
1439
break;
1440
}
1441
case PROTOBUF_C_TYPE_BOOL: {
1442
const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
1443
for (i = 0; i < count; i++)
1444
payload_at += boolean_pack(arr[i], payload_at);
1445
break;
1446
}
1447
default:
1448
PROTOBUF_C__ASSERT_NOT_REACHED();
1449
}
1450
1451
payload_len = payload_at - (out + header_len);
1452
actual_length_size = uint32_size(payload_len);
1453
if (length_size_min != actual_length_size) {
1454
assert(actual_length_size == length_size_min + 1);
1455
memmove(out + header_len + 1, out + header_len,
1456
payload_len);
1457
header_len++;
1458
}
1459
uint32_pack(payload_len, out + len_start);
1460
return header_len + payload_len;
1461
} else {
1462
/* not "packed" cased */
1463
/* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1464
size_t rv = 0;
1465
unsigned siz = sizeof_elt_in_repeated_array(field->type);
1466
1467
for (i = 0; i < count; i++) {
1468
rv += required_field_pack(field, array, out + rv);
1469
array = (char *)array + siz;
1470
}
1471
return rv;
1472
}
1473
}
1474
1475
static size_t
1476
unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
1477
{
1478
size_t rv = tag_pack(field->tag, out);
1479
out[0] |= field->wire_type;
1480
memcpy(out + rv, field->data, field->len);
1481
return rv + field->len;
1482
}
1483
1484
/**@}*/
1485
1486
size_t
1487
protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
1488
{
1489
unsigned i;
1490
size_t rv = 0;
1491
1492
ASSERT_IS_MESSAGE(message);
1493
for (i = 0; i < message->descriptor->n_fields; i++) {
1494
const ProtobufCFieldDescriptor *field =
1495
message->descriptor->fields + i;
1496
const void *member = ((const char *) message) + field->offset;
1497
1498
/*
1499
* It doesn't hurt to compute qmember (a pointer to the
1500
* quantifier field of the structure), but the pointer is only
1501
* valid if the field is:
1502
* - a repeated field, or
1503
* - a field that is part of a oneof
1504
* - an optional field that isn't a pointer type
1505
* (Meaning: not a message or a string).
1506
*/
1507
const void *qmember =
1508
((const char *) message) + field->quantifier_offset;
1509
1510
if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1511
rv += required_field_pack(field, member, out + rv);
1512
} else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1513
field->label == PROTOBUF_C_LABEL_NONE) &&
1514
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1515
rv += oneof_field_pack(
1516
field,
1517
*(const uint32_t *) qmember,
1518
member,
1519
out + rv
1520
);
1521
} else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1522
rv += optional_field_pack(
1523
field,
1524
*(const protobuf_c_boolean *) qmember,
1525
member,
1526
out + rv
1527
);
1528
} else if (field->label == PROTOBUF_C_LABEL_NONE) {
1529
rv += unlabeled_field_pack(field, member, out + rv);
1530
} else {
1531
rv += repeated_field_pack(field, *(const size_t *) qmember,
1532
member, out + rv);
1533
}
1534
}
1535
for (i = 0; i < message->n_unknown_fields; i++)
1536
rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
1537
return rv;
1538
}
1539
1540
/**
1541
* \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
1542
*
1543
* Routines mainly used by protobuf_c_message_pack_to_buffer().
1544
*
1545
* \ingroup internal
1546
* @{
1547
*/
1548
1549
/**
1550
* Pack a required field to a virtual buffer.
1551
*
1552
* \param field
1553
* Field descriptor.
1554
* \param member
1555
* The element to be packed.
1556
* \param[out] buffer
1557
* Virtual buffer to append data to.
1558
* \return
1559
* Number of bytes packed.
1560
*/
1561
static size_t
1562
required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1563
const void *member, ProtobufCBuffer *buffer)
1564
{
1565
size_t rv;
1566
uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1567
1568
rv = tag_pack(field->id, scratch);
1569
switch (field->type) {
1570
case PROTOBUF_C_TYPE_SINT32:
1571
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1572
rv += sint32_pack(*(const int32_t *) member, scratch + rv);
1573
buffer->append(buffer, rv, scratch);
1574
break;
1575
case PROTOBUF_C_TYPE_ENUM:
1576
case PROTOBUF_C_TYPE_INT32:
1577
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1578
rv += int32_pack(*(const int32_t *) member, scratch + rv);
1579
buffer->append(buffer, rv, scratch);
1580
break;
1581
case PROTOBUF_C_TYPE_UINT32:
1582
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1583
rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
1584
buffer->append(buffer, rv, scratch);
1585
break;
1586
case PROTOBUF_C_TYPE_SINT64:
1587
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1588
rv += sint64_pack(*(const int64_t *) member, scratch + rv);
1589
buffer->append(buffer, rv, scratch);
1590
break;
1591
case PROTOBUF_C_TYPE_INT64:
1592
case PROTOBUF_C_TYPE_UINT64:
1593
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1594
rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
1595
buffer->append(buffer, rv, scratch);
1596
break;
1597
case PROTOBUF_C_TYPE_SFIXED32:
1598
case PROTOBUF_C_TYPE_FIXED32:
1599
case PROTOBUF_C_TYPE_FLOAT:
1600
scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1601
rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
1602
buffer->append(buffer, rv, scratch);
1603
break;
1604
case PROTOBUF_C_TYPE_SFIXED64:
1605
case PROTOBUF_C_TYPE_FIXED64:
1606
case PROTOBUF_C_TYPE_DOUBLE:
1607
scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1608
rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
1609
buffer->append(buffer, rv, scratch);
1610
break;
1611
case PROTOBUF_C_TYPE_BOOL:
1612
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1613
rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
1614
buffer->append(buffer, rv, scratch);
1615
break;
1616
case PROTOBUF_C_TYPE_STRING: {
1617
const char *str = *(char *const *) member;
1618
size_t sublen = str ? strlen(str) : 0;
1619
1620
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1621
rv += uint32_pack(sublen, scratch + rv);
1622
buffer->append(buffer, rv, scratch);
1623
buffer->append(buffer, sublen, (const uint8_t *) str);
1624
rv += sublen;
1625
break;
1626
}
1627
case PROTOBUF_C_TYPE_BYTES: {
1628
const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
1629
size_t sublen = bd->len;
1630
1631
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1632
rv += uint32_pack(sublen, scratch + rv);
1633
buffer->append(buffer, rv, scratch);
1634
buffer->append(buffer, sublen, bd->data);
1635
rv += sublen;
1636
break;
1637
}
1638
case PROTOBUF_C_TYPE_MESSAGE: {
1639
const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1640
1641
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1642
if (msg == NULL) {
1643
rv += uint32_pack(0, scratch + rv);
1644
buffer->append(buffer, rv, scratch);
1645
} else {
1646
size_t sublen = protobuf_c_message_get_packed_size(msg);
1647
rv += uint32_pack(sublen, scratch + rv);
1648
buffer->append(buffer, rv, scratch);
1649
protobuf_c_message_pack_to_buffer(msg, buffer);
1650
rv += sublen;
1651
}
1652
break;
1653
}
1654
default:
1655
PROTOBUF_C__ASSERT_NOT_REACHED();
1656
}
1657
return rv;
1658
}
1659
1660
/**
1661
* Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
1662
*
1663
* \param field
1664
* Field descriptor.
1665
* \param oneof_case
1666
* Enum value that selects the field in the oneof.
1667
* \param member
1668
* The element to be packed.
1669
* \param[out] buffer
1670
* Virtual buffer to append data to.
1671
* \return
1672
* Number of bytes serialised to `buffer`.
1673
*/
1674
static size_t
1675
oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1676
uint32_t oneof_case,
1677
const void *member, ProtobufCBuffer *buffer)
1678
{
1679
if (oneof_case != field->id) {
1680
return 0;
1681
}
1682
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1683
field->type == PROTOBUF_C_TYPE_STRING)
1684
{
1685
const void *ptr = *(const void *const *) member;
1686
if (ptr == NULL || ptr == field->default_value)
1687
return 0;
1688
}
1689
return required_field_pack_to_buffer(field, member, buffer);
1690
}
1691
1692
/**
1693
* Pack an optional field to a buffer.
1694
*
1695
* \param field
1696
* Field descriptor.
1697
* \param has
1698
* Whether the field is set.
1699
* \param member
1700
* The element to be packed.
1701
* \param[out] buffer
1702
* Virtual buffer to append data to.
1703
* \return
1704
* Number of bytes serialised to `buffer`.
1705
*/
1706
static size_t
1707
optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1708
const protobuf_c_boolean has,
1709
const void *member, ProtobufCBuffer *buffer)
1710
{
1711
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1712
field->type == PROTOBUF_C_TYPE_STRING)
1713
{
1714
const void *ptr = *(const void *const *) member;
1715
if (ptr == NULL || ptr == field->default_value)
1716
return 0;
1717
} else {
1718
if (!has)
1719
return 0;
1720
}
1721
return required_field_pack_to_buffer(field, member, buffer);
1722
}
1723
1724
/**
1725
* Pack an unlabeled field to a buffer.
1726
*
1727
* \param field
1728
* Field descriptor.
1729
* \param member
1730
* The element to be packed.
1731
* \param[out] buffer
1732
* Virtual buffer to append data to.
1733
* \return
1734
* Number of bytes serialised to `buffer`.
1735
*/
1736
static size_t
1737
unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1738
const void *member, ProtobufCBuffer *buffer)
1739
{
1740
if (field_is_zeroish(field, member))
1741
return 0;
1742
return required_field_pack_to_buffer(field, member, buffer);
1743
}
1744
1745
/**
1746
* Get the packed size of an array of same field type.
1747
*
1748
* \param field
1749
* Field descriptor.
1750
* \param count
1751
* Number of elements of this type.
1752
* \param array
1753
* The elements to get the size of.
1754
* \return
1755
* Number of bytes required.
1756
*/
1757
static size_t
1758
get_packed_payload_length(const ProtobufCFieldDescriptor *field,
1759
unsigned count, const void *array)
1760
{
1761
unsigned rv = 0;
1762
unsigned i;
1763
1764
switch (field->type) {
1765
case PROTOBUF_C_TYPE_SFIXED32:
1766
case PROTOBUF_C_TYPE_FIXED32:
1767
case PROTOBUF_C_TYPE_FLOAT:
1768
return count * 4;
1769
case PROTOBUF_C_TYPE_SFIXED64:
1770
case PROTOBUF_C_TYPE_FIXED64:
1771
case PROTOBUF_C_TYPE_DOUBLE:
1772
return count * 8;
1773
case PROTOBUF_C_TYPE_ENUM:
1774
case PROTOBUF_C_TYPE_INT32: {
1775
const int32_t *arr = (const int32_t *) array;
1776
for (i = 0; i < count; i++)
1777
rv += int32_size(arr[i]);
1778
break;
1779
}
1780
case PROTOBUF_C_TYPE_SINT32: {
1781
const int32_t *arr = (const int32_t *) array;
1782
for (i = 0; i < count; i++)
1783
rv += sint32_size(arr[i]);
1784
break;
1785
}
1786
case PROTOBUF_C_TYPE_UINT32: {
1787
const uint32_t *arr = (const uint32_t *) array;
1788
for (i = 0; i < count; i++)
1789
rv += uint32_size(arr[i]);
1790
break;
1791
}
1792
case PROTOBUF_C_TYPE_SINT64: {
1793
const int64_t *arr = (const int64_t *) array;
1794
for (i = 0; i < count; i++)
1795
rv += sint64_size(arr[i]);
1796
break;
1797
}
1798
case PROTOBUF_C_TYPE_INT64:
1799
case PROTOBUF_C_TYPE_UINT64: {
1800
const uint64_t *arr = (const uint64_t *) array;
1801
for (i = 0; i < count; i++)
1802
rv += uint64_size(arr[i]);
1803
break;
1804
}
1805
case PROTOBUF_C_TYPE_BOOL:
1806
return count;
1807
default:
1808
PROTOBUF_C__ASSERT_NOT_REACHED();
1809
}
1810
return rv;
1811
}
1812
1813
/**
1814
* Pack an array of same field type to a virtual buffer.
1815
*
1816
* \param field
1817
* Field descriptor.
1818
* \param count
1819
* Number of elements of this type.
1820
* \param array
1821
* The elements to get the size of.
1822
* \param[out] buffer
1823
* Virtual buffer to append data to.
1824
* \return
1825
* Number of bytes packed.
1826
*/
1827
static size_t
1828
pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
1829
unsigned count, const void *array,
1830
ProtobufCBuffer *buffer)
1831
{
1832
uint8_t scratch[16];
1833
size_t rv = 0;
1834
unsigned i;
1835
1836
switch (field->type) {
1837
case PROTOBUF_C_TYPE_SFIXED32:
1838
case PROTOBUF_C_TYPE_FIXED32:
1839
case PROTOBUF_C_TYPE_FLOAT:
1840
#if !defined(WORDS_BIGENDIAN)
1841
rv = count * 4;
1842
goto no_packing_needed;
1843
#else
1844
for (i = 0; i < count; i++) {
1845
unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
1846
buffer->append(buffer, len, scratch);
1847
rv += len;
1848
}
1849
break;
1850
#endif
1851
case PROTOBUF_C_TYPE_SFIXED64:
1852
case PROTOBUF_C_TYPE_FIXED64:
1853
case PROTOBUF_C_TYPE_DOUBLE:
1854
#if !defined(WORDS_BIGENDIAN)
1855
rv = count * 8;
1856
goto no_packing_needed;
1857
#else
1858
for (i = 0; i < count; i++) {
1859
unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
1860
buffer->append(buffer, len, scratch);
1861
rv += len;
1862
}
1863
break;
1864
#endif
1865
case PROTOBUF_C_TYPE_ENUM:
1866
case PROTOBUF_C_TYPE_INT32:
1867
for (i = 0; i < count; i++) {
1868
unsigned len = int32_pack(((int32_t *) array)[i], scratch);
1869
buffer->append(buffer, len, scratch);
1870
rv += len;
1871
}
1872
break;
1873
case PROTOBUF_C_TYPE_SINT32:
1874
for (i = 0; i < count; i++) {
1875
unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
1876
buffer->append(buffer, len, scratch);
1877
rv += len;
1878
}
1879
break;
1880
case PROTOBUF_C_TYPE_UINT32:
1881
for (i = 0; i < count; i++) {
1882
unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
1883
buffer->append(buffer, len, scratch);
1884
rv += len;
1885
}
1886
break;
1887
case PROTOBUF_C_TYPE_SINT64:
1888
for (i = 0; i < count; i++) {
1889
unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
1890
buffer->append(buffer, len, scratch);
1891
rv += len;
1892
}
1893
break;
1894
case PROTOBUF_C_TYPE_INT64:
1895
case PROTOBUF_C_TYPE_UINT64:
1896
for (i = 0; i < count; i++) {
1897
unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
1898
buffer->append(buffer, len, scratch);
1899
rv += len;
1900
}
1901
break;
1902
case PROTOBUF_C_TYPE_BOOL:
1903
for (i = 0; i < count; i++) {
1904
unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
1905
buffer->append(buffer, len, scratch);
1906
}
1907
return count;
1908
default:
1909
PROTOBUF_C__ASSERT_NOT_REACHED();
1910
}
1911
return rv;
1912
1913
#if !defined(WORDS_BIGENDIAN)
1914
no_packing_needed:
1915
buffer->append(buffer, rv, array);
1916
return rv;
1917
#endif
1918
}
1919
1920
static size_t
1921
repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1922
unsigned count, const void *member,
1923
ProtobufCBuffer *buffer)
1924
{
1925
char *array = *(char * const *) member;
1926
1927
if (count == 0)
1928
return 0;
1929
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1930
uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1931
size_t rv = tag_pack(field->id, scratch);
1932
size_t payload_len = get_packed_payload_length(field, count, array);
1933
size_t tmp;
1934
1935
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1936
rv += uint32_pack(payload_len, scratch + rv);
1937
buffer->append(buffer, rv, scratch);
1938
tmp = pack_buffer_packed_payload(field, count, array, buffer);
1939
assert(tmp == payload_len);
1940
(void)tmp;
1941
return rv + payload_len;
1942
} else {
1943
size_t siz;
1944
unsigned i;
1945
/* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1946
unsigned rv = 0;
1947
1948
siz = sizeof_elt_in_repeated_array(field->type);
1949
for (i = 0; i < count; i++) {
1950
rv += required_field_pack_to_buffer(field, array, buffer);
1951
array += siz;
1952
}
1953
return rv;
1954
}
1955
}
1956
1957
static size_t
1958
unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
1959
ProtobufCBuffer *buffer)
1960
{
1961
uint8_t header[MAX_UINT64_ENCODED_SIZE];
1962
size_t rv = tag_pack(field->tag, header);
1963
1964
header[0] |= field->wire_type;
1965
buffer->append(buffer, rv, header);
1966
buffer->append(buffer, field->len, field->data);
1967
return rv + field->len;
1968
}
1969
1970
/**@}*/
1971
1972
size_t
1973
protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
1974
ProtobufCBuffer *buffer)
1975
{
1976
unsigned i;
1977
size_t rv = 0;
1978
1979
ASSERT_IS_MESSAGE(message);
1980
for (i = 0; i < message->descriptor->n_fields; i++) {
1981
const ProtobufCFieldDescriptor *field =
1982
message->descriptor->fields + i;
1983
const void *member =
1984
((const char *) message) + field->offset;
1985
const void *qmember =
1986
((const char *) message) + field->quantifier_offset;
1987
1988
if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1989
rv += required_field_pack_to_buffer(field, member, buffer);
1990
} else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1991
field->label == PROTOBUF_C_LABEL_NONE) &&
1992
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1993
rv += oneof_field_pack_to_buffer(
1994
field,
1995
*(const uint32_t *) qmember,
1996
member,
1997
buffer
1998
);
1999
} else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
2000
rv += optional_field_pack_to_buffer(
2001
field,
2002
*(const protobuf_c_boolean *) qmember,
2003
member,
2004
buffer
2005
);
2006
} else if (field->label == PROTOBUF_C_LABEL_NONE) {
2007
rv += unlabeled_field_pack_to_buffer(
2008
field,
2009
member,
2010
buffer
2011
);
2012
} else {
2013
rv += repeated_field_pack_to_buffer(
2014
field,
2015
*(const size_t *) qmember,
2016
member,
2017
buffer
2018
);
2019
}
2020
}
2021
for (i = 0; i < message->n_unknown_fields; i++)
2022
rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
2023
2024
return rv;
2025
}
2026
2027
/**
2028
* \defgroup unpack unpacking implementation
2029
*
2030
* Routines mainly used by the unpacking functions.
2031
*
2032
* \ingroup internal
2033
* @{
2034
*/
2035
2036
static inline int
2037
int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
2038
{
2039
unsigned n;
2040
unsigned start;
2041
2042
if (n_ranges == 0)
2043
return -1;
2044
start = 0;
2045
n = n_ranges;
2046
while (n > 1) {
2047
unsigned mid = start + n / 2;
2048
2049
if (value < ranges[mid].start_value) {
2050
n = mid - start;
2051
} else if (value >= ranges[mid].start_value +
2052
(int) (ranges[mid + 1].orig_index -
2053
ranges[mid].orig_index))
2054
{
2055
unsigned new_start = mid + 1;
2056
n = start + n - new_start;
2057
start = new_start;
2058
} else
2059
return (value - ranges[mid].start_value) +
2060
ranges[mid].orig_index;
2061
}
2062
if (n > 0) {
2063
unsigned start_orig_index = ranges[start].orig_index;
2064
unsigned range_size =
2065
ranges[start + 1].orig_index - start_orig_index;
2066
2067
if (ranges[start].start_value <= value &&
2068
value < (int) (ranges[start].start_value + range_size))
2069
{
2070
return (value - ranges[start].start_value) +
2071
start_orig_index;
2072
}
2073
}
2074
return -1;
2075
}
2076
2077
static size_t
2078
parse_tag_and_wiretype(size_t len,
2079
const uint8_t *data,
2080
uint32_t *tag_out,
2081
uint8_t *wiretype_out)
2082
{
2083
unsigned max_rv = len > 5 ? 5 : len;
2084
uint32_t tag = (data[0] & 0x7f) >> 3;
2085
unsigned shift = 4;
2086
unsigned rv;
2087
2088
/* 0 is not a valid tag value */
2089
if ((data[0] & 0xf8) == 0) {
2090
return 0;
2091
}
2092
2093
*wiretype_out = data[0] & 7;
2094
if ((data[0] & 0x80) == 0) {
2095
*tag_out = tag;
2096
return 1;
2097
}
2098
for (rv = 1; rv < max_rv; rv++) {
2099
if (data[rv] & 0x80) {
2100
tag |= (data[rv] & 0x7f) << shift;
2101
shift += 7;
2102
} else {
2103
tag |= data[rv] << shift;
2104
*tag_out = tag;
2105
return rv + 1;
2106
}
2107
}
2108
return 0; /* error: bad header */
2109
}
2110
2111
/* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
2112
#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
2113
typedef struct ScannedMember ScannedMember;
2114
/** Field as it's being read. */
2115
struct ScannedMember {
2116
uint32_t tag; /**< Field tag. */
2117
uint8_t wire_type; /**< Field type. */
2118
uint8_t length_prefix_len; /**< Prefix length. */
2119
const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
2120
size_t len; /**< Field length. */
2121
const uint8_t *data; /**< Pointer to field data. */
2122
};
2123
2124
static inline size_t
2125
scan_length_prefixed_data(size_t len, const uint8_t *data,
2126
size_t *prefix_len_out)
2127
{
2128
unsigned hdr_max = len < 5 ? len : 5;
2129
unsigned hdr_len;
2130
size_t val = 0;
2131
unsigned i;
2132
unsigned shift = 0;
2133
2134
for (i = 0; i < hdr_max; i++) {
2135
val |= ((size_t)data[i] & 0x7f) << shift;
2136
shift += 7;
2137
if ((data[i] & 0x80) == 0)
2138
break;
2139
}
2140
if (i == hdr_max) {
2141
PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
2142
return 0;
2143
}
2144
hdr_len = i + 1;
2145
*prefix_len_out = hdr_len;
2146
if (val > INT_MAX) {
2147
// Protobuf messages should always be less than 2 GiB in size.
2148
// We also want to return early here so that hdr_len + val does
2149
// not overflow on 32-bit systems.
2150
PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large",
2151
(unsigned long int)val);
2152
return 0;
2153
}
2154
if (hdr_len + val > len) {
2155
PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu",
2156
(unsigned long int)val);
2157
return 0;
2158
}
2159
return hdr_len + val;
2160
}
2161
2162
static size_t
2163
max_b128_numbers(size_t len, const uint8_t *data)
2164
{
2165
size_t rv = 0;
2166
while (len--)
2167
if ((*data++ & 0x80) == 0)
2168
++rv;
2169
return rv;
2170
}
2171
2172
/**@}*/
2173
2174
/**
2175
* Merge earlier message into a latter message.
2176
*
2177
* For numeric types and strings, if the same value appears multiple
2178
* times, the parser accepts the last value it sees. For embedded
2179
* message fields, the parser merges multiple instances of the same
2180
* field. That is, all singular scalar fields in the latter instance
2181
* replace those in the former, singular embedded messages are merged,
2182
* and repeated fields are concatenated.
2183
*
2184
* The earlier message should be freed after calling this function, as
2185
* some of its fields may have been reused and changed to their default
2186
* values during the merge.
2187
*/
2188
static protobuf_c_boolean
2189
merge_messages(ProtobufCMessage *earlier_msg,
2190
ProtobufCMessage *latter_msg,
2191
ProtobufCAllocator *allocator)
2192
{
2193
unsigned i;
2194
const ProtobufCFieldDescriptor *fields =
2195
latter_msg->descriptor->fields;
2196
for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
2197
if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
2198
size_t *n_earlier =
2199
STRUCT_MEMBER_PTR(size_t, earlier_msg,
2200
fields[i].quantifier_offset);
2201
uint8_t **p_earlier =
2202
STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
2203
fields[i].offset);
2204
size_t *n_latter =
2205
STRUCT_MEMBER_PTR(size_t, latter_msg,
2206
fields[i].quantifier_offset);
2207
uint8_t **p_latter =
2208
STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
2209
fields[i].offset);
2210
2211
if (*n_earlier > 0) {
2212
if (*n_latter > 0) {
2213
/* Concatenate the repeated field */
2214
size_t el_size =
2215
sizeof_elt_in_repeated_array(fields[i].type);
2216
uint8_t *new_field;
2217
2218
new_field = do_alloc(allocator,
2219
(*n_earlier + *n_latter) * el_size);
2220
if (!new_field)
2221
return FALSE;
2222
2223
memcpy(new_field, *p_earlier,
2224
*n_earlier * el_size);
2225
memcpy(new_field +
2226
*n_earlier * el_size,
2227
*p_latter,
2228
*n_latter * el_size);
2229
2230
do_free(allocator, *p_latter);
2231
do_free(allocator, *p_earlier);
2232
*p_latter = new_field;
2233
*n_latter = *n_earlier + *n_latter;
2234
} else {
2235
/* Zero copy the repeated field from the earlier message */
2236
*n_latter = *n_earlier;
2237
*p_latter = *p_earlier;
2238
}
2239
/* Make sure the field does not get double freed */
2240
*n_earlier = 0;
2241
*p_earlier = 0;
2242
}
2243
} else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL ||
2244
fields[i].label == PROTOBUF_C_LABEL_NONE) {
2245
const ProtobufCFieldDescriptor *field;
2246
uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t,
2247
earlier_msg,
2248
fields[i].
2249
quantifier_offset);
2250
uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t,
2251
latter_msg,
2252
fields[i].
2253
quantifier_offset);
2254
protobuf_c_boolean need_to_merge = FALSE;
2255
void *earlier_elem;
2256
void *latter_elem;
2257
const void *def_val;
2258
2259
if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
2260
if (*latter_case_p == 0) {
2261
/* lookup correct oneof field */
2262
int field_index =
2263
int_range_lookup(
2264
latter_msg->descriptor
2265
->n_field_ranges,
2266
latter_msg->descriptor
2267
->field_ranges,
2268
*earlier_case_p);
2269
if (field_index < 0)
2270
return FALSE;
2271
field = latter_msg->descriptor->fields +
2272
field_index;
2273
} else {
2274
/* Oneof is present in the latter message, move on */
2275
continue;
2276
}
2277
} else {
2278
field = &fields[i];
2279
}
2280
2281
earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset);
2282
latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset);
2283
def_val = field->default_value;
2284
2285
switch (field->type) {
2286
case PROTOBUF_C_TYPE_MESSAGE: {
2287
ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem;
2288
ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem;
2289
if (em != NULL) {
2290
if (lm != NULL) {
2291
if (!merge_messages(em, lm, allocator))
2292
return FALSE;
2293
/* Already merged */
2294
need_to_merge = FALSE;
2295
} else {
2296
/* Zero copy the message */
2297
need_to_merge = TRUE;
2298
}
2299
}
2300
break;
2301
}
2302
case PROTOBUF_C_TYPE_BYTES: {
2303
uint8_t *e_data =
2304
((ProtobufCBinaryData *) earlier_elem)->data;
2305
uint8_t *l_data =
2306
((ProtobufCBinaryData *) latter_elem)->data;
2307
const ProtobufCBinaryData *d_bd =
2308
(ProtobufCBinaryData *) def_val;
2309
2310
need_to_merge =
2311
(e_data != NULL &&
2312
(d_bd == NULL ||
2313
e_data != d_bd->data)) &&
2314
(l_data == NULL ||
2315
(d_bd != NULL &&
2316
l_data == d_bd->data));
2317
break;
2318
}
2319
case PROTOBUF_C_TYPE_STRING: {
2320
char *e_str = *(char **) earlier_elem;
2321
char *l_str = *(char **) latter_elem;
2322
const char *d_str = def_val;
2323
2324
need_to_merge = e_str != d_str && l_str == d_str;
2325
break;
2326
}
2327
default: {
2328
/* Could be has field or case enum, the logic is
2329
* equivalent, since 0 (FALSE) means not set for
2330
* oneof */
2331
need_to_merge = (*earlier_case_p != 0) &&
2332
(*latter_case_p == 0);
2333
break;
2334
}
2335
}
2336
2337
if (need_to_merge) {
2338
size_t el_size =
2339
sizeof_elt_in_repeated_array(field->type);
2340
memcpy(latter_elem, earlier_elem, el_size);
2341
/*
2342
* Reset the element from the old message to 0
2343
* to make sure earlier message deallocation
2344
* doesn't corrupt zero-copied data in the new
2345
* message, earlier message will be freed after
2346
* this function is called anyway
2347
*/
2348
memset(earlier_elem, 0, el_size);
2349
2350
if (field->quantifier_offset != 0) {
2351
/* Set the has field or the case enum,
2352
* if applicable */
2353
*latter_case_p = *earlier_case_p;
2354
*earlier_case_p = 0;
2355
}
2356
}
2357
}
2358
}
2359
return TRUE;
2360
}
2361
2362
/**
2363
* Count packed elements.
2364
*
2365
* Given a raw slab of packed-repeated values, determine the number of
2366
* elements. This function detects certain kinds of errors but not
2367
* others; the remaining error checking is done by
2368
* parse_packed_repeated_member().
2369
*/
2370
static protobuf_c_boolean
2371
count_packed_elements(ProtobufCType type,
2372
size_t len, const uint8_t *data, size_t *count_out)
2373
{
2374
switch (type) {
2375
case PROTOBUF_C_TYPE_SFIXED32:
2376
case PROTOBUF_C_TYPE_FIXED32:
2377
case PROTOBUF_C_TYPE_FLOAT:
2378
if (len % 4 != 0) {
2379
PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
2380
return FALSE;
2381
}
2382
*count_out = len / 4;
2383
return TRUE;
2384
case PROTOBUF_C_TYPE_SFIXED64:
2385
case PROTOBUF_C_TYPE_FIXED64:
2386
case PROTOBUF_C_TYPE_DOUBLE:
2387
if (len % 8 != 0) {
2388
PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
2389
return FALSE;
2390
}
2391
*count_out = len / 8;
2392
return TRUE;
2393
case PROTOBUF_C_TYPE_ENUM:
2394
case PROTOBUF_C_TYPE_INT32:
2395
case PROTOBUF_C_TYPE_SINT32:
2396
case PROTOBUF_C_TYPE_UINT32:
2397
case PROTOBUF_C_TYPE_INT64:
2398
case PROTOBUF_C_TYPE_SINT64:
2399
case PROTOBUF_C_TYPE_UINT64:
2400
*count_out = max_b128_numbers(len, data);
2401
return TRUE;
2402
case PROTOBUF_C_TYPE_BOOL:
2403
*count_out = len;
2404
return TRUE;
2405
case PROTOBUF_C_TYPE_STRING:
2406
case PROTOBUF_C_TYPE_BYTES:
2407
case PROTOBUF_C_TYPE_MESSAGE:
2408
default:
2409
PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
2410
return FALSE;
2411
}
2412
}
2413
2414
static inline uint32_t
2415
parse_uint32(unsigned len, const uint8_t *data)
2416
{
2417
uint32_t rv = data[0] & 0x7f;
2418
if (len > 1) {
2419
rv |= ((uint32_t) (data[1] & 0x7f) << 7);
2420
if (len > 2) {
2421
rv |= ((uint32_t) (data[2] & 0x7f) << 14);
2422
if (len > 3) {
2423
rv |= ((uint32_t) (data[3] & 0x7f) << 21);
2424
if (len > 4)
2425
rv |= ((uint32_t) (data[4]) << 28);
2426
}
2427
}
2428
}
2429
return rv;
2430
}
2431
2432
static inline uint32_t
2433
parse_int32(unsigned len, const uint8_t *data)
2434
{
2435
return parse_uint32(len, data);
2436
}
2437
2438
static inline int32_t
2439
unzigzag32(uint32_t v)
2440
{
2441
// Note: Using unsigned types prevents undefined behavior
2442
return (int32_t)((v >> 1) ^ -(v & 1));
2443
}
2444
2445
static inline uint32_t
2446
parse_fixed_uint32(const uint8_t *data)
2447
{
2448
#if !defined(WORDS_BIGENDIAN)
2449
uint32_t t;
2450
memcpy(&t, data, 4);
2451
return t;
2452
#else
2453
return data[0] |
2454
((uint32_t) (data[1]) << 8) |
2455
((uint32_t) (data[2]) << 16) |
2456
((uint32_t) (data[3]) << 24);
2457
#endif
2458
}
2459
2460
static uint64_t
2461
parse_uint64(unsigned len, const uint8_t *data)
2462
{
2463
unsigned shift, i;
2464
uint64_t rv;
2465
2466
if (len < 5)
2467
return parse_uint32(len, data);
2468
rv = ((uint64_t) (data[0] & 0x7f)) |
2469
((uint64_t) (data[1] & 0x7f) << 7) |
2470
((uint64_t) (data[2] & 0x7f) << 14) |
2471
((uint64_t) (data[3] & 0x7f) << 21);
2472
shift = 28;
2473
for (i = 4; i < len; i++) {
2474
rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
2475
shift += 7;
2476
}
2477
return rv;
2478
}
2479
2480
static inline int64_t
2481
unzigzag64(uint64_t v)
2482
{
2483
// Note: Using unsigned types prevents undefined behavior
2484
return (int64_t)((v >> 1) ^ -(v & 1));
2485
}
2486
2487
static inline uint64_t
2488
parse_fixed_uint64(const uint8_t *data)
2489
{
2490
#if !defined(WORDS_BIGENDIAN)
2491
uint64_t t;
2492
memcpy(&t, data, 8);
2493
return t;
2494
#else
2495
return (uint64_t) parse_fixed_uint32(data) |
2496
(((uint64_t) parse_fixed_uint32(data + 4)) << 32);
2497
#endif
2498
}
2499
2500
static protobuf_c_boolean
2501
parse_boolean(unsigned len, const uint8_t *data)
2502
{
2503
unsigned i;
2504
for (i = 0; i < len; i++)
2505
if (data[i] & 0x7f)
2506
return TRUE;
2507
return FALSE;
2508
}
2509
2510
static protobuf_c_boolean
2511
parse_required_member(ScannedMember *scanned_member,
2512
void *member,
2513
ProtobufCAllocator *allocator,
2514
protobuf_c_boolean maybe_clear)
2515
{
2516
unsigned len = scanned_member->len;
2517
const uint8_t *data = scanned_member->data;
2518
uint8_t wire_type = scanned_member->wire_type;
2519
2520
switch (scanned_member->field->type) {
2521
case PROTOBUF_C_TYPE_ENUM:
2522
case PROTOBUF_C_TYPE_INT32:
2523
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2524
return FALSE;
2525
*(int32_t *) member = parse_int32(len, data);
2526
return TRUE;
2527
case PROTOBUF_C_TYPE_UINT32:
2528
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2529
return FALSE;
2530
*(uint32_t *) member = parse_uint32(len, data);
2531
return TRUE;
2532
case PROTOBUF_C_TYPE_SINT32:
2533
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2534
return FALSE;
2535
*(int32_t *) member = unzigzag32(parse_uint32(len, data));
2536
return TRUE;
2537
case PROTOBUF_C_TYPE_SFIXED32:
2538
case PROTOBUF_C_TYPE_FIXED32:
2539
case PROTOBUF_C_TYPE_FLOAT:
2540
if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
2541
return FALSE;
2542
*(uint32_t *) member = parse_fixed_uint32(data);
2543
return TRUE;
2544
case PROTOBUF_C_TYPE_INT64:
2545
case PROTOBUF_C_TYPE_UINT64:
2546
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2547
return FALSE;
2548
*(uint64_t *) member = parse_uint64(len, data);
2549
return TRUE;
2550
case PROTOBUF_C_TYPE_SINT64:
2551
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2552
return FALSE;
2553
*(int64_t *) member = unzigzag64(parse_uint64(len, data));
2554
return TRUE;
2555
case PROTOBUF_C_TYPE_SFIXED64:
2556
case PROTOBUF_C_TYPE_FIXED64:
2557
case PROTOBUF_C_TYPE_DOUBLE:
2558
if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
2559
return FALSE;
2560
*(uint64_t *) member = parse_fixed_uint64(data);
2561
return TRUE;
2562
case PROTOBUF_C_TYPE_BOOL:
2563
*(protobuf_c_boolean *) member = parse_boolean(len, data);
2564
return TRUE;
2565
case PROTOBUF_C_TYPE_STRING: {
2566
char **pstr = member;
2567
unsigned pref_len = scanned_member->length_prefix_len;
2568
2569
if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2570
return FALSE;
2571
2572
if (maybe_clear && *pstr != NULL) {
2573
const char *def = scanned_member->field->default_value;
2574
if (*pstr != def)
2575
do_free(allocator, *pstr);
2576
}
2577
*pstr = do_alloc(allocator, len - pref_len + 1);
2578
if (*pstr == NULL)
2579
return FALSE;
2580
memcpy(*pstr, data + pref_len, len - pref_len);
2581
(*pstr)[len - pref_len] = 0;
2582
return TRUE;
2583
}
2584
case PROTOBUF_C_TYPE_BYTES: {
2585
ProtobufCBinaryData *bd = member;
2586
const ProtobufCBinaryData *def_bd;
2587
unsigned pref_len = scanned_member->length_prefix_len;
2588
2589
if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2590
return FALSE;
2591
2592
def_bd = scanned_member->field->default_value;
2593
if (maybe_clear &&
2594
bd->data != NULL &&
2595
(def_bd == NULL || bd->data != def_bd->data))
2596
{
2597
do_free(allocator, bd->data);
2598
}
2599
if (len > pref_len) {
2600
bd->data = do_alloc(allocator, len - pref_len);
2601
if (bd->data == NULL)
2602
return FALSE;
2603
memcpy(bd->data, data + pref_len, len - pref_len);
2604
} else {
2605
bd->data = NULL;
2606
}
2607
bd->len = len - pref_len;
2608
return TRUE;
2609
}
2610
case PROTOBUF_C_TYPE_MESSAGE: {
2611
ProtobufCMessage **pmessage = member;
2612
ProtobufCMessage *subm;
2613
const ProtobufCMessage *def_mess;
2614
protobuf_c_boolean merge_successful = TRUE;
2615
unsigned pref_len = scanned_member->length_prefix_len;
2616
2617
if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2618
return FALSE;
2619
2620
def_mess = scanned_member->field->default_value;
2621
if (len >= pref_len)
2622
subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
2623
allocator,
2624
len - pref_len,
2625
data + pref_len);
2626
else
2627
subm = NULL;
2628
2629
if (maybe_clear &&
2630
*pmessage != NULL &&
2631
*pmessage != def_mess)
2632
{
2633
if (subm != NULL)
2634
merge_successful = merge_messages(*pmessage, subm, allocator);
2635
/* Delete the previous message */
2636
protobuf_c_message_free_unpacked(*pmessage, allocator);
2637
}
2638
*pmessage = subm;
2639
if (subm == NULL || !merge_successful)
2640
return FALSE;
2641
return TRUE;
2642
}
2643
}
2644
return FALSE;
2645
}
2646
2647
static protobuf_c_boolean
2648
parse_oneof_member (ScannedMember *scanned_member,
2649
void *member,
2650
ProtobufCMessage *message,
2651
ProtobufCAllocator *allocator)
2652
{
2653
uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message,
2654
scanned_member->field->quantifier_offset);
2655
2656
/* If we have already parsed a member of this oneof, free it. */
2657
if (*oneof_case != 0) {
2658
const ProtobufCFieldDescriptor *old_field;
2659
size_t el_size;
2660
/* lookup field */
2661
int field_index =
2662
int_range_lookup(message->descriptor->n_field_ranges,
2663
message->descriptor->field_ranges,
2664
*oneof_case);
2665
if (field_index < 0)
2666
return FALSE;
2667
old_field = message->descriptor->fields + field_index;
2668
el_size = sizeof_elt_in_repeated_array(old_field->type);
2669
2670
switch (old_field->type) {
2671
case PROTOBUF_C_TYPE_STRING: {
2672
char **pstr = member;
2673
const char *def = old_field->default_value;
2674
if (*pstr != NULL && *pstr != def)
2675
do_free(allocator, *pstr);
2676
break;
2677
}
2678
case PROTOBUF_C_TYPE_BYTES: {
2679
ProtobufCBinaryData *bd = member;
2680
const ProtobufCBinaryData *def_bd = old_field->default_value;
2681
if (bd->data != NULL &&
2682
(def_bd == NULL || bd->data != def_bd->data))
2683
{
2684
do_free(allocator, bd->data);
2685
}
2686
break;
2687
}
2688
case PROTOBUF_C_TYPE_MESSAGE: {
2689
ProtobufCMessage **pmessage = member;
2690
const ProtobufCMessage *def_mess = old_field->default_value;
2691
if (*pmessage != NULL && *pmessage != def_mess)
2692
protobuf_c_message_free_unpacked(*pmessage, allocator);
2693
break;
2694
}
2695
default:
2696
break;
2697
}
2698
2699
memset (member, 0, el_size);
2700
}
2701
if (!parse_required_member (scanned_member, member, allocator, TRUE))
2702
return FALSE;
2703
2704
*oneof_case = scanned_member->tag;
2705
return TRUE;
2706
}
2707
2708
2709
static protobuf_c_boolean
2710
parse_optional_member(ScannedMember *scanned_member,
2711
void *member,
2712
ProtobufCMessage *message,
2713
ProtobufCAllocator *allocator)
2714
{
2715
if (!parse_required_member(scanned_member, member, allocator, TRUE))
2716
return FALSE;
2717
if (scanned_member->field->quantifier_offset != 0)
2718
STRUCT_MEMBER(protobuf_c_boolean,
2719
message,
2720
scanned_member->field->quantifier_offset) = TRUE;
2721
return TRUE;
2722
}
2723
2724
static protobuf_c_boolean
2725
parse_repeated_member(ScannedMember *scanned_member,
2726
void *member,
2727
ProtobufCMessage *message,
2728
ProtobufCAllocator *allocator)
2729
{
2730
const ProtobufCFieldDescriptor *field = scanned_member->field;
2731
size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2732
size_t siz = sizeof_elt_in_repeated_array(field->type);
2733
char *array = *(char **) member;
2734
2735
if (!parse_required_member(scanned_member, array + siz * (*p_n),
2736
allocator, FALSE))
2737
{
2738
return FALSE;
2739
}
2740
*p_n += 1;
2741
return TRUE;
2742
}
2743
2744
static unsigned
2745
scan_varint(unsigned len, const uint8_t *data)
2746
{
2747
unsigned i;
2748
if (len > 10)
2749
len = 10;
2750
for (i = 0; i < len; i++)
2751
if ((data[i] & 0x80) == 0)
2752
break;
2753
if (i == len)
2754
return 0;
2755
return i + 1;
2756
}
2757
2758
static protobuf_c_boolean
2759
parse_packed_repeated_member(ScannedMember *scanned_member,
2760
void *member,
2761
ProtobufCMessage *message)
2762
{
2763
const ProtobufCFieldDescriptor *field = scanned_member->field;
2764
size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2765
size_t siz = sizeof_elt_in_repeated_array(field->type);
2766
void *array = *(char **) member + siz * (*p_n);
2767
const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
2768
size_t rem = scanned_member->len - scanned_member->length_prefix_len;
2769
size_t count = 0;
2770
#if defined(WORDS_BIGENDIAN)
2771
unsigned i;
2772
#endif
2773
2774
switch (field->type) {
2775
case PROTOBUF_C_TYPE_SFIXED32:
2776
case PROTOBUF_C_TYPE_FIXED32:
2777
case PROTOBUF_C_TYPE_FLOAT:
2778
count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
2779
#if !defined(WORDS_BIGENDIAN)
2780
goto no_unpacking_needed;
2781
#else
2782
for (i = 0; i < count; i++) {
2783
((uint32_t *) array)[i] = parse_fixed_uint32(at);
2784
at += 4;
2785
}
2786
break;
2787
#endif
2788
case PROTOBUF_C_TYPE_SFIXED64:
2789
case PROTOBUF_C_TYPE_FIXED64:
2790
case PROTOBUF_C_TYPE_DOUBLE:
2791
count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
2792
#if !defined(WORDS_BIGENDIAN)
2793
goto no_unpacking_needed;
2794
#else
2795
for (i = 0; i < count; i++) {
2796
((uint64_t *) array)[i] = parse_fixed_uint64(at);
2797
at += 8;
2798
}
2799
break;
2800
#endif
2801
case PROTOBUF_C_TYPE_ENUM:
2802
case PROTOBUF_C_TYPE_INT32:
2803
while (rem > 0) {
2804
unsigned s = scan_varint(rem, at);
2805
if (s == 0) {
2806
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
2807
return FALSE;
2808
}
2809
((int32_t *) array)[count++] = parse_int32(s, at);
2810
at += s;
2811
rem -= s;
2812
}
2813
break;
2814
case PROTOBUF_C_TYPE_SINT32:
2815
while (rem > 0) {
2816
unsigned s = scan_varint(rem, at);
2817
if (s == 0) {
2818
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
2819
return FALSE;
2820
}
2821
((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
2822
at += s;
2823
rem -= s;
2824
}
2825
break;
2826
case PROTOBUF_C_TYPE_UINT32:
2827
while (rem > 0) {
2828
unsigned s = scan_varint(rem, at);
2829
if (s == 0) {
2830
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
2831
return FALSE;
2832
}
2833
((uint32_t *) array)[count++] = parse_uint32(s, at);
2834
at += s;
2835
rem -= s;
2836
}
2837
break;
2838
2839
case PROTOBUF_C_TYPE_SINT64:
2840
while (rem > 0) {
2841
unsigned s = scan_varint(rem, at);
2842
if (s == 0) {
2843
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
2844
return FALSE;
2845
}
2846
((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
2847
at += s;
2848
rem -= s;
2849
}
2850
break;
2851
case PROTOBUF_C_TYPE_INT64:
2852
case PROTOBUF_C_TYPE_UINT64:
2853
while (rem > 0) {
2854
unsigned s = scan_varint(rem, at);
2855
if (s == 0) {
2856
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
2857
return FALSE;
2858
}
2859
((int64_t *) array)[count++] = parse_uint64(s, at);
2860
at += s;
2861
rem -= s;
2862
}
2863
break;
2864
case PROTOBUF_C_TYPE_BOOL:
2865
while (rem > 0) {
2866
unsigned s = scan_varint(rem, at);
2867
if (s == 0) {
2868
PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
2869
return FALSE;
2870
}
2871
((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at);
2872
at += s;
2873
rem -= s;
2874
}
2875
break;
2876
default:
2877
PROTOBUF_C__ASSERT_NOT_REACHED();
2878
}
2879
*p_n += count;
2880
return TRUE;
2881
2882
#if !defined(WORDS_BIGENDIAN)
2883
no_unpacking_needed:
2884
memcpy(array, at, count * siz);
2885
*p_n += count;
2886
return TRUE;
2887
#endif
2888
}
2889
2890
static protobuf_c_boolean
2891
is_packable_type(ProtobufCType type)
2892
{
2893
return
2894
type != PROTOBUF_C_TYPE_STRING &&
2895
type != PROTOBUF_C_TYPE_BYTES &&
2896
type != PROTOBUF_C_TYPE_MESSAGE;
2897
}
2898
2899
static protobuf_c_boolean
2900
parse_member(ScannedMember *scanned_member,
2901
ProtobufCMessage *message,
2902
ProtobufCAllocator *allocator)
2903
{
2904
const ProtobufCFieldDescriptor *field = scanned_member->field;
2905
void *member;
2906
2907
if (field == NULL) {
2908
ProtobufCMessageUnknownField *ufield =
2909
message->unknown_fields +
2910
(message->n_unknown_fields++);
2911
ufield->tag = scanned_member->tag;
2912
ufield->wire_type = scanned_member->wire_type;
2913
ufield->len = scanned_member->len;
2914
ufield->data = do_alloc(allocator, scanned_member->len);
2915
if (ufield->data == NULL)
2916
return FALSE;
2917
memcpy(ufield->data, scanned_member->data, ufield->len);
2918
return TRUE;
2919
}
2920
member = (char *) message + field->offset;
2921
switch (field->label) {
2922
case PROTOBUF_C_LABEL_REQUIRED:
2923
return parse_required_member(scanned_member, member,
2924
allocator, TRUE);
2925
case PROTOBUF_C_LABEL_OPTIONAL:
2926
case PROTOBUF_C_LABEL_NONE:
2927
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
2928
return parse_oneof_member(scanned_member, member,
2929
message, allocator);
2930
} else {
2931
return parse_optional_member(scanned_member, member,
2932
message, allocator);
2933
}
2934
case PROTOBUF_C_LABEL_REPEATED:
2935
if (scanned_member->wire_type ==
2936
PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
2937
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
2938
is_packable_type(field->type)))
2939
{
2940
return parse_packed_repeated_member(scanned_member,
2941
member, message);
2942
} else {
2943
return parse_repeated_member(scanned_member,
2944
member, message,
2945
allocator);
2946
}
2947
}
2948
PROTOBUF_C__ASSERT_NOT_REACHED();
2949
return 0;
2950
}
2951
2952
/**
2953
* Initialise messages generated by old code.
2954
*
2955
* This function is used if desc->message_init == NULL (which occurs
2956
* for old code, and which would be useful to support allocating
2957
* descriptors dynamically).
2958
*/
2959
static void
2960
message_init_generic(const ProtobufCMessageDescriptor *desc,
2961
ProtobufCMessage *message)
2962
{
2963
unsigned i;
2964
2965
memset(message, 0, desc->sizeof_message);
2966
message->descriptor = desc;
2967
for (i = 0; i < desc->n_fields; i++) {
2968
if (desc->fields[i].default_value != NULL &&
2969
desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
2970
{
2971
void *field =
2972
STRUCT_MEMBER_P(message, desc->fields[i].offset);
2973
const void *dv = desc->fields[i].default_value;
2974
2975
switch (desc->fields[i].type) {
2976
case PROTOBUF_C_TYPE_INT32:
2977
case PROTOBUF_C_TYPE_SINT32:
2978
case PROTOBUF_C_TYPE_SFIXED32:
2979
case PROTOBUF_C_TYPE_UINT32:
2980
case PROTOBUF_C_TYPE_FIXED32:
2981
case PROTOBUF_C_TYPE_FLOAT:
2982
case PROTOBUF_C_TYPE_ENUM:
2983
memcpy(field, dv, 4);
2984
break;
2985
case PROTOBUF_C_TYPE_INT64:
2986
case PROTOBUF_C_TYPE_SINT64:
2987
case PROTOBUF_C_TYPE_SFIXED64:
2988
case PROTOBUF_C_TYPE_UINT64:
2989
case PROTOBUF_C_TYPE_FIXED64:
2990
case PROTOBUF_C_TYPE_DOUBLE:
2991
memcpy(field, dv, 8);
2992
break;
2993
case PROTOBUF_C_TYPE_BOOL:
2994
memcpy(field, dv, sizeof(protobuf_c_boolean));
2995
break;
2996
case PROTOBUF_C_TYPE_BYTES:
2997
memcpy(field, dv, sizeof(ProtobufCBinaryData));
2998
break;
2999
3000
case PROTOBUF_C_TYPE_STRING:
3001
case PROTOBUF_C_TYPE_MESSAGE:
3002
/*
3003
* The next line essentially implements a cast
3004
* from const, which is totally unavoidable.
3005
*/
3006
*(const void **) field = dv;
3007
break;
3008
}
3009
}
3010
}
3011
}
3012
3013
/**@}*/
3014
3015
/*
3016
* ScannedMember slabs (an unpacking implementation detail). Before doing real
3017
* unpacking, we first scan through the elements to see how many there are (for
3018
* repeated fields), and which field to use (for non-repeated fields given
3019
* twice).
3020
*
3021
* In order to avoid allocations for small messages, we keep a stack-allocated
3022
* slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
3023
* fill that up, we allocate each slab twice as large as the previous one.
3024
*/
3025
#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
3026
3027
/*
3028
* The number of slabs, including the stack-allocated ones; choose the number so
3029
* that we would overflow if we needed a slab larger than provided.
3030
*/
3031
#define MAX_SCANNED_MEMBER_SLAB \
3032
(sizeof(unsigned int)*8 - 1 \
3033
- BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
3034
- FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
3035
3036
#define REQUIRED_FIELD_BITMAP_SET(index) \
3037
(required_fields_bitmap[(index)/8] |= (1UL<<((index)%8)))
3038
3039
#define REQUIRED_FIELD_BITMAP_IS_SET(index) \
3040
(required_fields_bitmap[(index)/8] & (1UL<<((index)%8)))
3041
3042
ProtobufCMessage *
3043
protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
3044
ProtobufCAllocator *allocator,
3045
size_t len, const uint8_t *data)
3046
{
3047
ProtobufCMessage *rv;
3048
size_t rem = len;
3049
const uint8_t *at = data;
3050
const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
3051
ScannedMember first_member_slab[1UL <<
3052
FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
3053
3054
/*
3055
* scanned_member_slabs[i] is an array of arrays of ScannedMember.
3056
* The first slab (scanned_member_slabs[0] is just a pointer to
3057
* first_member_slab), above. All subsequent slabs will be allocated
3058
* using the allocator.
3059
*/
3060
ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
3061
unsigned which_slab = 0; /* the slab we are currently populating */
3062
unsigned in_slab_index = 0; /* number of members in the slab */
3063
size_t n_unknown = 0;
3064
unsigned f;
3065
unsigned j;
3066
unsigned i_slab;
3067
unsigned last_field_index = 0;
3068
unsigned required_fields_bitmap_len;
3069
unsigned char required_fields_bitmap_stack[16];
3070
unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
3071
protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
3072
3073
ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
3074
3075
if (allocator == NULL)
3076
allocator = &protobuf_c__allocator;
3077
3078
rv = do_alloc(allocator, desc->sizeof_message);
3079
if (!rv)
3080
return (NULL);
3081
scanned_member_slabs[0] = first_member_slab;
3082
3083
required_fields_bitmap_len = (desc->n_fields + 7) / 8;
3084
if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
3085
required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
3086
if (!required_fields_bitmap) {
3087
do_free(allocator, rv);
3088
return (NULL);
3089
}
3090
required_fields_bitmap_alloced = TRUE;
3091
}
3092
memset(required_fields_bitmap, 0, required_fields_bitmap_len);
3093
3094
/*
3095
* Generated code always defines "message_init". However, we provide a
3096
* fallback for (1) users of old protobuf-c generated-code that do not
3097
* provide the function, and (2) descriptors constructed from some other
3098
* source (most likely, direct construction from the .proto file).
3099
*/
3100
if (desc->message_init != NULL)
3101
protobuf_c_message_init(desc, rv);
3102
else
3103
message_init_generic(desc, rv);
3104
3105
while (rem > 0) {
3106
uint32_t tag;
3107
uint8_t wire_type;
3108
size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
3109
const ProtobufCFieldDescriptor *field;
3110
ScannedMember tmp;
3111
3112
if (used == 0) {
3113
PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
3114
(unsigned) (at - data));
3115
goto error_cleanup_during_scan;
3116
}
3117
/*
3118
* \todo Consider optimizing for field[1].id == tag, if field[1]
3119
* exists!
3120
*/
3121
if (last_field == NULL || last_field->id != tag) {
3122
/* lookup field */
3123
int field_index =
3124
int_range_lookup(desc->n_field_ranges,
3125
desc->field_ranges,
3126
tag);
3127
if (field_index < 0) {
3128
field = NULL;
3129
n_unknown++;
3130
} else {
3131
field = desc->fields + field_index;
3132
last_field = field;
3133
last_field_index = field_index;
3134
}
3135
} else {
3136
field = last_field;
3137
}
3138
3139
if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
3140
REQUIRED_FIELD_BITMAP_SET(last_field_index);
3141
3142
at += used;
3143
rem -= used;
3144
tmp.tag = tag;
3145
tmp.wire_type = wire_type;
3146
tmp.field = field;
3147
tmp.data = at;
3148
tmp.length_prefix_len = 0;
3149
3150
switch (wire_type) {
3151
case PROTOBUF_C_WIRE_TYPE_VARINT: {
3152
unsigned max_len = rem < 10 ? rem : 10;
3153
unsigned i;
3154
3155
for (i = 0; i < max_len; i++)
3156
if ((at[i] & 0x80) == 0)
3157
break;
3158
if (i == max_len) {
3159
PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
3160
(unsigned) (at - data));
3161
goto error_cleanup_during_scan;
3162
}
3163
tmp.len = i + 1;
3164
break;
3165
}
3166
case PROTOBUF_C_WIRE_TYPE_64BIT:
3167
if (rem < 8) {
3168
PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
3169
(unsigned) (at - data));
3170
goto error_cleanup_during_scan;
3171
}
3172
tmp.len = 8;
3173
break;
3174
case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
3175
size_t pref_len;
3176
3177
tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
3178
if (tmp.len == 0) {
3179
/* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
3180
goto error_cleanup_during_scan;
3181
}
3182
tmp.length_prefix_len = pref_len;
3183
break;
3184
}
3185
case PROTOBUF_C_WIRE_TYPE_32BIT:
3186
if (rem < 4) {
3187
PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
3188
(unsigned) (at - data));
3189
goto error_cleanup_during_scan;
3190
}
3191
tmp.len = 4;
3192
break;
3193
default:
3194
PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
3195
wire_type, (unsigned) (at - data));
3196
goto error_cleanup_during_scan;
3197
}
3198
3199
if (in_slab_index == (1UL <<
3200
(which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
3201
{
3202
size_t size;
3203
3204
in_slab_index = 0;
3205
if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
3206
PROTOBUF_C_UNPACK_ERROR("too many fields");
3207
goto error_cleanup_during_scan;
3208
}
3209
which_slab++;
3210
size = sizeof(ScannedMember)
3211
<< (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
3212
scanned_member_slabs[which_slab] = do_alloc(allocator, size);
3213
if (scanned_member_slabs[which_slab] == NULL)
3214
goto error_cleanup_during_scan;
3215
}
3216
scanned_member_slabs[which_slab][in_slab_index++] = tmp;
3217
3218
if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
3219
size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
3220
field->quantifier_offset);
3221
if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
3222
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
3223
is_packable_type(field->type)))
3224
{
3225
size_t count;
3226
if (!count_packed_elements(field->type,
3227
tmp.len -
3228
tmp.length_prefix_len,
3229
tmp.data +
3230
tmp.length_prefix_len,
3231
&count))
3232
{
3233
PROTOBUF_C_UNPACK_ERROR("counting packed elements");
3234
goto error_cleanup_during_scan;
3235
}
3236
*n += count;
3237
} else {
3238
*n += 1;
3239
}
3240
}
3241
3242
at += tmp.len;
3243
rem -= tmp.len;
3244
}
3245
3246
/* allocate space for repeated fields, also check that all required fields have been set */
3247
for (f = 0; f < desc->n_fields; f++) {
3248
const ProtobufCFieldDescriptor *field = desc->fields + f;
3249
if (field == NULL) {
3250
continue;
3251
}
3252
if (field->label == PROTOBUF_C_LABEL_REPEATED) {
3253
size_t siz =
3254
sizeof_elt_in_repeated_array(field->type);
3255
size_t *n_ptr =
3256
STRUCT_MEMBER_PTR(size_t, rv,
3257
field->quantifier_offset);
3258
if (*n_ptr != 0) {
3259
unsigned n = *n_ptr;
3260
void *a;
3261
*n_ptr = 0;
3262
assert(rv->descriptor != NULL);
3263
#define CLEAR_REMAINING_N_PTRS() \
3264
for(f++;f < desc->n_fields; f++) \
3265
{ \
3266
field = desc->fields + f; \
3267
if (field->label == PROTOBUF_C_LABEL_REPEATED) \
3268
STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
3269
}
3270
a = do_alloc(allocator, siz * n);
3271
if (!a) {
3272
CLEAR_REMAINING_N_PTRS();
3273
goto error_cleanup;
3274
}
3275
STRUCT_MEMBER(void *, rv, field->offset) = a;
3276
}
3277
} else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
3278
if (field->default_value == NULL &&
3279
!REQUIRED_FIELD_BITMAP_IS_SET(f))
3280
{
3281
CLEAR_REMAINING_N_PTRS();
3282
PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
3283
desc->name, field->name);
3284
goto error_cleanup;
3285
}
3286
}
3287
}
3288
#undef CLEAR_REMAINING_N_PTRS
3289
3290
/* allocate space for unknown fields */
3291
if (n_unknown) {
3292
rv->unknown_fields = do_alloc(allocator,
3293
n_unknown * sizeof(ProtobufCMessageUnknownField));
3294
if (rv->unknown_fields == NULL)
3295
goto error_cleanup;
3296
} else {
3297
rv->unknown_fields = NULL;
3298
}
3299
3300
/* do real parsing */
3301
for (i_slab = 0; i_slab <= which_slab; i_slab++) {
3302
unsigned max = (i_slab == which_slab) ?
3303
in_slab_index : (1UL << (i_slab + 4));
3304
ScannedMember *slab = scanned_member_slabs[i_slab];
3305
3306
for (j = 0; j < max; j++) {
3307
if (!parse_member(slab + j, rv, allocator)) {
3308
PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
3309
slab->field ? slab->field->name : "*unknown-field*",
3310
desc->name);
3311
goto error_cleanup;
3312
}
3313
}
3314
}
3315
3316
/* cleanup */
3317
for (j = 1; j <= which_slab; j++)
3318
do_free(allocator, scanned_member_slabs[j]);
3319
if (required_fields_bitmap_alloced)
3320
do_free(allocator, required_fields_bitmap);
3321
return rv;
3322
3323
error_cleanup:
3324
protobuf_c_message_free_unpacked(rv, allocator);
3325
for (j = 1; j <= which_slab; j++)
3326
do_free(allocator, scanned_member_slabs[j]);
3327
if (required_fields_bitmap_alloced)
3328
do_free(allocator, required_fields_bitmap);
3329
return NULL;
3330
3331
error_cleanup_during_scan:
3332
do_free(allocator, rv);
3333
for (j = 1; j <= which_slab; j++)
3334
do_free(allocator, scanned_member_slabs[j]);
3335
if (required_fields_bitmap_alloced)
3336
do_free(allocator, required_fields_bitmap);
3337
return NULL;
3338
}
3339
3340
void
3341
protobuf_c_message_free_unpacked(ProtobufCMessage *message,
3342
ProtobufCAllocator *allocator)
3343
{
3344
const ProtobufCMessageDescriptor *desc;
3345
unsigned f;
3346
3347
if (message == NULL)
3348
return;
3349
3350
desc = message->descriptor;
3351
3352
ASSERT_IS_MESSAGE(message);
3353
3354
if (allocator == NULL)
3355
allocator = &protobuf_c__allocator;
3356
message->descriptor = NULL;
3357
for (f = 0; f < desc->n_fields; f++) {
3358
if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) &&
3359
desc->fields[f].id !=
3360
STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset))
3361
{
3362
/* This is not the selected oneof, skip it */
3363
continue;
3364
}
3365
3366
if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
3367
size_t n = STRUCT_MEMBER(size_t,
3368
message,
3369
desc->fields[f].quantifier_offset);
3370
void *arr = STRUCT_MEMBER(void *,
3371
message,
3372
desc->fields[f].offset);
3373
3374
if (arr != NULL) {
3375
if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3376
unsigned i;
3377
for (i = 0; i < n; i++)
3378
do_free(allocator, ((char **) arr)[i]);
3379
} else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3380
unsigned i;
3381
for (i = 0; i < n; i++)
3382
do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
3383
} else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3384
unsigned i;
3385
for (i = 0; i < n; i++)
3386
protobuf_c_message_free_unpacked(
3387
((ProtobufCMessage **) arr)[i],
3388
allocator
3389
);
3390
}
3391
do_free(allocator, arr);
3392
}
3393
} else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3394
char *str = STRUCT_MEMBER(char *, message,
3395
desc->fields[f].offset);
3396
3397
if (str && str != desc->fields[f].default_value)
3398
do_free(allocator, str);
3399
} else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3400
void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
3401
desc->fields[f].offset).data;
3402
const ProtobufCBinaryData *default_bd;
3403
3404
default_bd = desc->fields[f].default_value;
3405
if (data != NULL &&
3406
(default_bd == NULL ||
3407
default_bd->data != data))
3408
{
3409
do_free(allocator, data);
3410
}
3411
} else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3412
ProtobufCMessage *sm;
3413
3414
sm = STRUCT_MEMBER(ProtobufCMessage *, message,
3415
desc->fields[f].offset);
3416
if (sm && sm != desc->fields[f].default_value)
3417
protobuf_c_message_free_unpacked(sm, allocator);
3418
}
3419
}
3420
3421
for (f = 0; f < message->n_unknown_fields; f++)
3422
do_free(allocator, message->unknown_fields[f].data);
3423
if (message->unknown_fields != NULL)
3424
do_free(allocator, message->unknown_fields);
3425
3426
do_free(allocator, message);
3427
}
3428
3429
void
3430
protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
3431
void *message)
3432
{
3433
descriptor->message_init((ProtobufCMessage *) (message));
3434
}
3435
3436
protobuf_c_boolean
3437
protobuf_c_message_check(const ProtobufCMessage *message)
3438
{
3439
unsigned i;
3440
3441
if (!message ||
3442
!message->descriptor ||
3443
message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
3444
{
3445
return FALSE;
3446
}
3447
3448
for (i = 0; i < message->descriptor->n_fields; i++) {
3449
const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
3450
ProtobufCType type = f->type;
3451
ProtobufCLabel label = f->label;
3452
void *field = STRUCT_MEMBER_P (message, f->offset);
3453
3454
if (f->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
3455
const uint32_t *oneof_case = STRUCT_MEMBER_P (message, f->quantifier_offset);
3456
if (f->id != *oneof_case) {
3457
continue; //Do not check if it is an unpopulated oneof member.
3458
}
3459
}
3460
3461
if (label == PROTOBUF_C_LABEL_REPEATED) {
3462
size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
3463
3464
if (*quantity > 0 && *(void **) field == NULL) {
3465
return FALSE;
3466
}
3467
3468
if (type == PROTOBUF_C_TYPE_MESSAGE) {
3469
ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
3470
unsigned j;
3471
for (j = 0; j < *quantity; j++) {
3472
if (!protobuf_c_message_check(submessage[j]))
3473
return FALSE;
3474
}
3475
} else if (type == PROTOBUF_C_TYPE_STRING) {
3476
char **string = *(char ***) field;
3477
unsigned j;
3478
for (j = 0; j < *quantity; j++) {
3479
if (!string[j])
3480
return FALSE;
3481
}
3482
} else if (type == PROTOBUF_C_TYPE_BYTES) {
3483
ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
3484
unsigned j;
3485
for (j = 0; j < *quantity; j++) {
3486
if (bd[j].len > 0 && bd[j].data == NULL)
3487
return FALSE;
3488
}
3489
}
3490
3491
} else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
3492
3493
if (type == PROTOBUF_C_TYPE_MESSAGE) {
3494
ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
3495
if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
3496
if (!protobuf_c_message_check(submessage))
3497
return FALSE;
3498
}
3499
} else if (type == PROTOBUF_C_TYPE_STRING) {
3500
char *string = *(char **) field;
3501
if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
3502
return FALSE;
3503
} else if (type == PROTOBUF_C_TYPE_BYTES) {
3504
protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
3505
ProtobufCBinaryData *bd = field;
3506
if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
3507
if (bd->len > 0 && bd->data == NULL)
3508
return FALSE;
3509
}
3510
}
3511
}
3512
}
3513
3514
return TRUE;
3515
}
3516
3517
/* === services === */
3518
3519
typedef void (*GenericHandler) (void *service,
3520
const ProtobufCMessage *input,
3521
ProtobufCClosure closure,
3522
void *closure_data);
3523
void
3524
protobuf_c_service_invoke_internal(ProtobufCService *service,
3525
unsigned method_index,
3526
const ProtobufCMessage *input,
3527
ProtobufCClosure closure,
3528
void *closure_data)
3529
{
3530
GenericHandler *handlers;
3531
GenericHandler handler;
3532
3533
/*
3534
* Verify that method_index is within range. If this fails, you are
3535
* likely invoking a newly added method on an old service. (Although
3536
* other memory corruption bugs can cause this assertion too.)
3537
*/
3538
assert(method_index < service->descriptor->n_methods);
3539
3540
/*
3541
* Get the array of virtual methods (which are enumerated by the
3542
* generated code).
3543
*/
3544
handlers = (GenericHandler *) (service + 1);
3545
3546
/*
3547
* Get our method and invoke it.
3548
* \todo Seems like handler == NULL is a situation that needs handling.
3549
*/
3550
handler = handlers[method_index];
3551
(*handler)(service, input, closure, closure_data);
3552
}
3553
3554
void
3555
protobuf_c_service_generated_init(ProtobufCService *service,
3556
const ProtobufCServiceDescriptor *descriptor,
3557
ProtobufCServiceDestroy destroy)
3558
{
3559
ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
3560
service->descriptor = descriptor;
3561
service->destroy = destroy;
3562
service->invoke = protobuf_c_service_invoke_internal;
3563
memset(&service[1], 0, descriptor->n_methods * sizeof(GenericHandler));
3564
}
3565
3566
void protobuf_c_service_destroy(ProtobufCService *service)
3567
{
3568
service->destroy(service);
3569
}
3570
3571
/* --- querying the descriptors --- */
3572
3573
const ProtobufCEnumValue *
3574
protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
3575
const char *name)
3576
{
3577
unsigned start = 0;
3578
unsigned count;
3579
3580
if (desc == NULL || desc->values_by_name == NULL)
3581
return NULL;
3582
3583
count = desc->n_value_names;
3584
3585
while (count > 1) {
3586
unsigned mid = start + count / 2;
3587
int rv = strcmp(desc->values_by_name[mid].name, name);
3588
if (rv == 0)
3589
return desc->values + desc->values_by_name[mid].index;
3590
else if (rv < 0) {
3591
count = start + count - (mid + 1);
3592
start = mid + 1;
3593
} else
3594
count = mid - start;
3595
}
3596
if (count == 0)
3597
return NULL;
3598
if (strcmp(desc->values_by_name[start].name, name) == 0)
3599
return desc->values + desc->values_by_name[start].index;
3600
return NULL;
3601
}
3602
3603
const ProtobufCEnumValue *
3604
protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
3605
int value)
3606
{
3607
int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
3608
if (rv < 0)
3609
return NULL;
3610
return desc->values + rv;
3611
}
3612
3613
const ProtobufCFieldDescriptor *
3614
protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
3615
const char *name)
3616
{
3617
unsigned start = 0;
3618
unsigned count;
3619
const ProtobufCFieldDescriptor *field;
3620
3621
if (desc == NULL || desc->fields_sorted_by_name == NULL)
3622
return NULL;
3623
3624
count = desc->n_fields;
3625
3626
while (count > 1) {
3627
unsigned mid = start + count / 2;
3628
int rv;
3629
field = desc->fields + desc->fields_sorted_by_name[mid];
3630
rv = strcmp(field->name, name);
3631
if (rv == 0)
3632
return field;
3633
else if (rv < 0) {
3634
count = start + count - (mid + 1);
3635
start = mid + 1;
3636
} else
3637
count = mid - start;
3638
}
3639
if (count == 0)
3640
return NULL;
3641
field = desc->fields + desc->fields_sorted_by_name[start];
3642
if (strcmp(field->name, name) == 0)
3643
return field;
3644
return NULL;
3645
}
3646
3647
const ProtobufCFieldDescriptor *
3648
protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
3649
unsigned value)
3650
{
3651
int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
3652
if (rv < 0)
3653
return NULL;
3654
return desc->fields + rv;
3655
}
3656
3657
const ProtobufCMethodDescriptor *
3658
protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
3659
const char *name)
3660
{
3661
unsigned start = 0;
3662
unsigned count;
3663
3664
if (desc == NULL || desc->method_indices_by_name == NULL)
3665
return NULL;
3666
3667
count = desc->n_methods;
3668
3669
while (count > 1) {
3670
unsigned mid = start + count / 2;
3671
unsigned mid_index = desc->method_indices_by_name[mid];
3672
const char *mid_name = desc->methods[mid_index].name;
3673
int rv = strcmp(mid_name, name);
3674
3675
if (rv == 0)
3676
return desc->methods + desc->method_indices_by_name[mid];
3677
if (rv < 0) {
3678
count = start + count - (mid + 1);
3679
start = mid + 1;
3680
} else {
3681
count = mid - start;
3682
}
3683
}
3684
if (count == 0)
3685
return NULL;
3686
if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
3687
return desc->methods + desc->method_indices_by_name[start];
3688
return NULL;
3689
}
3690
3691