xref: /aosp_15_r20/external/nanopb-c/pb_decode.c (revision c8d645cafcee3f91213d30caa0fe303887010b9b)
1*c8d645caSAndroid Build Coastguard Worker /* pb_decode.c -- decode a protobuf using minimal resources
2*c8d645caSAndroid Build Coastguard Worker  *
3*c8d645caSAndroid Build Coastguard Worker  * 2011 Petteri Aimonen <[email protected]>
4*c8d645caSAndroid Build Coastguard Worker  */
5*c8d645caSAndroid Build Coastguard Worker 
6*c8d645caSAndroid Build Coastguard Worker /* Use the GCC warn_unused_result attribute to check that all return values
7*c8d645caSAndroid Build Coastguard Worker  * are propagated correctly. On other compilers and gcc before 3.4.0 just
8*c8d645caSAndroid Build Coastguard Worker  * ignore the annotation.
9*c8d645caSAndroid Build Coastguard Worker  */
10*c8d645caSAndroid Build Coastguard Worker #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
11*c8d645caSAndroid Build Coastguard Worker     #define checkreturn
12*c8d645caSAndroid Build Coastguard Worker #else
13*c8d645caSAndroid Build Coastguard Worker     #define checkreturn __attribute__((warn_unused_result))
14*c8d645caSAndroid Build Coastguard Worker #endif
15*c8d645caSAndroid Build Coastguard Worker 
16*c8d645caSAndroid Build Coastguard Worker #include "pb.h"
17*c8d645caSAndroid Build Coastguard Worker #include "pb_decode.h"
18*c8d645caSAndroid Build Coastguard Worker #include "pb_common.h"
19*c8d645caSAndroid Build Coastguard Worker 
20*c8d645caSAndroid Build Coastguard Worker /**************************************
21*c8d645caSAndroid Build Coastguard Worker  * Declarations internal to this file *
22*c8d645caSAndroid Build Coastguard Worker  **************************************/
23*c8d645caSAndroid Build Coastguard Worker 
24*c8d645caSAndroid Build Coastguard Worker typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn;
25*c8d645caSAndroid Build Coastguard Worker 
26*c8d645caSAndroid Build Coastguard Worker static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
27*c8d645caSAndroid Build Coastguard Worker static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
28*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
29*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
30*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter);
31*c8d645caSAndroid Build Coastguard Worker static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension);
32*c8d645caSAndroid Build Coastguard Worker static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
33*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter);
34*c8d645caSAndroid Build Coastguard Worker static bool checkreturn find_extension_field(pb_field_iter_t *iter);
35*c8d645caSAndroid Build Coastguard Worker static void pb_field_set_to_default(pb_field_iter_t *iter);
36*c8d645caSAndroid Build Coastguard Worker static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct);
37*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_t *field, void *dest);
38*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
39*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
40*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
41*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
42*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
43*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest);
44*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
45*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
46*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest);
47*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
48*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_skip_varint(pb_istream_t *stream);
49*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_skip_string(pb_istream_t *stream);
50*c8d645caSAndroid Build Coastguard Worker 
51*c8d645caSAndroid Build Coastguard Worker #ifdef PB_ENABLE_MALLOC
52*c8d645caSAndroid Build Coastguard Worker static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
53*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter);
54*c8d645caSAndroid Build Coastguard Worker static void pb_release_single_field(const pb_field_iter_t *iter);
55*c8d645caSAndroid Build Coastguard Worker #endif
56*c8d645caSAndroid Build Coastguard Worker 
57*c8d645caSAndroid Build Coastguard Worker #ifdef PB_WITHOUT_64BIT
58*c8d645caSAndroid Build Coastguard Worker #define pb_int64_t int32_t
59*c8d645caSAndroid Build Coastguard Worker #define pb_uint64_t uint32_t
60*c8d645caSAndroid Build Coastguard Worker #else
61*c8d645caSAndroid Build Coastguard Worker #define pb_int64_t int64_t
62*c8d645caSAndroid Build Coastguard Worker #define pb_uint64_t uint64_t
63*c8d645caSAndroid Build Coastguard Worker #endif
64*c8d645caSAndroid Build Coastguard Worker 
65*c8d645caSAndroid Build Coastguard Worker /* --- Function pointers to field decoders ---
66*c8d645caSAndroid Build Coastguard Worker  * Order in the array must match pb_action_t LTYPE numbering.
67*c8d645caSAndroid Build Coastguard Worker  */
68*c8d645caSAndroid Build Coastguard Worker static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
69*c8d645caSAndroid Build Coastguard Worker     &pb_dec_bool,
70*c8d645caSAndroid Build Coastguard Worker     &pb_dec_varint,
71*c8d645caSAndroid Build Coastguard Worker     &pb_dec_uvarint,
72*c8d645caSAndroid Build Coastguard Worker     &pb_dec_svarint,
73*c8d645caSAndroid Build Coastguard Worker     &pb_dec_fixed32,
74*c8d645caSAndroid Build Coastguard Worker     &pb_dec_fixed64,
75*c8d645caSAndroid Build Coastguard Worker 
76*c8d645caSAndroid Build Coastguard Worker     &pb_dec_bytes,
77*c8d645caSAndroid Build Coastguard Worker     &pb_dec_string,
78*c8d645caSAndroid Build Coastguard Worker     &pb_dec_submessage,
79*c8d645caSAndroid Build Coastguard Worker     NULL, /* extensions */
80*c8d645caSAndroid Build Coastguard Worker     &pb_dec_fixed_length_bytes
81*c8d645caSAndroid Build Coastguard Worker };
82*c8d645caSAndroid Build Coastguard Worker 
83*c8d645caSAndroid Build Coastguard Worker /*******************************
84*c8d645caSAndroid Build Coastguard Worker  * pb_istream_t implementation *
85*c8d645caSAndroid Build Coastguard Worker  *******************************/
86*c8d645caSAndroid Build Coastguard Worker 
buf_read(pb_istream_t * stream,pb_byte_t * buf,size_t count)87*c8d645caSAndroid Build Coastguard Worker static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
88*c8d645caSAndroid Build Coastguard Worker {
89*c8d645caSAndroid Build Coastguard Worker     size_t i;
90*c8d645caSAndroid Build Coastguard Worker     const pb_byte_t *source = (const pb_byte_t*)stream->state;
91*c8d645caSAndroid Build Coastguard Worker     stream->state = (pb_byte_t*)stream->state + count;
92*c8d645caSAndroid Build Coastguard Worker 
93*c8d645caSAndroid Build Coastguard Worker     if (buf != NULL)
94*c8d645caSAndroid Build Coastguard Worker     {
95*c8d645caSAndroid Build Coastguard Worker         for (i = 0; i < count; i++)
96*c8d645caSAndroid Build Coastguard Worker             buf[i] = source[i];
97*c8d645caSAndroid Build Coastguard Worker     }
98*c8d645caSAndroid Build Coastguard Worker 
99*c8d645caSAndroid Build Coastguard Worker     return true;
100*c8d645caSAndroid Build Coastguard Worker }
101*c8d645caSAndroid Build Coastguard Worker 
pb_read(pb_istream_t * stream,pb_byte_t * buf,size_t count)102*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
103*c8d645caSAndroid Build Coastguard Worker {
104*c8d645caSAndroid Build Coastguard Worker     if (count == 0)
105*c8d645caSAndroid Build Coastguard Worker         return true;
106*c8d645caSAndroid Build Coastguard Worker 
107*c8d645caSAndroid Build Coastguard Worker #ifndef PB_BUFFER_ONLY
108*c8d645caSAndroid Build Coastguard Worker 	if (buf == NULL && stream->callback != buf_read)
109*c8d645caSAndroid Build Coastguard Worker 	{
110*c8d645caSAndroid Build Coastguard Worker 		/* Skip input bytes */
111*c8d645caSAndroid Build Coastguard Worker 		pb_byte_t tmp[16];
112*c8d645caSAndroid Build Coastguard Worker 		while (count > 16)
113*c8d645caSAndroid Build Coastguard Worker 		{
114*c8d645caSAndroid Build Coastguard Worker 			if (!pb_read(stream, tmp, 16))
115*c8d645caSAndroid Build Coastguard Worker 				return false;
116*c8d645caSAndroid Build Coastguard Worker 
117*c8d645caSAndroid Build Coastguard Worker 			count -= 16;
118*c8d645caSAndroid Build Coastguard Worker 		}
119*c8d645caSAndroid Build Coastguard Worker 
120*c8d645caSAndroid Build Coastguard Worker 		return pb_read(stream, tmp, count);
121*c8d645caSAndroid Build Coastguard Worker 	}
122*c8d645caSAndroid Build Coastguard Worker #endif
123*c8d645caSAndroid Build Coastguard Worker 
124*c8d645caSAndroid Build Coastguard Worker     if (stream->bytes_left < count)
125*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "end-of-stream");
126*c8d645caSAndroid Build Coastguard Worker 
127*c8d645caSAndroid Build Coastguard Worker #ifndef PB_BUFFER_ONLY
128*c8d645caSAndroid Build Coastguard Worker     if (!stream->callback(stream, buf, count))
129*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "io error");
130*c8d645caSAndroid Build Coastguard Worker #else
131*c8d645caSAndroid Build Coastguard Worker     if (!buf_read(stream, buf, count))
132*c8d645caSAndroid Build Coastguard Worker         return false;
133*c8d645caSAndroid Build Coastguard Worker #endif
134*c8d645caSAndroid Build Coastguard Worker 
135*c8d645caSAndroid Build Coastguard Worker     stream->bytes_left -= count;
136*c8d645caSAndroid Build Coastguard Worker     return true;
137*c8d645caSAndroid Build Coastguard Worker }
138*c8d645caSAndroid Build Coastguard Worker 
139*c8d645caSAndroid Build Coastguard Worker /* Read a single byte from input stream. buf may not be NULL.
140*c8d645caSAndroid Build Coastguard Worker  * This is an optimization for the varint decoding. */
pb_readbyte(pb_istream_t * stream,pb_byte_t * buf)141*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
142*c8d645caSAndroid Build Coastguard Worker {
143*c8d645caSAndroid Build Coastguard Worker     if (stream->bytes_left == 0)
144*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "end-of-stream");
145*c8d645caSAndroid Build Coastguard Worker 
146*c8d645caSAndroid Build Coastguard Worker #ifndef PB_BUFFER_ONLY
147*c8d645caSAndroid Build Coastguard Worker     if (!stream->callback(stream, buf, 1))
148*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "io error");
149*c8d645caSAndroid Build Coastguard Worker #else
150*c8d645caSAndroid Build Coastguard Worker     *buf = *(const pb_byte_t*)stream->state;
151*c8d645caSAndroid Build Coastguard Worker     stream->state = (pb_byte_t*)stream->state + 1;
152*c8d645caSAndroid Build Coastguard Worker #endif
153*c8d645caSAndroid Build Coastguard Worker 
154*c8d645caSAndroid Build Coastguard Worker     stream->bytes_left--;
155*c8d645caSAndroid Build Coastguard Worker 
156*c8d645caSAndroid Build Coastguard Worker     return true;
157*c8d645caSAndroid Build Coastguard Worker }
158*c8d645caSAndroid Build Coastguard Worker 
pb_istream_from_buffer(const pb_byte_t * buf,size_t bufsize)159*c8d645caSAndroid Build Coastguard Worker pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
160*c8d645caSAndroid Build Coastguard Worker {
161*c8d645caSAndroid Build Coastguard Worker     pb_istream_t stream;
162*c8d645caSAndroid Build Coastguard Worker     /* Cast away the const from buf without a compiler error.  We are
163*c8d645caSAndroid Build Coastguard Worker      * careful to use it only in a const manner in the callbacks.
164*c8d645caSAndroid Build Coastguard Worker      */
165*c8d645caSAndroid Build Coastguard Worker     union {
166*c8d645caSAndroid Build Coastguard Worker         void *state;
167*c8d645caSAndroid Build Coastguard Worker         const void *c_state;
168*c8d645caSAndroid Build Coastguard Worker     } state;
169*c8d645caSAndroid Build Coastguard Worker #ifdef PB_BUFFER_ONLY
170*c8d645caSAndroid Build Coastguard Worker     stream.callback = NULL;
171*c8d645caSAndroid Build Coastguard Worker #else
172*c8d645caSAndroid Build Coastguard Worker     stream.callback = &buf_read;
173*c8d645caSAndroid Build Coastguard Worker #endif
174*c8d645caSAndroid Build Coastguard Worker     state.c_state = buf;
175*c8d645caSAndroid Build Coastguard Worker     stream.state = state.state;
176*c8d645caSAndroid Build Coastguard Worker     stream.bytes_left = bufsize;
177*c8d645caSAndroid Build Coastguard Worker #ifndef PB_NO_ERRMSG
178*c8d645caSAndroid Build Coastguard Worker     stream.errmsg = NULL;
179*c8d645caSAndroid Build Coastguard Worker #endif
180*c8d645caSAndroid Build Coastguard Worker     return stream;
181*c8d645caSAndroid Build Coastguard Worker }
182*c8d645caSAndroid Build Coastguard Worker 
183*c8d645caSAndroid Build Coastguard Worker /********************
184*c8d645caSAndroid Build Coastguard Worker  * Helper functions *
185*c8d645caSAndroid Build Coastguard Worker  ********************/
186*c8d645caSAndroid Build Coastguard Worker 
pb_decode_varint32_eof(pb_istream_t * stream,uint32_t * dest,bool * eof)187*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof)
188*c8d645caSAndroid Build Coastguard Worker {
189*c8d645caSAndroid Build Coastguard Worker     pb_byte_t byte;
190*c8d645caSAndroid Build Coastguard Worker     uint32_t result;
191*c8d645caSAndroid Build Coastguard Worker 
192*c8d645caSAndroid Build Coastguard Worker     if (!pb_readbyte(stream, &byte))
193*c8d645caSAndroid Build Coastguard Worker     {
194*c8d645caSAndroid Build Coastguard Worker         if (stream->bytes_left == 0)
195*c8d645caSAndroid Build Coastguard Worker         {
196*c8d645caSAndroid Build Coastguard Worker             if (eof)
197*c8d645caSAndroid Build Coastguard Worker             {
198*c8d645caSAndroid Build Coastguard Worker                 *eof = true;
199*c8d645caSAndroid Build Coastguard Worker             }
200*c8d645caSAndroid Build Coastguard Worker         }
201*c8d645caSAndroid Build Coastguard Worker 
202*c8d645caSAndroid Build Coastguard Worker         return false;
203*c8d645caSAndroid Build Coastguard Worker     }
204*c8d645caSAndroid Build Coastguard Worker 
205*c8d645caSAndroid Build Coastguard Worker     if ((byte & 0x80) == 0)
206*c8d645caSAndroid Build Coastguard Worker     {
207*c8d645caSAndroid Build Coastguard Worker         /* Quick case, 1 byte value */
208*c8d645caSAndroid Build Coastguard Worker         result = byte;
209*c8d645caSAndroid Build Coastguard Worker     }
210*c8d645caSAndroid Build Coastguard Worker     else
211*c8d645caSAndroid Build Coastguard Worker     {
212*c8d645caSAndroid Build Coastguard Worker         /* Multibyte case */
213*c8d645caSAndroid Build Coastguard Worker         uint_fast8_t bitpos = 7;
214*c8d645caSAndroid Build Coastguard Worker         result = byte & 0x7F;
215*c8d645caSAndroid Build Coastguard Worker 
216*c8d645caSAndroid Build Coastguard Worker         do
217*c8d645caSAndroid Build Coastguard Worker         {
218*c8d645caSAndroid Build Coastguard Worker             if (!pb_readbyte(stream, &byte))
219*c8d645caSAndroid Build Coastguard Worker                 return false;
220*c8d645caSAndroid Build Coastguard Worker 
221*c8d645caSAndroid Build Coastguard Worker             if (bitpos >= 32)
222*c8d645caSAndroid Build Coastguard Worker             {
223*c8d645caSAndroid Build Coastguard Worker                 /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
224*c8d645caSAndroid Build Coastguard Worker                 uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
225*c8d645caSAndroid Build Coastguard Worker 
226*c8d645caSAndroid Build Coastguard Worker                 if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension))
227*c8d645caSAndroid Build Coastguard Worker                 {
228*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "varint overflow");
229*c8d645caSAndroid Build Coastguard Worker                 }
230*c8d645caSAndroid Build Coastguard Worker             }
231*c8d645caSAndroid Build Coastguard Worker             else
232*c8d645caSAndroid Build Coastguard Worker             {
233*c8d645caSAndroid Build Coastguard Worker                 result |= (uint32_t)(byte & 0x7F) << bitpos;
234*c8d645caSAndroid Build Coastguard Worker             }
235*c8d645caSAndroid Build Coastguard Worker             bitpos = (uint_fast8_t)(bitpos + 7);
236*c8d645caSAndroid Build Coastguard Worker         } while (byte & 0x80);
237*c8d645caSAndroid Build Coastguard Worker 
238*c8d645caSAndroid Build Coastguard Worker         if (bitpos == 35 && (byte & 0x70) != 0)
239*c8d645caSAndroid Build Coastguard Worker         {
240*c8d645caSAndroid Build Coastguard Worker             /* The last byte was at bitpos=28, so only bottom 4 bits fit. */
241*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "varint overflow");
242*c8d645caSAndroid Build Coastguard Worker         }
243*c8d645caSAndroid Build Coastguard Worker    }
244*c8d645caSAndroid Build Coastguard Worker 
245*c8d645caSAndroid Build Coastguard Worker    *dest = result;
246*c8d645caSAndroid Build Coastguard Worker    return true;
247*c8d645caSAndroid Build Coastguard Worker }
248*c8d645caSAndroid Build Coastguard Worker 
pb_decode_varint32(pb_istream_t * stream,uint32_t * dest)249*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
250*c8d645caSAndroid Build Coastguard Worker {
251*c8d645caSAndroid Build Coastguard Worker     return pb_decode_varint32_eof(stream, dest, NULL);
252*c8d645caSAndroid Build Coastguard Worker }
253*c8d645caSAndroid Build Coastguard Worker 
254*c8d645caSAndroid Build Coastguard Worker #ifndef PB_WITHOUT_64BIT
pb_decode_varint(pb_istream_t * stream,uint64_t * dest)255*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
256*c8d645caSAndroid Build Coastguard Worker {
257*c8d645caSAndroid Build Coastguard Worker     pb_byte_t byte;
258*c8d645caSAndroid Build Coastguard Worker     uint_fast8_t bitpos = 0;
259*c8d645caSAndroid Build Coastguard Worker     uint64_t result = 0;
260*c8d645caSAndroid Build Coastguard Worker 
261*c8d645caSAndroid Build Coastguard Worker     do
262*c8d645caSAndroid Build Coastguard Worker     {
263*c8d645caSAndroid Build Coastguard Worker         if (bitpos >= 64)
264*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "varint overflow");
265*c8d645caSAndroid Build Coastguard Worker 
266*c8d645caSAndroid Build Coastguard Worker         if (!pb_readbyte(stream, &byte))
267*c8d645caSAndroid Build Coastguard Worker             return false;
268*c8d645caSAndroid Build Coastguard Worker 
269*c8d645caSAndroid Build Coastguard Worker         result |= (uint64_t)(byte & 0x7F) << bitpos;
270*c8d645caSAndroid Build Coastguard Worker         bitpos = (uint_fast8_t)(bitpos + 7);
271*c8d645caSAndroid Build Coastguard Worker     } while (byte & 0x80);
272*c8d645caSAndroid Build Coastguard Worker 
273*c8d645caSAndroid Build Coastguard Worker     *dest = result;
274*c8d645caSAndroid Build Coastguard Worker     return true;
275*c8d645caSAndroid Build Coastguard Worker }
276*c8d645caSAndroid Build Coastguard Worker #endif
277*c8d645caSAndroid Build Coastguard Worker 
pb_skip_varint(pb_istream_t * stream)278*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_skip_varint(pb_istream_t *stream)
279*c8d645caSAndroid Build Coastguard Worker {
280*c8d645caSAndroid Build Coastguard Worker     pb_byte_t byte;
281*c8d645caSAndroid Build Coastguard Worker     do
282*c8d645caSAndroid Build Coastguard Worker     {
283*c8d645caSAndroid Build Coastguard Worker         if (!pb_read(stream, &byte, 1))
284*c8d645caSAndroid Build Coastguard Worker             return false;
285*c8d645caSAndroid Build Coastguard Worker     } while (byte & 0x80);
286*c8d645caSAndroid Build Coastguard Worker     return true;
287*c8d645caSAndroid Build Coastguard Worker }
288*c8d645caSAndroid Build Coastguard Worker 
pb_skip_string(pb_istream_t * stream)289*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_skip_string(pb_istream_t *stream)
290*c8d645caSAndroid Build Coastguard Worker {
291*c8d645caSAndroid Build Coastguard Worker     uint32_t length;
292*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &length))
293*c8d645caSAndroid Build Coastguard Worker         return false;
294*c8d645caSAndroid Build Coastguard Worker 
295*c8d645caSAndroid Build Coastguard Worker     return pb_read(stream, NULL, length);
296*c8d645caSAndroid Build Coastguard Worker }
297*c8d645caSAndroid Build Coastguard Worker 
pb_decode_tag(pb_istream_t * stream,pb_wire_type_t * wire_type,uint32_t * tag,bool * eof)298*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
299*c8d645caSAndroid Build Coastguard Worker {
300*c8d645caSAndroid Build Coastguard Worker     uint32_t temp;
301*c8d645caSAndroid Build Coastguard Worker     *eof = false;
302*c8d645caSAndroid Build Coastguard Worker     *wire_type = (pb_wire_type_t) 0;
303*c8d645caSAndroid Build Coastguard Worker     *tag = 0;
304*c8d645caSAndroid Build Coastguard Worker 
305*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32_eof(stream, &temp, eof))
306*c8d645caSAndroid Build Coastguard Worker     {
307*c8d645caSAndroid Build Coastguard Worker         return false;
308*c8d645caSAndroid Build Coastguard Worker     }
309*c8d645caSAndroid Build Coastguard Worker 
310*c8d645caSAndroid Build Coastguard Worker     if (temp == 0)
311*c8d645caSAndroid Build Coastguard Worker     {
312*c8d645caSAndroid Build Coastguard Worker         *eof = true; /* Special feature: allow 0-terminated messages. */
313*c8d645caSAndroid Build Coastguard Worker         return false;
314*c8d645caSAndroid Build Coastguard Worker     }
315*c8d645caSAndroid Build Coastguard Worker 
316*c8d645caSAndroid Build Coastguard Worker     *tag = temp >> 3;
317*c8d645caSAndroid Build Coastguard Worker     *wire_type = (pb_wire_type_t)(temp & 7);
318*c8d645caSAndroid Build Coastguard Worker     return true;
319*c8d645caSAndroid Build Coastguard Worker }
320*c8d645caSAndroid Build Coastguard Worker 
pb_skip_field(pb_istream_t * stream,pb_wire_type_t wire_type)321*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
322*c8d645caSAndroid Build Coastguard Worker {
323*c8d645caSAndroid Build Coastguard Worker     switch (wire_type)
324*c8d645caSAndroid Build Coastguard Worker     {
325*c8d645caSAndroid Build Coastguard Worker         case PB_WT_VARINT: return pb_skip_varint(stream);
326*c8d645caSAndroid Build Coastguard Worker         case PB_WT_64BIT: return pb_read(stream, NULL, 8);
327*c8d645caSAndroid Build Coastguard Worker         case PB_WT_STRING: return pb_skip_string(stream);
328*c8d645caSAndroid Build Coastguard Worker         case PB_WT_32BIT: return pb_read(stream, NULL, 4);
329*c8d645caSAndroid Build Coastguard Worker         default: PB_RETURN_ERROR(stream, "invalid wire_type");
330*c8d645caSAndroid Build Coastguard Worker     }
331*c8d645caSAndroid Build Coastguard Worker }
332*c8d645caSAndroid Build Coastguard Worker 
333*c8d645caSAndroid Build Coastguard Worker /* Read a raw value to buffer, for the purpose of passing it to callback as
334*c8d645caSAndroid Build Coastguard Worker  * a substream. Size is maximum size on call, and actual size on return.
335*c8d645caSAndroid Build Coastguard Worker  */
read_raw_value(pb_istream_t * stream,pb_wire_type_t wire_type,pb_byte_t * buf,size_t * size)336*c8d645caSAndroid Build Coastguard Worker static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size)
337*c8d645caSAndroid Build Coastguard Worker {
338*c8d645caSAndroid Build Coastguard Worker     size_t max_size = *size;
339*c8d645caSAndroid Build Coastguard Worker     switch (wire_type)
340*c8d645caSAndroid Build Coastguard Worker     {
341*c8d645caSAndroid Build Coastguard Worker         case PB_WT_VARINT:
342*c8d645caSAndroid Build Coastguard Worker             *size = 0;
343*c8d645caSAndroid Build Coastguard Worker             do
344*c8d645caSAndroid Build Coastguard Worker             {
345*c8d645caSAndroid Build Coastguard Worker                 (*size)++;
346*c8d645caSAndroid Build Coastguard Worker                 if (*size > max_size) return false;
347*c8d645caSAndroid Build Coastguard Worker                 if (!pb_read(stream, buf, 1)) return false;
348*c8d645caSAndroid Build Coastguard Worker             } while (*buf++ & 0x80);
349*c8d645caSAndroid Build Coastguard Worker             return true;
350*c8d645caSAndroid Build Coastguard Worker 
351*c8d645caSAndroid Build Coastguard Worker         case PB_WT_64BIT:
352*c8d645caSAndroid Build Coastguard Worker             *size = 8;
353*c8d645caSAndroid Build Coastguard Worker             return pb_read(stream, buf, 8);
354*c8d645caSAndroid Build Coastguard Worker 
355*c8d645caSAndroid Build Coastguard Worker         case PB_WT_32BIT:
356*c8d645caSAndroid Build Coastguard Worker             *size = 4;
357*c8d645caSAndroid Build Coastguard Worker             return pb_read(stream, buf, 4);
358*c8d645caSAndroid Build Coastguard Worker 
359*c8d645caSAndroid Build Coastguard Worker         case PB_WT_STRING:
360*c8d645caSAndroid Build Coastguard Worker             /* Calling read_raw_value with a PB_WT_STRING is an error.
361*c8d645caSAndroid Build Coastguard Worker              * Explicitly handle this case and fallthrough to default to avoid
362*c8d645caSAndroid Build Coastguard Worker              * compiler warnings.
363*c8d645caSAndroid Build Coastguard Worker              */
364*c8d645caSAndroid Build Coastguard Worker 
365*c8d645caSAndroid Build Coastguard Worker         default: PB_RETURN_ERROR(stream, "invalid wire_type");
366*c8d645caSAndroid Build Coastguard Worker     }
367*c8d645caSAndroid Build Coastguard Worker }
368*c8d645caSAndroid Build Coastguard Worker 
369*c8d645caSAndroid Build Coastguard Worker /* Decode string length from stream and return a substream with limited length.
370*c8d645caSAndroid Build Coastguard Worker  * Remember to close the substream using pb_close_string_substream().
371*c8d645caSAndroid Build Coastguard Worker  */
pb_make_string_substream(pb_istream_t * stream,pb_istream_t * substream)372*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
373*c8d645caSAndroid Build Coastguard Worker {
374*c8d645caSAndroid Build Coastguard Worker     uint32_t size;
375*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &size))
376*c8d645caSAndroid Build Coastguard Worker         return false;
377*c8d645caSAndroid Build Coastguard Worker 
378*c8d645caSAndroid Build Coastguard Worker     *substream = *stream;
379*c8d645caSAndroid Build Coastguard Worker     if (substream->bytes_left < size)
380*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "parent stream too short");
381*c8d645caSAndroid Build Coastguard Worker 
382*c8d645caSAndroid Build Coastguard Worker     substream->bytes_left = size;
383*c8d645caSAndroid Build Coastguard Worker     stream->bytes_left -= size;
384*c8d645caSAndroid Build Coastguard Worker     return true;
385*c8d645caSAndroid Build Coastguard Worker }
386*c8d645caSAndroid Build Coastguard Worker 
pb_close_string_substream(pb_istream_t * stream,pb_istream_t * substream)387*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream)
388*c8d645caSAndroid Build Coastguard Worker {
389*c8d645caSAndroid Build Coastguard Worker     if (substream->bytes_left) {
390*c8d645caSAndroid Build Coastguard Worker         if (!pb_read(substream, NULL, substream->bytes_left))
391*c8d645caSAndroid Build Coastguard Worker             return false;
392*c8d645caSAndroid Build Coastguard Worker     }
393*c8d645caSAndroid Build Coastguard Worker 
394*c8d645caSAndroid Build Coastguard Worker     stream->state = substream->state;
395*c8d645caSAndroid Build Coastguard Worker 
396*c8d645caSAndroid Build Coastguard Worker #ifndef PB_NO_ERRMSG
397*c8d645caSAndroid Build Coastguard Worker     stream->errmsg = substream->errmsg;
398*c8d645caSAndroid Build Coastguard Worker #endif
399*c8d645caSAndroid Build Coastguard Worker     return true;
400*c8d645caSAndroid Build Coastguard Worker }
401*c8d645caSAndroid Build Coastguard Worker 
402*c8d645caSAndroid Build Coastguard Worker /*************************
403*c8d645caSAndroid Build Coastguard Worker  * Decode a single field *
404*c8d645caSAndroid Build Coastguard Worker  *************************/
405*c8d645caSAndroid Build Coastguard Worker 
decode_static_field(pb_istream_t * stream,pb_wire_type_t wire_type,pb_field_iter_t * iter)406*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
407*c8d645caSAndroid Build Coastguard Worker {
408*c8d645caSAndroid Build Coastguard Worker     pb_type_t type;
409*c8d645caSAndroid Build Coastguard Worker     pb_decoder_t func;
410*c8d645caSAndroid Build Coastguard Worker 
411*c8d645caSAndroid Build Coastguard Worker     type = iter->pos->type;
412*c8d645caSAndroid Build Coastguard Worker     func = PB_DECODERS[PB_LTYPE(type)];
413*c8d645caSAndroid Build Coastguard Worker 
414*c8d645caSAndroid Build Coastguard Worker     switch (PB_HTYPE(type))
415*c8d645caSAndroid Build Coastguard Worker     {
416*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_REQUIRED:
417*c8d645caSAndroid Build Coastguard Worker             return func(stream, iter->pos, iter->pData);
418*c8d645caSAndroid Build Coastguard Worker 
419*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_OPTIONAL:
420*c8d645caSAndroid Build Coastguard Worker             if (iter->pSize != iter->pData)
421*c8d645caSAndroid Build Coastguard Worker                 *(bool*)iter->pSize = true;
422*c8d645caSAndroid Build Coastguard Worker             return func(stream, iter->pos, iter->pData);
423*c8d645caSAndroid Build Coastguard Worker 
424*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_REPEATED:
425*c8d645caSAndroid Build Coastguard Worker             if (wire_type == PB_WT_STRING
426*c8d645caSAndroid Build Coastguard Worker                 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
427*c8d645caSAndroid Build Coastguard Worker             {
428*c8d645caSAndroid Build Coastguard Worker                 /* Packed array */
429*c8d645caSAndroid Build Coastguard Worker                 bool status = true;
430*c8d645caSAndroid Build Coastguard Worker                 pb_size_t *size = (pb_size_t*)iter->pSize;
431*c8d645caSAndroid Build Coastguard Worker 
432*c8d645caSAndroid Build Coastguard Worker                 pb_istream_t substream;
433*c8d645caSAndroid Build Coastguard Worker                 if (!pb_make_string_substream(stream, &substream))
434*c8d645caSAndroid Build Coastguard Worker                     return false;
435*c8d645caSAndroid Build Coastguard Worker 
436*c8d645caSAndroid Build Coastguard Worker                 while (substream.bytes_left > 0 && *size < iter->pos->array_size)
437*c8d645caSAndroid Build Coastguard Worker                 {
438*c8d645caSAndroid Build Coastguard Worker                     void *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
439*c8d645caSAndroid Build Coastguard Worker                     if (!func(&substream, iter->pos, pItem))
440*c8d645caSAndroid Build Coastguard Worker                     {
441*c8d645caSAndroid Build Coastguard Worker                         status = false;
442*c8d645caSAndroid Build Coastguard Worker                         break;
443*c8d645caSAndroid Build Coastguard Worker                     }
444*c8d645caSAndroid Build Coastguard Worker                     (*size)++;
445*c8d645caSAndroid Build Coastguard Worker                 }
446*c8d645caSAndroid Build Coastguard Worker 
447*c8d645caSAndroid Build Coastguard Worker                 if (substream.bytes_left != 0)
448*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "array overflow");
449*c8d645caSAndroid Build Coastguard Worker                 if (!pb_close_string_substream(stream, &substream))
450*c8d645caSAndroid Build Coastguard Worker                     return false;
451*c8d645caSAndroid Build Coastguard Worker 
452*c8d645caSAndroid Build Coastguard Worker                 return status;
453*c8d645caSAndroid Build Coastguard Worker             }
454*c8d645caSAndroid Build Coastguard Worker             else
455*c8d645caSAndroid Build Coastguard Worker             {
456*c8d645caSAndroid Build Coastguard Worker                 /* Repeated field */
457*c8d645caSAndroid Build Coastguard Worker                 pb_size_t *size = (pb_size_t*)iter->pSize;
458*c8d645caSAndroid Build Coastguard Worker                 char *pItem = (char*)iter->pData + iter->pos->data_size * (*size);
459*c8d645caSAndroid Build Coastguard Worker 
460*c8d645caSAndroid Build Coastguard Worker                 if ((*size)++ >= iter->pos->array_size)
461*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "array overflow");
462*c8d645caSAndroid Build Coastguard Worker 
463*c8d645caSAndroid Build Coastguard Worker                 return func(stream, iter->pos, pItem);
464*c8d645caSAndroid Build Coastguard Worker             }
465*c8d645caSAndroid Build Coastguard Worker 
466*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_ONEOF:
467*c8d645caSAndroid Build Coastguard Worker             if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE &&
468*c8d645caSAndroid Build Coastguard Worker                 *(pb_size_t*)iter->pSize != iter->pos->tag)
469*c8d645caSAndroid Build Coastguard Worker             {
470*c8d645caSAndroid Build Coastguard Worker                 /* We memset to zero so that any callbacks are set to NULL.
471*c8d645caSAndroid Build Coastguard Worker                  * This is because the callbacks might otherwise have values
472*c8d645caSAndroid Build Coastguard Worker                  * from some other union field. */
473*c8d645caSAndroid Build Coastguard Worker                 memset(iter->pData, 0, iter->pos->data_size);
474*c8d645caSAndroid Build Coastguard Worker                 pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData);
475*c8d645caSAndroid Build Coastguard Worker             }
476*c8d645caSAndroid Build Coastguard Worker             *(pb_size_t*)iter->pSize = iter->pos->tag;
477*c8d645caSAndroid Build Coastguard Worker 
478*c8d645caSAndroid Build Coastguard Worker             return func(stream, iter->pos, iter->pData);
479*c8d645caSAndroid Build Coastguard Worker 
480*c8d645caSAndroid Build Coastguard Worker         default:
481*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "invalid field type");
482*c8d645caSAndroid Build Coastguard Worker     }
483*c8d645caSAndroid Build Coastguard Worker }
484*c8d645caSAndroid Build Coastguard Worker 
485*c8d645caSAndroid Build Coastguard Worker #ifdef PB_ENABLE_MALLOC
486*c8d645caSAndroid Build Coastguard Worker /* Allocate storage for the field and store the pointer at iter->pData.
487*c8d645caSAndroid Build Coastguard Worker  * array_size is the number of entries to reserve in an array.
488*c8d645caSAndroid Build Coastguard Worker  * Zero size is not allowed, use pb_free() for releasing.
489*c8d645caSAndroid Build Coastguard Worker  */
allocate_field(pb_istream_t * stream,void * pData,size_t data_size,size_t array_size)490*c8d645caSAndroid Build Coastguard Worker static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size)
491*c8d645caSAndroid Build Coastguard Worker {
492*c8d645caSAndroid Build Coastguard Worker     void *ptr = *(void**)pData;
493*c8d645caSAndroid Build Coastguard Worker 
494*c8d645caSAndroid Build Coastguard Worker     if (data_size == 0 || array_size == 0)
495*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid size");
496*c8d645caSAndroid Build Coastguard Worker 
497*c8d645caSAndroid Build Coastguard Worker #ifdef __AVR__
498*c8d645caSAndroid Build Coastguard Worker     /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284
499*c8d645caSAndroid Build Coastguard Worker      * Realloc to size of 1 byte can cause corruption of the malloc structures.
500*c8d645caSAndroid Build Coastguard Worker      */
501*c8d645caSAndroid Build Coastguard Worker     if (data_size == 1 && array_size == 1)
502*c8d645caSAndroid Build Coastguard Worker     {
503*c8d645caSAndroid Build Coastguard Worker         data_size = 2;
504*c8d645caSAndroid Build Coastguard Worker     }
505*c8d645caSAndroid Build Coastguard Worker #endif
506*c8d645caSAndroid Build Coastguard Worker 
507*c8d645caSAndroid Build Coastguard Worker     /* Check for multiplication overflows.
508*c8d645caSAndroid Build Coastguard Worker      * This code avoids the costly division if the sizes are small enough.
509*c8d645caSAndroid Build Coastguard Worker      * Multiplication is safe as long as only half of bits are set
510*c8d645caSAndroid Build Coastguard Worker      * in either multiplicand.
511*c8d645caSAndroid Build Coastguard Worker      */
512*c8d645caSAndroid Build Coastguard Worker     {
513*c8d645caSAndroid Build Coastguard Worker         const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4);
514*c8d645caSAndroid Build Coastguard Worker         if (data_size >= check_limit || array_size >= check_limit)
515*c8d645caSAndroid Build Coastguard Worker         {
516*c8d645caSAndroid Build Coastguard Worker             const size_t size_max = (size_t)-1;
517*c8d645caSAndroid Build Coastguard Worker             if (size_max / array_size < data_size)
518*c8d645caSAndroid Build Coastguard Worker             {
519*c8d645caSAndroid Build Coastguard Worker                 PB_RETURN_ERROR(stream, "size too large");
520*c8d645caSAndroid Build Coastguard Worker             }
521*c8d645caSAndroid Build Coastguard Worker         }
522*c8d645caSAndroid Build Coastguard Worker     }
523*c8d645caSAndroid Build Coastguard Worker 
524*c8d645caSAndroid Build Coastguard Worker     /* Allocate new or expand previous allocation */
525*c8d645caSAndroid Build Coastguard Worker     /* Note: on failure the old pointer will remain in the structure,
526*c8d645caSAndroid Build Coastguard Worker      * the message must be freed by caller also on error return. */
527*c8d645caSAndroid Build Coastguard Worker     ptr = pb_realloc(ptr, array_size * data_size);
528*c8d645caSAndroid Build Coastguard Worker     if (ptr == NULL)
529*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "realloc failed");
530*c8d645caSAndroid Build Coastguard Worker 
531*c8d645caSAndroid Build Coastguard Worker     *(void**)pData = ptr;
532*c8d645caSAndroid Build Coastguard Worker     return true;
533*c8d645caSAndroid Build Coastguard Worker }
534*c8d645caSAndroid Build Coastguard Worker 
535*c8d645caSAndroid Build Coastguard Worker /* Clear a newly allocated item in case it contains a pointer, or is a submessage. */
initialize_pointer_field(void * pItem,pb_field_iter_t * iter)536*c8d645caSAndroid Build Coastguard Worker static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter)
537*c8d645caSAndroid Build Coastguard Worker {
538*c8d645caSAndroid Build Coastguard Worker     if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING ||
539*c8d645caSAndroid Build Coastguard Worker         PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES)
540*c8d645caSAndroid Build Coastguard Worker     {
541*c8d645caSAndroid Build Coastguard Worker         *(void**)pItem = NULL;
542*c8d645caSAndroid Build Coastguard Worker     }
543*c8d645caSAndroid Build Coastguard Worker     else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
544*c8d645caSAndroid Build Coastguard Worker     {
545*c8d645caSAndroid Build Coastguard Worker         /* We memset to zero so that any callbacks are set to NULL.
546*c8d645caSAndroid Build Coastguard Worker          * Then set any default values. */
547*c8d645caSAndroid Build Coastguard Worker         memset(pItem, 0, iter->pos->data_size);
548*c8d645caSAndroid Build Coastguard Worker         pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem);
549*c8d645caSAndroid Build Coastguard Worker     }
550*c8d645caSAndroid Build Coastguard Worker }
551*c8d645caSAndroid Build Coastguard Worker #endif
552*c8d645caSAndroid Build Coastguard Worker 
decode_pointer_field(pb_istream_t * stream,pb_wire_type_t wire_type,pb_field_iter_t * iter)553*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
554*c8d645caSAndroid Build Coastguard Worker {
555*c8d645caSAndroid Build Coastguard Worker #ifndef PB_ENABLE_MALLOC
556*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(wire_type);
557*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(iter);
558*c8d645caSAndroid Build Coastguard Worker     PB_RETURN_ERROR(stream, "no malloc support");
559*c8d645caSAndroid Build Coastguard Worker #else
560*c8d645caSAndroid Build Coastguard Worker     pb_type_t type;
561*c8d645caSAndroid Build Coastguard Worker     pb_decoder_t func;
562*c8d645caSAndroid Build Coastguard Worker 
563*c8d645caSAndroid Build Coastguard Worker     type = iter->pos->type;
564*c8d645caSAndroid Build Coastguard Worker     func = PB_DECODERS[PB_LTYPE(type)];
565*c8d645caSAndroid Build Coastguard Worker 
566*c8d645caSAndroid Build Coastguard Worker     switch (PB_HTYPE(type))
567*c8d645caSAndroid Build Coastguard Worker     {
568*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_REQUIRED:
569*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_OPTIONAL:
570*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_ONEOF:
571*c8d645caSAndroid Build Coastguard Worker             if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE &&
572*c8d645caSAndroid Build Coastguard Worker                 *(void**)iter->pData != NULL)
573*c8d645caSAndroid Build Coastguard Worker             {
574*c8d645caSAndroid Build Coastguard Worker                 /* Duplicate field, have to release the old allocation first. */
575*c8d645caSAndroid Build Coastguard Worker                 pb_release_single_field(iter);
576*c8d645caSAndroid Build Coastguard Worker             }
577*c8d645caSAndroid Build Coastguard Worker 
578*c8d645caSAndroid Build Coastguard Worker             if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
579*c8d645caSAndroid Build Coastguard Worker             {
580*c8d645caSAndroid Build Coastguard Worker                 *(pb_size_t*)iter->pSize = iter->pos->tag;
581*c8d645caSAndroid Build Coastguard Worker             }
582*c8d645caSAndroid Build Coastguard Worker 
583*c8d645caSAndroid Build Coastguard Worker             if (PB_LTYPE(type) == PB_LTYPE_STRING ||
584*c8d645caSAndroid Build Coastguard Worker                 PB_LTYPE(type) == PB_LTYPE_BYTES)
585*c8d645caSAndroid Build Coastguard Worker             {
586*c8d645caSAndroid Build Coastguard Worker                 return func(stream, iter->pos, iter->pData);
587*c8d645caSAndroid Build Coastguard Worker             }
588*c8d645caSAndroid Build Coastguard Worker             else
589*c8d645caSAndroid Build Coastguard Worker             {
590*c8d645caSAndroid Build Coastguard Worker                 if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1))
591*c8d645caSAndroid Build Coastguard Worker                     return false;
592*c8d645caSAndroid Build Coastguard Worker 
593*c8d645caSAndroid Build Coastguard Worker                 initialize_pointer_field(*(void**)iter->pData, iter);
594*c8d645caSAndroid Build Coastguard Worker                 return func(stream, iter->pos, *(void**)iter->pData);
595*c8d645caSAndroid Build Coastguard Worker             }
596*c8d645caSAndroid Build Coastguard Worker 
597*c8d645caSAndroid Build Coastguard Worker         case PB_HTYPE_REPEATED:
598*c8d645caSAndroid Build Coastguard Worker             if (wire_type == PB_WT_STRING
599*c8d645caSAndroid Build Coastguard Worker                 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
600*c8d645caSAndroid Build Coastguard Worker             {
601*c8d645caSAndroid Build Coastguard Worker                 /* Packed array, multiple items come in at once. */
602*c8d645caSAndroid Build Coastguard Worker                 bool status = true;
603*c8d645caSAndroid Build Coastguard Worker                 pb_size_t *size = (pb_size_t*)iter->pSize;
604*c8d645caSAndroid Build Coastguard Worker                 size_t allocated_size = *size;
605*c8d645caSAndroid Build Coastguard Worker                 void *pItem;
606*c8d645caSAndroid Build Coastguard Worker                 pb_istream_t substream;
607*c8d645caSAndroid Build Coastguard Worker 
608*c8d645caSAndroid Build Coastguard Worker                 if (!pb_make_string_substream(stream, &substream))
609*c8d645caSAndroid Build Coastguard Worker                     return false;
610*c8d645caSAndroid Build Coastguard Worker 
611*c8d645caSAndroid Build Coastguard Worker                 while (substream.bytes_left)
612*c8d645caSAndroid Build Coastguard Worker                 {
613*c8d645caSAndroid Build Coastguard Worker                     if (*size == PB_SIZE_MAX)
614*c8d645caSAndroid Build Coastguard Worker                     {
615*c8d645caSAndroid Build Coastguard Worker #ifndef PB_NO_ERRMSG
616*c8d645caSAndroid Build Coastguard Worker                         stream->errmsg = "too many array entries";
617*c8d645caSAndroid Build Coastguard Worker #endif
618*c8d645caSAndroid Build Coastguard Worker                         status = false;
619*c8d645caSAndroid Build Coastguard Worker                         break;
620*c8d645caSAndroid Build Coastguard Worker                     }
621*c8d645caSAndroid Build Coastguard Worker 
622*c8d645caSAndroid Build Coastguard Worker                     if ((size_t)*size + 1 > allocated_size)
623*c8d645caSAndroid Build Coastguard Worker                     {
624*c8d645caSAndroid Build Coastguard Worker                         /* Allocate more storage. This tries to guess the
625*c8d645caSAndroid Build Coastguard Worker                          * number of remaining entries. Round the division
626*c8d645caSAndroid Build Coastguard Worker                          * upwards. */
627*c8d645caSAndroid Build Coastguard Worker                         size_t remain = (substream.bytes_left - 1) / iter->pos->data_size + 1;
628*c8d645caSAndroid Build Coastguard Worker                         if (remain < PB_SIZE_MAX - allocated_size)
629*c8d645caSAndroid Build Coastguard Worker                             allocated_size += remain;
630*c8d645caSAndroid Build Coastguard Worker                         else
631*c8d645caSAndroid Build Coastguard Worker                             allocated_size += 1;
632*c8d645caSAndroid Build Coastguard Worker 
633*c8d645caSAndroid Build Coastguard Worker                         if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size))
634*c8d645caSAndroid Build Coastguard Worker                         {
635*c8d645caSAndroid Build Coastguard Worker                             status = false;
636*c8d645caSAndroid Build Coastguard Worker                             break;
637*c8d645caSAndroid Build Coastguard Worker                         }
638*c8d645caSAndroid Build Coastguard Worker                     }
639*c8d645caSAndroid Build Coastguard Worker 
640*c8d645caSAndroid Build Coastguard Worker                     /* Decode the array entry */
641*c8d645caSAndroid Build Coastguard Worker                     pItem = *(char**)iter->pData + iter->pos->data_size * (*size);
642*c8d645caSAndroid Build Coastguard Worker                     initialize_pointer_field(pItem, iter);
643*c8d645caSAndroid Build Coastguard Worker                     if (!func(&substream, iter->pos, pItem))
644*c8d645caSAndroid Build Coastguard Worker                     {
645*c8d645caSAndroid Build Coastguard Worker                         status = false;
646*c8d645caSAndroid Build Coastguard Worker                         break;
647*c8d645caSAndroid Build Coastguard Worker                     }
648*c8d645caSAndroid Build Coastguard Worker 
649*c8d645caSAndroid Build Coastguard Worker                     (*size)++;
650*c8d645caSAndroid Build Coastguard Worker                 }
651*c8d645caSAndroid Build Coastguard Worker                 if (!pb_close_string_substream(stream, &substream))
652*c8d645caSAndroid Build Coastguard Worker                     return false;
653*c8d645caSAndroid Build Coastguard Worker 
654*c8d645caSAndroid Build Coastguard Worker                 return status;
655*c8d645caSAndroid Build Coastguard Worker             }
656*c8d645caSAndroid Build Coastguard Worker             else
657*c8d645caSAndroid Build Coastguard Worker             {
658*c8d645caSAndroid Build Coastguard Worker                 /* Normal repeated field, i.e. only one item at a time. */
659*c8d645caSAndroid Build Coastguard Worker                 pb_size_t *size = (pb_size_t*)iter->pSize;
660*c8d645caSAndroid Build Coastguard Worker                 void *pItem;
661*c8d645caSAndroid Build Coastguard Worker 
662*c8d645caSAndroid Build Coastguard Worker                 if (*size == PB_SIZE_MAX)
663*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "too many array entries");
664*c8d645caSAndroid Build Coastguard Worker 
665*c8d645caSAndroid Build Coastguard Worker                 if (!allocate_field(stream, iter->pData, iter->pos->data_size, (size_t)(*size + 1)))
666*c8d645caSAndroid Build Coastguard Worker                     return false;
667*c8d645caSAndroid Build Coastguard Worker 
668*c8d645caSAndroid Build Coastguard Worker                 pItem = *(char**)iter->pData + iter->pos->data_size * (*size);
669*c8d645caSAndroid Build Coastguard Worker                 (*size)++;
670*c8d645caSAndroid Build Coastguard Worker                 initialize_pointer_field(pItem, iter);
671*c8d645caSAndroid Build Coastguard Worker                 return func(stream, iter->pos, pItem);
672*c8d645caSAndroid Build Coastguard Worker             }
673*c8d645caSAndroid Build Coastguard Worker 
674*c8d645caSAndroid Build Coastguard Worker         default:
675*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "invalid field type");
676*c8d645caSAndroid Build Coastguard Worker     }
677*c8d645caSAndroid Build Coastguard Worker #endif
678*c8d645caSAndroid Build Coastguard Worker }
679*c8d645caSAndroid Build Coastguard Worker 
decode_callback_field(pb_istream_t * stream,pb_wire_type_t wire_type,pb_field_iter_t * iter)680*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
681*c8d645caSAndroid Build Coastguard Worker {
682*c8d645caSAndroid Build Coastguard Worker     pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
683*c8d645caSAndroid Build Coastguard Worker #ifdef PB_OLD_CALLBACK_STYLE
684*c8d645caSAndroid Build Coastguard Worker     void *arg;
685*c8d645caSAndroid Build Coastguard Worker #else
686*c8d645caSAndroid Build Coastguard Worker     void **arg;
687*c8d645caSAndroid Build Coastguard Worker #endif
688*c8d645caSAndroid Build Coastguard Worker 
689*c8d645caSAndroid Build Coastguard Worker     if (pCallback == NULL || pCallback->funcs.decode == NULL)
690*c8d645caSAndroid Build Coastguard Worker         return pb_skip_field(stream, wire_type);
691*c8d645caSAndroid Build Coastguard Worker 
692*c8d645caSAndroid Build Coastguard Worker #ifdef PB_OLD_CALLBACK_STYLE
693*c8d645caSAndroid Build Coastguard Worker     arg = pCallback->arg;
694*c8d645caSAndroid Build Coastguard Worker #else
695*c8d645caSAndroid Build Coastguard Worker     arg = &(pCallback->arg);
696*c8d645caSAndroid Build Coastguard Worker #endif
697*c8d645caSAndroid Build Coastguard Worker 
698*c8d645caSAndroid Build Coastguard Worker     if (wire_type == PB_WT_STRING)
699*c8d645caSAndroid Build Coastguard Worker     {
700*c8d645caSAndroid Build Coastguard Worker         pb_istream_t substream;
701*c8d645caSAndroid Build Coastguard Worker 
702*c8d645caSAndroid Build Coastguard Worker         if (!pb_make_string_substream(stream, &substream))
703*c8d645caSAndroid Build Coastguard Worker             return false;
704*c8d645caSAndroid Build Coastguard Worker 
705*c8d645caSAndroid Build Coastguard Worker         do
706*c8d645caSAndroid Build Coastguard Worker         {
707*c8d645caSAndroid Build Coastguard Worker             if (!pCallback->funcs.decode(&substream, iter->pos, arg))
708*c8d645caSAndroid Build Coastguard Worker                 PB_RETURN_ERROR(stream, "callback failed");
709*c8d645caSAndroid Build Coastguard Worker         } while (substream.bytes_left);
710*c8d645caSAndroid Build Coastguard Worker 
711*c8d645caSAndroid Build Coastguard Worker         if (!pb_close_string_substream(stream, &substream))
712*c8d645caSAndroid Build Coastguard Worker             return false;
713*c8d645caSAndroid Build Coastguard Worker 
714*c8d645caSAndroid Build Coastguard Worker         return true;
715*c8d645caSAndroid Build Coastguard Worker     }
716*c8d645caSAndroid Build Coastguard Worker     else
717*c8d645caSAndroid Build Coastguard Worker     {
718*c8d645caSAndroid Build Coastguard Worker         /* Copy the single scalar value to stack.
719*c8d645caSAndroid Build Coastguard Worker          * This is required so that we can limit the stream length,
720*c8d645caSAndroid Build Coastguard Worker          * which in turn allows to use same callback for packed and
721*c8d645caSAndroid Build Coastguard Worker          * not-packed fields. */
722*c8d645caSAndroid Build Coastguard Worker         pb_istream_t substream;
723*c8d645caSAndroid Build Coastguard Worker         pb_byte_t buffer[10];
724*c8d645caSAndroid Build Coastguard Worker         size_t size = sizeof(buffer);
725*c8d645caSAndroid Build Coastguard Worker 
726*c8d645caSAndroid Build Coastguard Worker         if (!read_raw_value(stream, wire_type, buffer, &size))
727*c8d645caSAndroid Build Coastguard Worker             return false;
728*c8d645caSAndroid Build Coastguard Worker         substream = pb_istream_from_buffer(buffer, size);
729*c8d645caSAndroid Build Coastguard Worker 
730*c8d645caSAndroid Build Coastguard Worker         return pCallback->funcs.decode(&substream, iter->pos, arg);
731*c8d645caSAndroid Build Coastguard Worker     }
732*c8d645caSAndroid Build Coastguard Worker }
733*c8d645caSAndroid Build Coastguard Worker 
decode_field(pb_istream_t * stream,pb_wire_type_t wire_type,pb_field_iter_t * iter)734*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter)
735*c8d645caSAndroid Build Coastguard Worker {
736*c8d645caSAndroid Build Coastguard Worker #ifdef PB_ENABLE_MALLOC
737*c8d645caSAndroid Build Coastguard Worker     /* When decoding an oneof field, check if there is old data that must be
738*c8d645caSAndroid Build Coastguard Worker      * released first. */
739*c8d645caSAndroid Build Coastguard Worker     if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF)
740*c8d645caSAndroid Build Coastguard Worker     {
741*c8d645caSAndroid Build Coastguard Worker         if (!pb_release_union_field(stream, iter))
742*c8d645caSAndroid Build Coastguard Worker             return false;
743*c8d645caSAndroid Build Coastguard Worker     }
744*c8d645caSAndroid Build Coastguard Worker #endif
745*c8d645caSAndroid Build Coastguard Worker 
746*c8d645caSAndroid Build Coastguard Worker     switch (PB_ATYPE(iter->pos->type))
747*c8d645caSAndroid Build Coastguard Worker     {
748*c8d645caSAndroid Build Coastguard Worker         case PB_ATYPE_STATIC:
749*c8d645caSAndroid Build Coastguard Worker             return decode_static_field(stream, wire_type, iter);
750*c8d645caSAndroid Build Coastguard Worker 
751*c8d645caSAndroid Build Coastguard Worker         case PB_ATYPE_POINTER:
752*c8d645caSAndroid Build Coastguard Worker             return decode_pointer_field(stream, wire_type, iter);
753*c8d645caSAndroid Build Coastguard Worker 
754*c8d645caSAndroid Build Coastguard Worker         case PB_ATYPE_CALLBACK:
755*c8d645caSAndroid Build Coastguard Worker             return decode_callback_field(stream, wire_type, iter);
756*c8d645caSAndroid Build Coastguard Worker 
757*c8d645caSAndroid Build Coastguard Worker         default:
758*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "invalid field type");
759*c8d645caSAndroid Build Coastguard Worker     }
760*c8d645caSAndroid Build Coastguard Worker }
761*c8d645caSAndroid Build Coastguard Worker 
iter_from_extension(pb_field_iter_t * iter,pb_extension_t * extension)762*c8d645caSAndroid Build Coastguard Worker static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension)
763*c8d645caSAndroid Build Coastguard Worker {
764*c8d645caSAndroid Build Coastguard Worker     /* Fake a field iterator for the extension field.
765*c8d645caSAndroid Build Coastguard Worker      * It is not actually safe to advance this iterator, but decode_field
766*c8d645caSAndroid Build Coastguard Worker      * will not even try to. */
767*c8d645caSAndroid Build Coastguard Worker     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
768*c8d645caSAndroid Build Coastguard Worker     (void)pb_field_iter_begin(iter, field, extension->dest);
769*c8d645caSAndroid Build Coastguard Worker     iter->pData = extension->dest;
770*c8d645caSAndroid Build Coastguard Worker     iter->pSize = &extension->found;
771*c8d645caSAndroid Build Coastguard Worker 
772*c8d645caSAndroid Build Coastguard Worker     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
773*c8d645caSAndroid Build Coastguard Worker     {
774*c8d645caSAndroid Build Coastguard Worker         /* For pointer extensions, the pointer is stored directly
775*c8d645caSAndroid Build Coastguard Worker          * in the extension structure. This avoids having an extra
776*c8d645caSAndroid Build Coastguard Worker          * indirection. */
777*c8d645caSAndroid Build Coastguard Worker         iter->pData = &extension->dest;
778*c8d645caSAndroid Build Coastguard Worker     }
779*c8d645caSAndroid Build Coastguard Worker }
780*c8d645caSAndroid Build Coastguard Worker 
781*c8d645caSAndroid Build Coastguard Worker /* Default handler for extension fields. Expects a pb_field_t structure
782*c8d645caSAndroid Build Coastguard Worker  * in extension->type->arg. */
default_extension_decoder(pb_istream_t * stream,pb_extension_t * extension,uint32_t tag,pb_wire_type_t wire_type)783*c8d645caSAndroid Build Coastguard Worker static bool checkreturn default_extension_decoder(pb_istream_t *stream,
784*c8d645caSAndroid Build Coastguard Worker     pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type)
785*c8d645caSAndroid Build Coastguard Worker {
786*c8d645caSAndroid Build Coastguard Worker     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
787*c8d645caSAndroid Build Coastguard Worker     pb_field_iter_t iter;
788*c8d645caSAndroid Build Coastguard Worker 
789*c8d645caSAndroid Build Coastguard Worker     if (field->tag != tag)
790*c8d645caSAndroid Build Coastguard Worker         return true;
791*c8d645caSAndroid Build Coastguard Worker 
792*c8d645caSAndroid Build Coastguard Worker     iter_from_extension(&iter, extension);
793*c8d645caSAndroid Build Coastguard Worker     extension->found = true;
794*c8d645caSAndroid Build Coastguard Worker     return decode_field(stream, wire_type, &iter);
795*c8d645caSAndroid Build Coastguard Worker }
796*c8d645caSAndroid Build Coastguard Worker 
797*c8d645caSAndroid Build Coastguard Worker /* Try to decode an unknown field as an extension field. Tries each extension
798*c8d645caSAndroid Build Coastguard Worker  * decoder in turn, until one of them handles the field or loop ends. */
decode_extension(pb_istream_t * stream,uint32_t tag,pb_wire_type_t wire_type,pb_field_iter_t * iter)799*c8d645caSAndroid Build Coastguard Worker static bool checkreturn decode_extension(pb_istream_t *stream,
800*c8d645caSAndroid Build Coastguard Worker     uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter)
801*c8d645caSAndroid Build Coastguard Worker {
802*c8d645caSAndroid Build Coastguard Worker     pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
803*c8d645caSAndroid Build Coastguard Worker     size_t pos = stream->bytes_left;
804*c8d645caSAndroid Build Coastguard Worker 
805*c8d645caSAndroid Build Coastguard Worker     while (extension != NULL && pos == stream->bytes_left)
806*c8d645caSAndroid Build Coastguard Worker     {
807*c8d645caSAndroid Build Coastguard Worker         bool status;
808*c8d645caSAndroid Build Coastguard Worker         if (extension->type->decode)
809*c8d645caSAndroid Build Coastguard Worker             status = extension->type->decode(stream, extension, tag, wire_type);
810*c8d645caSAndroid Build Coastguard Worker         else
811*c8d645caSAndroid Build Coastguard Worker             status = default_extension_decoder(stream, extension, tag, wire_type);
812*c8d645caSAndroid Build Coastguard Worker 
813*c8d645caSAndroid Build Coastguard Worker         if (!status)
814*c8d645caSAndroid Build Coastguard Worker             return false;
815*c8d645caSAndroid Build Coastguard Worker 
816*c8d645caSAndroid Build Coastguard Worker         extension = extension->next;
817*c8d645caSAndroid Build Coastguard Worker     }
818*c8d645caSAndroid Build Coastguard Worker 
819*c8d645caSAndroid Build Coastguard Worker     return true;
820*c8d645caSAndroid Build Coastguard Worker }
821*c8d645caSAndroid Build Coastguard Worker 
822*c8d645caSAndroid Build Coastguard Worker /* Step through the iterator until an extension field is found or until all
823*c8d645caSAndroid Build Coastguard Worker  * entries have been checked. There can be only one extension field per
824*c8d645caSAndroid Build Coastguard Worker  * message. Returns false if no extension field is found. */
find_extension_field(pb_field_iter_t * iter)825*c8d645caSAndroid Build Coastguard Worker static bool checkreturn find_extension_field(pb_field_iter_t *iter)
826*c8d645caSAndroid Build Coastguard Worker {
827*c8d645caSAndroid Build Coastguard Worker     const pb_field_t *start = iter->pos;
828*c8d645caSAndroid Build Coastguard Worker 
829*c8d645caSAndroid Build Coastguard Worker     do {
830*c8d645caSAndroid Build Coastguard Worker         if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION)
831*c8d645caSAndroid Build Coastguard Worker             return true;
832*c8d645caSAndroid Build Coastguard Worker         (void)pb_field_iter_next(iter);
833*c8d645caSAndroid Build Coastguard Worker     } while (iter->pos != start);
834*c8d645caSAndroid Build Coastguard Worker 
835*c8d645caSAndroid Build Coastguard Worker     return false;
836*c8d645caSAndroid Build Coastguard Worker }
837*c8d645caSAndroid Build Coastguard Worker 
838*c8d645caSAndroid Build Coastguard Worker /* Initialize message fields to default values, recursively */
pb_field_set_to_default(pb_field_iter_t * iter)839*c8d645caSAndroid Build Coastguard Worker static void pb_field_set_to_default(pb_field_iter_t *iter)
840*c8d645caSAndroid Build Coastguard Worker {
841*c8d645caSAndroid Build Coastguard Worker     pb_type_t type;
842*c8d645caSAndroid Build Coastguard Worker     type = iter->pos->type;
843*c8d645caSAndroid Build Coastguard Worker 
844*c8d645caSAndroid Build Coastguard Worker     if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
845*c8d645caSAndroid Build Coastguard Worker     {
846*c8d645caSAndroid Build Coastguard Worker         pb_extension_t *ext = *(pb_extension_t* const *)iter->pData;
847*c8d645caSAndroid Build Coastguard Worker         while (ext != NULL)
848*c8d645caSAndroid Build Coastguard Worker         {
849*c8d645caSAndroid Build Coastguard Worker             pb_field_iter_t ext_iter;
850*c8d645caSAndroid Build Coastguard Worker             ext->found = false;
851*c8d645caSAndroid Build Coastguard Worker             iter_from_extension(&ext_iter, ext);
852*c8d645caSAndroid Build Coastguard Worker             pb_field_set_to_default(&ext_iter);
853*c8d645caSAndroid Build Coastguard Worker             ext = ext->next;
854*c8d645caSAndroid Build Coastguard Worker         }
855*c8d645caSAndroid Build Coastguard Worker     }
856*c8d645caSAndroid Build Coastguard Worker     else if (PB_ATYPE(type) == PB_ATYPE_STATIC)
857*c8d645caSAndroid Build Coastguard Worker     {
858*c8d645caSAndroid Build Coastguard Worker         bool init_data = true;
859*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData)
860*c8d645caSAndroid Build Coastguard Worker         {
861*c8d645caSAndroid Build Coastguard Worker             /* Set has_field to false. Still initialize the optional field
862*c8d645caSAndroid Build Coastguard Worker              * itself also. */
863*c8d645caSAndroid Build Coastguard Worker             *(bool*)iter->pSize = false;
864*c8d645caSAndroid Build Coastguard Worker         }
865*c8d645caSAndroid Build Coastguard Worker         else if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
866*c8d645caSAndroid Build Coastguard Worker                  PB_HTYPE(type) == PB_HTYPE_ONEOF)
867*c8d645caSAndroid Build Coastguard Worker         {
868*c8d645caSAndroid Build Coastguard Worker             /* REPEATED: Set array count to 0, no need to initialize contents.
869*c8d645caSAndroid Build Coastguard Worker                ONEOF: Set which_field to 0. */
870*c8d645caSAndroid Build Coastguard Worker             *(pb_size_t*)iter->pSize = 0;
871*c8d645caSAndroid Build Coastguard Worker             init_data = false;
872*c8d645caSAndroid Build Coastguard Worker         }
873*c8d645caSAndroid Build Coastguard Worker 
874*c8d645caSAndroid Build Coastguard Worker         if (init_data)
875*c8d645caSAndroid Build Coastguard Worker         {
876*c8d645caSAndroid Build Coastguard Worker             if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE)
877*c8d645caSAndroid Build Coastguard Worker             {
878*c8d645caSAndroid Build Coastguard Worker                 /* Initialize submessage to defaults */
879*c8d645caSAndroid Build Coastguard Worker                 pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData);
880*c8d645caSAndroid Build Coastguard Worker             }
881*c8d645caSAndroid Build Coastguard Worker             else if (iter->pos->ptr != NULL)
882*c8d645caSAndroid Build Coastguard Worker             {
883*c8d645caSAndroid Build Coastguard Worker                 /* Initialize to default value */
884*c8d645caSAndroid Build Coastguard Worker                 memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size);
885*c8d645caSAndroid Build Coastguard Worker             }
886*c8d645caSAndroid Build Coastguard Worker             else
887*c8d645caSAndroid Build Coastguard Worker             {
888*c8d645caSAndroid Build Coastguard Worker                 /* Initialize to zeros */
889*c8d645caSAndroid Build Coastguard Worker                 memset(iter->pData, 0, iter->pos->data_size);
890*c8d645caSAndroid Build Coastguard Worker             }
891*c8d645caSAndroid Build Coastguard Worker         }
892*c8d645caSAndroid Build Coastguard Worker     }
893*c8d645caSAndroid Build Coastguard Worker     else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
894*c8d645caSAndroid Build Coastguard Worker     {
895*c8d645caSAndroid Build Coastguard Worker         /* Initialize the pointer to NULL. */
896*c8d645caSAndroid Build Coastguard Worker         *(void**)iter->pData = NULL;
897*c8d645caSAndroid Build Coastguard Worker 
898*c8d645caSAndroid Build Coastguard Worker         /* Initialize array count to 0. */
899*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(type) == PB_HTYPE_REPEATED ||
900*c8d645caSAndroid Build Coastguard Worker             PB_HTYPE(type) == PB_HTYPE_ONEOF)
901*c8d645caSAndroid Build Coastguard Worker         {
902*c8d645caSAndroid Build Coastguard Worker             *(pb_size_t*)iter->pSize = 0;
903*c8d645caSAndroid Build Coastguard Worker         }
904*c8d645caSAndroid Build Coastguard Worker     }
905*c8d645caSAndroid Build Coastguard Worker     else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
906*c8d645caSAndroid Build Coastguard Worker     {
907*c8d645caSAndroid Build Coastguard Worker         /* Don't overwrite callback */
908*c8d645caSAndroid Build Coastguard Worker     }
909*c8d645caSAndroid Build Coastguard Worker }
910*c8d645caSAndroid Build Coastguard Worker 
pb_message_set_to_defaults(const pb_field_t fields[],void * dest_struct)911*c8d645caSAndroid Build Coastguard Worker static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
912*c8d645caSAndroid Build Coastguard Worker {
913*c8d645caSAndroid Build Coastguard Worker     pb_field_iter_t iter;
914*c8d645caSAndroid Build Coastguard Worker 
915*c8d645caSAndroid Build Coastguard Worker     if (!pb_field_iter_begin(&iter, fields, dest_struct))
916*c8d645caSAndroid Build Coastguard Worker         return; /* Empty message type */
917*c8d645caSAndroid Build Coastguard Worker 
918*c8d645caSAndroid Build Coastguard Worker     do
919*c8d645caSAndroid Build Coastguard Worker     {
920*c8d645caSAndroid Build Coastguard Worker         pb_field_set_to_default(&iter);
921*c8d645caSAndroid Build Coastguard Worker     } while (pb_field_iter_next(&iter));
922*c8d645caSAndroid Build Coastguard Worker }
923*c8d645caSAndroid Build Coastguard Worker 
924*c8d645caSAndroid Build Coastguard Worker /*********************
925*c8d645caSAndroid Build Coastguard Worker  * Decode all fields *
926*c8d645caSAndroid Build Coastguard Worker  *********************/
927*c8d645caSAndroid Build Coastguard Worker 
pb_decode_noinit(pb_istream_t * stream,const pb_field_t fields[],void * dest_struct)928*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
929*c8d645caSAndroid Build Coastguard Worker {
930*c8d645caSAndroid Build Coastguard Worker     uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0};
931*c8d645caSAndroid Build Coastguard Worker     const uint32_t allbits = ~(uint32_t)0;
932*c8d645caSAndroid Build Coastguard Worker     uint32_t extension_range_start = 0;
933*c8d645caSAndroid Build Coastguard Worker     pb_field_iter_t iter;
934*c8d645caSAndroid Build Coastguard Worker 
935*c8d645caSAndroid Build Coastguard Worker     /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed
936*c8d645caSAndroid Build Coastguard Worker      * count field. This can only handle _one_ repeated fixed count field that
937*c8d645caSAndroid Build Coastguard Worker      * is unpacked and unordered among other (non repeated fixed count) fields.
938*c8d645caSAndroid Build Coastguard Worker      */
939*c8d645caSAndroid Build Coastguard Worker     const pb_field_t *fixed_count_field = NULL;
940*c8d645caSAndroid Build Coastguard Worker     pb_size_t fixed_count_size = 0;
941*c8d645caSAndroid Build Coastguard Worker 
942*c8d645caSAndroid Build Coastguard Worker     /* Return value ignored, as empty message types will be correctly handled by
943*c8d645caSAndroid Build Coastguard Worker      * pb_field_iter_find() anyway. */
944*c8d645caSAndroid Build Coastguard Worker     (void)pb_field_iter_begin(&iter, fields, dest_struct);
945*c8d645caSAndroid Build Coastguard Worker 
946*c8d645caSAndroid Build Coastguard Worker     while (stream->bytes_left)
947*c8d645caSAndroid Build Coastguard Worker     {
948*c8d645caSAndroid Build Coastguard Worker         uint32_t tag;
949*c8d645caSAndroid Build Coastguard Worker         pb_wire_type_t wire_type;
950*c8d645caSAndroid Build Coastguard Worker         bool eof;
951*c8d645caSAndroid Build Coastguard Worker 
952*c8d645caSAndroid Build Coastguard Worker         if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
953*c8d645caSAndroid Build Coastguard Worker         {
954*c8d645caSAndroid Build Coastguard Worker             if (eof)
955*c8d645caSAndroid Build Coastguard Worker                 break;
956*c8d645caSAndroid Build Coastguard Worker             else
957*c8d645caSAndroid Build Coastguard Worker                 return false;
958*c8d645caSAndroid Build Coastguard Worker         }
959*c8d645caSAndroid Build Coastguard Worker 
960*c8d645caSAndroid Build Coastguard Worker         if (!pb_field_iter_find(&iter, tag))
961*c8d645caSAndroid Build Coastguard Worker         {
962*c8d645caSAndroid Build Coastguard Worker             /* No match found, check if it matches an extension. */
963*c8d645caSAndroid Build Coastguard Worker             if (tag >= extension_range_start)
964*c8d645caSAndroid Build Coastguard Worker             {
965*c8d645caSAndroid Build Coastguard Worker                 if (!find_extension_field(&iter))
966*c8d645caSAndroid Build Coastguard Worker                     extension_range_start = (uint32_t)-1;
967*c8d645caSAndroid Build Coastguard Worker                 else
968*c8d645caSAndroid Build Coastguard Worker                     extension_range_start = iter.pos->tag;
969*c8d645caSAndroid Build Coastguard Worker 
970*c8d645caSAndroid Build Coastguard Worker                 if (tag >= extension_range_start)
971*c8d645caSAndroid Build Coastguard Worker                 {
972*c8d645caSAndroid Build Coastguard Worker                     size_t pos = stream->bytes_left;
973*c8d645caSAndroid Build Coastguard Worker 
974*c8d645caSAndroid Build Coastguard Worker                     if (!decode_extension(stream, tag, wire_type, &iter))
975*c8d645caSAndroid Build Coastguard Worker                         return false;
976*c8d645caSAndroid Build Coastguard Worker 
977*c8d645caSAndroid Build Coastguard Worker                     if (pos != stream->bytes_left)
978*c8d645caSAndroid Build Coastguard Worker                     {
979*c8d645caSAndroid Build Coastguard Worker                         /* The field was handled */
980*c8d645caSAndroid Build Coastguard Worker                         continue;
981*c8d645caSAndroid Build Coastguard Worker                     }
982*c8d645caSAndroid Build Coastguard Worker                 }
983*c8d645caSAndroid Build Coastguard Worker             }
984*c8d645caSAndroid Build Coastguard Worker 
985*c8d645caSAndroid Build Coastguard Worker             /* No match found, skip data */
986*c8d645caSAndroid Build Coastguard Worker             if (!pb_skip_field(stream, wire_type))
987*c8d645caSAndroid Build Coastguard Worker                 return false;
988*c8d645caSAndroid Build Coastguard Worker             continue;
989*c8d645caSAndroid Build Coastguard Worker         }
990*c8d645caSAndroid Build Coastguard Worker 
991*c8d645caSAndroid Build Coastguard Worker         /* If a repeated fixed count field was found, get size from
992*c8d645caSAndroid Build Coastguard Worker          * 'fixed_count_field' as there is no counter contained in the struct.
993*c8d645caSAndroid Build Coastguard Worker          */
994*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED
995*c8d645caSAndroid Build Coastguard Worker             && iter.pSize == iter.pData)
996*c8d645caSAndroid Build Coastguard Worker         {
997*c8d645caSAndroid Build Coastguard Worker             if (fixed_count_field != iter.pos) {
998*c8d645caSAndroid Build Coastguard Worker                 /* If the new fixed count field does not match the previous one,
999*c8d645caSAndroid Build Coastguard Worker                  * check that the previous one is NULL or that it finished
1000*c8d645caSAndroid Build Coastguard Worker                  * receiving all the expected data.
1001*c8d645caSAndroid Build Coastguard Worker                  */
1002*c8d645caSAndroid Build Coastguard Worker                 if (fixed_count_field != NULL &&
1003*c8d645caSAndroid Build Coastguard Worker                     fixed_count_size != fixed_count_field->array_size)
1004*c8d645caSAndroid Build Coastguard Worker                 {
1005*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "wrong size for fixed count field");
1006*c8d645caSAndroid Build Coastguard Worker                 }
1007*c8d645caSAndroid Build Coastguard Worker 
1008*c8d645caSAndroid Build Coastguard Worker                 fixed_count_field = iter.pos;
1009*c8d645caSAndroid Build Coastguard Worker                 fixed_count_size = 0;
1010*c8d645caSAndroid Build Coastguard Worker             }
1011*c8d645caSAndroid Build Coastguard Worker 
1012*c8d645caSAndroid Build Coastguard Worker             iter.pSize = &fixed_count_size;
1013*c8d645caSAndroid Build Coastguard Worker         }
1014*c8d645caSAndroid Build Coastguard Worker 
1015*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED
1016*c8d645caSAndroid Build Coastguard Worker             && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
1017*c8d645caSAndroid Build Coastguard Worker         {
1018*c8d645caSAndroid Build Coastguard Worker             uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31));
1019*c8d645caSAndroid Build Coastguard Worker             fields_seen[iter.required_field_index >> 5] |= tmp;
1020*c8d645caSAndroid Build Coastguard Worker         }
1021*c8d645caSAndroid Build Coastguard Worker 
1022*c8d645caSAndroid Build Coastguard Worker         if (!decode_field(stream, wire_type, &iter))
1023*c8d645caSAndroid Build Coastguard Worker             return false;
1024*c8d645caSAndroid Build Coastguard Worker     }
1025*c8d645caSAndroid Build Coastguard Worker 
1026*c8d645caSAndroid Build Coastguard Worker     /* Check that all elements of the last decoded fixed count field were present. */
1027*c8d645caSAndroid Build Coastguard Worker     if (fixed_count_field != NULL &&
1028*c8d645caSAndroid Build Coastguard Worker         fixed_count_size != fixed_count_field->array_size)
1029*c8d645caSAndroid Build Coastguard Worker     {
1030*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "wrong size for fixed count field");
1031*c8d645caSAndroid Build Coastguard Worker     }
1032*c8d645caSAndroid Build Coastguard Worker 
1033*c8d645caSAndroid Build Coastguard Worker     /* Check that all required fields were present. */
1034*c8d645caSAndroid Build Coastguard Worker     {
1035*c8d645caSAndroid Build Coastguard Worker         /* First figure out the number of required fields by
1036*c8d645caSAndroid Build Coastguard Worker          * seeking to the end of the field array. Usually we
1037*c8d645caSAndroid Build Coastguard Worker          * are already close to end after decoding.
1038*c8d645caSAndroid Build Coastguard Worker          */
1039*c8d645caSAndroid Build Coastguard Worker         unsigned req_field_count;
1040*c8d645caSAndroid Build Coastguard Worker         pb_type_t last_type;
1041*c8d645caSAndroid Build Coastguard Worker         unsigned i;
1042*c8d645caSAndroid Build Coastguard Worker         do {
1043*c8d645caSAndroid Build Coastguard Worker             req_field_count = iter.required_field_index;
1044*c8d645caSAndroid Build Coastguard Worker             last_type = iter.pos->type;
1045*c8d645caSAndroid Build Coastguard Worker         } while (pb_field_iter_next(&iter));
1046*c8d645caSAndroid Build Coastguard Worker 
1047*c8d645caSAndroid Build Coastguard Worker         /* Fixup if last field was also required. */
1048*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0)
1049*c8d645caSAndroid Build Coastguard Worker             req_field_count++;
1050*c8d645caSAndroid Build Coastguard Worker 
1051*c8d645caSAndroid Build Coastguard Worker         if (req_field_count > PB_MAX_REQUIRED_FIELDS)
1052*c8d645caSAndroid Build Coastguard Worker             req_field_count = PB_MAX_REQUIRED_FIELDS;
1053*c8d645caSAndroid Build Coastguard Worker 
1054*c8d645caSAndroid Build Coastguard Worker         if (req_field_count > 0)
1055*c8d645caSAndroid Build Coastguard Worker         {
1056*c8d645caSAndroid Build Coastguard Worker             /* Check the whole words */
1057*c8d645caSAndroid Build Coastguard Worker             for (i = 0; i < (req_field_count >> 5); i++)
1058*c8d645caSAndroid Build Coastguard Worker             {
1059*c8d645caSAndroid Build Coastguard Worker                 if (fields_seen[i] != allbits)
1060*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "missing required field");
1061*c8d645caSAndroid Build Coastguard Worker             }
1062*c8d645caSAndroid Build Coastguard Worker 
1063*c8d645caSAndroid Build Coastguard Worker             /* Check the remaining bits (if any) */
1064*c8d645caSAndroid Build Coastguard Worker             if ((req_field_count & 31) != 0)
1065*c8d645caSAndroid Build Coastguard Worker             {
1066*c8d645caSAndroid Build Coastguard Worker                 if (fields_seen[req_field_count >> 5] !=
1067*c8d645caSAndroid Build Coastguard Worker                     (allbits >> (32 - (req_field_count & 31))))
1068*c8d645caSAndroid Build Coastguard Worker                 {
1069*c8d645caSAndroid Build Coastguard Worker                     PB_RETURN_ERROR(stream, "missing required field");
1070*c8d645caSAndroid Build Coastguard Worker                 }
1071*c8d645caSAndroid Build Coastguard Worker             }
1072*c8d645caSAndroid Build Coastguard Worker         }
1073*c8d645caSAndroid Build Coastguard Worker     }
1074*c8d645caSAndroid Build Coastguard Worker 
1075*c8d645caSAndroid Build Coastguard Worker     return true;
1076*c8d645caSAndroid Build Coastguard Worker }
1077*c8d645caSAndroid Build Coastguard Worker 
pb_decode(pb_istream_t * stream,const pb_field_t fields[],void * dest_struct)1078*c8d645caSAndroid Build Coastguard Worker bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
1079*c8d645caSAndroid Build Coastguard Worker {
1080*c8d645caSAndroid Build Coastguard Worker     bool status;
1081*c8d645caSAndroid Build Coastguard Worker     pb_message_set_to_defaults(fields, dest_struct);
1082*c8d645caSAndroid Build Coastguard Worker     status = pb_decode_noinit(stream, fields, dest_struct);
1083*c8d645caSAndroid Build Coastguard Worker 
1084*c8d645caSAndroid Build Coastguard Worker #ifdef PB_ENABLE_MALLOC
1085*c8d645caSAndroid Build Coastguard Worker     if (!status)
1086*c8d645caSAndroid Build Coastguard Worker         pb_release(fields, dest_struct);
1087*c8d645caSAndroid Build Coastguard Worker #endif
1088*c8d645caSAndroid Build Coastguard Worker 
1089*c8d645caSAndroid Build Coastguard Worker     return status;
1090*c8d645caSAndroid Build Coastguard Worker }
1091*c8d645caSAndroid Build Coastguard Worker 
pb_decode_delimited_noinit(pb_istream_t * stream,const pb_field_t fields[],void * dest_struct)1092*c8d645caSAndroid Build Coastguard Worker bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
1093*c8d645caSAndroid Build Coastguard Worker {
1094*c8d645caSAndroid Build Coastguard Worker     pb_istream_t substream;
1095*c8d645caSAndroid Build Coastguard Worker     bool status;
1096*c8d645caSAndroid Build Coastguard Worker 
1097*c8d645caSAndroid Build Coastguard Worker     if (!pb_make_string_substream(stream, &substream))
1098*c8d645caSAndroid Build Coastguard Worker         return false;
1099*c8d645caSAndroid Build Coastguard Worker 
1100*c8d645caSAndroid Build Coastguard Worker     status = pb_decode_noinit(&substream, fields, dest_struct);
1101*c8d645caSAndroid Build Coastguard Worker 
1102*c8d645caSAndroid Build Coastguard Worker     if (!pb_close_string_substream(stream, &substream))
1103*c8d645caSAndroid Build Coastguard Worker         return false;
1104*c8d645caSAndroid Build Coastguard Worker     return status;
1105*c8d645caSAndroid Build Coastguard Worker }
1106*c8d645caSAndroid Build Coastguard Worker 
pb_decode_delimited(pb_istream_t * stream,const pb_field_t fields[],void * dest_struct)1107*c8d645caSAndroid Build Coastguard Worker bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
1108*c8d645caSAndroid Build Coastguard Worker {
1109*c8d645caSAndroid Build Coastguard Worker     pb_istream_t substream;
1110*c8d645caSAndroid Build Coastguard Worker     bool status;
1111*c8d645caSAndroid Build Coastguard Worker 
1112*c8d645caSAndroid Build Coastguard Worker     if (!pb_make_string_substream(stream, &substream))
1113*c8d645caSAndroid Build Coastguard Worker         return false;
1114*c8d645caSAndroid Build Coastguard Worker 
1115*c8d645caSAndroid Build Coastguard Worker     status = pb_decode(&substream, fields, dest_struct);
1116*c8d645caSAndroid Build Coastguard Worker 
1117*c8d645caSAndroid Build Coastguard Worker     if (!pb_close_string_substream(stream, &substream))
1118*c8d645caSAndroid Build Coastguard Worker         return false;
1119*c8d645caSAndroid Build Coastguard Worker     return status;
1120*c8d645caSAndroid Build Coastguard Worker }
1121*c8d645caSAndroid Build Coastguard Worker 
pb_decode_nullterminated(pb_istream_t * stream,const pb_field_t fields[],void * dest_struct)1122*c8d645caSAndroid Build Coastguard Worker bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
1123*c8d645caSAndroid Build Coastguard Worker {
1124*c8d645caSAndroid Build Coastguard Worker     /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */
1125*c8d645caSAndroid Build Coastguard Worker     return pb_decode(stream, fields, dest_struct);
1126*c8d645caSAndroid Build Coastguard Worker }
1127*c8d645caSAndroid Build Coastguard Worker 
1128*c8d645caSAndroid Build Coastguard Worker #ifdef PB_ENABLE_MALLOC
1129*c8d645caSAndroid Build Coastguard Worker /* Given an oneof field, if there has already been a field inside this oneof,
1130*c8d645caSAndroid Build Coastguard Worker  * release it before overwriting with a different one. */
pb_release_union_field(pb_istream_t * stream,pb_field_iter_t * iter)1131*c8d645caSAndroid Build Coastguard Worker static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter)
1132*c8d645caSAndroid Build Coastguard Worker {
1133*c8d645caSAndroid Build Coastguard Worker     pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */
1134*c8d645caSAndroid Build Coastguard Worker     pb_size_t new_tag = iter->pos->tag; /* New which_ value */
1135*c8d645caSAndroid Build Coastguard Worker 
1136*c8d645caSAndroid Build Coastguard Worker     if (old_tag == 0)
1137*c8d645caSAndroid Build Coastguard Worker         return true; /* Ok, no old data in union */
1138*c8d645caSAndroid Build Coastguard Worker 
1139*c8d645caSAndroid Build Coastguard Worker     if (old_tag == new_tag)
1140*c8d645caSAndroid Build Coastguard Worker         return true; /* Ok, old data is of same type => merge */
1141*c8d645caSAndroid Build Coastguard Worker 
1142*c8d645caSAndroid Build Coastguard Worker     /* Release old data. The find can fail if the message struct contains
1143*c8d645caSAndroid Build Coastguard Worker      * invalid data. */
1144*c8d645caSAndroid Build Coastguard Worker     if (!pb_field_iter_find(iter, old_tag))
1145*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid union tag");
1146*c8d645caSAndroid Build Coastguard Worker 
1147*c8d645caSAndroid Build Coastguard Worker     pb_release_single_field(iter);
1148*c8d645caSAndroid Build Coastguard Worker 
1149*c8d645caSAndroid Build Coastguard Worker     /* Restore iterator to where it should be.
1150*c8d645caSAndroid Build Coastguard Worker      * This shouldn't fail unless the pb_field_t structure is corrupted. */
1151*c8d645caSAndroid Build Coastguard Worker     if (!pb_field_iter_find(iter, new_tag))
1152*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "iterator error");
1153*c8d645caSAndroid Build Coastguard Worker 
1154*c8d645caSAndroid Build Coastguard Worker     if (PB_ATYPE(iter->pos->type) == PB_ATYPE_POINTER)
1155*c8d645caSAndroid Build Coastguard Worker     {
1156*c8d645caSAndroid Build Coastguard Worker         /* Initialize the pointer to NULL to make sure it is valid
1157*c8d645caSAndroid Build Coastguard Worker          * even in case of error return. */
1158*c8d645caSAndroid Build Coastguard Worker         *(void**)iter->pData = NULL;
1159*c8d645caSAndroid Build Coastguard Worker     }
1160*c8d645caSAndroid Build Coastguard Worker 
1161*c8d645caSAndroid Build Coastguard Worker     return true;
1162*c8d645caSAndroid Build Coastguard Worker }
1163*c8d645caSAndroid Build Coastguard Worker 
pb_release_single_field(const pb_field_iter_t * iter)1164*c8d645caSAndroid Build Coastguard Worker static void pb_release_single_field(const pb_field_iter_t *iter)
1165*c8d645caSAndroid Build Coastguard Worker {
1166*c8d645caSAndroid Build Coastguard Worker     pb_type_t type;
1167*c8d645caSAndroid Build Coastguard Worker     type = iter->pos->type;
1168*c8d645caSAndroid Build Coastguard Worker 
1169*c8d645caSAndroid Build Coastguard Worker     if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
1170*c8d645caSAndroid Build Coastguard Worker     {
1171*c8d645caSAndroid Build Coastguard Worker         if (*(pb_size_t*)iter->pSize != iter->pos->tag)
1172*c8d645caSAndroid Build Coastguard Worker             return; /* This is not the current field in the union */
1173*c8d645caSAndroid Build Coastguard Worker     }
1174*c8d645caSAndroid Build Coastguard Worker 
1175*c8d645caSAndroid Build Coastguard Worker     /* Release anything contained inside an extension or submsg.
1176*c8d645caSAndroid Build Coastguard Worker      * This has to be done even if the submsg itself is statically
1177*c8d645caSAndroid Build Coastguard Worker      * allocated. */
1178*c8d645caSAndroid Build Coastguard Worker     if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
1179*c8d645caSAndroid Build Coastguard Worker     {
1180*c8d645caSAndroid Build Coastguard Worker         /* Release fields from all extensions in the linked list */
1181*c8d645caSAndroid Build Coastguard Worker         pb_extension_t *ext = *(pb_extension_t**)iter->pData;
1182*c8d645caSAndroid Build Coastguard Worker         while (ext != NULL)
1183*c8d645caSAndroid Build Coastguard Worker         {
1184*c8d645caSAndroid Build Coastguard Worker             pb_field_iter_t ext_iter;
1185*c8d645caSAndroid Build Coastguard Worker             iter_from_extension(&ext_iter, ext);
1186*c8d645caSAndroid Build Coastguard Worker             pb_release_single_field(&ext_iter);
1187*c8d645caSAndroid Build Coastguard Worker             ext = ext->next;
1188*c8d645caSAndroid Build Coastguard Worker         }
1189*c8d645caSAndroid Build Coastguard Worker     }
1190*c8d645caSAndroid Build Coastguard Worker     else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && PB_ATYPE(type) != PB_ATYPE_CALLBACK)
1191*c8d645caSAndroid Build Coastguard Worker     {
1192*c8d645caSAndroid Build Coastguard Worker         /* Release fields in submessage or submsg array */
1193*c8d645caSAndroid Build Coastguard Worker         void *pItem = iter->pData;
1194*c8d645caSAndroid Build Coastguard Worker         pb_size_t count = 1;
1195*c8d645caSAndroid Build Coastguard Worker 
1196*c8d645caSAndroid Build Coastguard Worker         if (PB_ATYPE(type) == PB_ATYPE_POINTER)
1197*c8d645caSAndroid Build Coastguard Worker         {
1198*c8d645caSAndroid Build Coastguard Worker             pItem = *(void**)iter->pData;
1199*c8d645caSAndroid Build Coastguard Worker         }
1200*c8d645caSAndroid Build Coastguard Worker 
1201*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
1202*c8d645caSAndroid Build Coastguard Worker         {
1203*c8d645caSAndroid Build Coastguard Worker             if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) {
1204*c8d645caSAndroid Build Coastguard Worker                 /* No _count field so use size of the array */
1205*c8d645caSAndroid Build Coastguard Worker                 count = iter->pos->array_size;
1206*c8d645caSAndroid Build Coastguard Worker             } else {
1207*c8d645caSAndroid Build Coastguard Worker                 count = *(pb_size_t*)iter->pSize;
1208*c8d645caSAndroid Build Coastguard Worker             }
1209*c8d645caSAndroid Build Coastguard Worker 
1210*c8d645caSAndroid Build Coastguard Worker             if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size)
1211*c8d645caSAndroid Build Coastguard Worker             {
1212*c8d645caSAndroid Build Coastguard Worker                 /* Protect against corrupted _count fields */
1213*c8d645caSAndroid Build Coastguard Worker                 count = iter->pos->array_size;
1214*c8d645caSAndroid Build Coastguard Worker             }
1215*c8d645caSAndroid Build Coastguard Worker         }
1216*c8d645caSAndroid Build Coastguard Worker 
1217*c8d645caSAndroid Build Coastguard Worker         if (pItem)
1218*c8d645caSAndroid Build Coastguard Worker         {
1219*c8d645caSAndroid Build Coastguard Worker             while (count--)
1220*c8d645caSAndroid Build Coastguard Worker             {
1221*c8d645caSAndroid Build Coastguard Worker                 pb_release((const pb_field_t*)iter->pos->ptr, pItem);
1222*c8d645caSAndroid Build Coastguard Worker                 pItem = (char*)pItem + iter->pos->data_size;
1223*c8d645caSAndroid Build Coastguard Worker             }
1224*c8d645caSAndroid Build Coastguard Worker         }
1225*c8d645caSAndroid Build Coastguard Worker     }
1226*c8d645caSAndroid Build Coastguard Worker 
1227*c8d645caSAndroid Build Coastguard Worker     if (PB_ATYPE(type) == PB_ATYPE_POINTER)
1228*c8d645caSAndroid Build Coastguard Worker     {
1229*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(type) == PB_HTYPE_REPEATED &&
1230*c8d645caSAndroid Build Coastguard Worker             (PB_LTYPE(type) == PB_LTYPE_STRING ||
1231*c8d645caSAndroid Build Coastguard Worker              PB_LTYPE(type) == PB_LTYPE_BYTES))
1232*c8d645caSAndroid Build Coastguard Worker         {
1233*c8d645caSAndroid Build Coastguard Worker             /* Release entries in repeated string or bytes array */
1234*c8d645caSAndroid Build Coastguard Worker             void **pItem = *(void***)iter->pData;
1235*c8d645caSAndroid Build Coastguard Worker             pb_size_t count = *(pb_size_t*)iter->pSize;
1236*c8d645caSAndroid Build Coastguard Worker             while (count--)
1237*c8d645caSAndroid Build Coastguard Worker             {
1238*c8d645caSAndroid Build Coastguard Worker                 pb_free(*pItem);
1239*c8d645caSAndroid Build Coastguard Worker                 *pItem++ = NULL;
1240*c8d645caSAndroid Build Coastguard Worker             }
1241*c8d645caSAndroid Build Coastguard Worker         }
1242*c8d645caSAndroid Build Coastguard Worker 
1243*c8d645caSAndroid Build Coastguard Worker         if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
1244*c8d645caSAndroid Build Coastguard Worker         {
1245*c8d645caSAndroid Build Coastguard Worker             /* We are going to release the array, so set the size to 0 */
1246*c8d645caSAndroid Build Coastguard Worker             *(pb_size_t*)iter->pSize = 0;
1247*c8d645caSAndroid Build Coastguard Worker         }
1248*c8d645caSAndroid Build Coastguard Worker 
1249*c8d645caSAndroid Build Coastguard Worker         /* Release main item */
1250*c8d645caSAndroid Build Coastguard Worker         pb_free(*(void**)iter->pData);
1251*c8d645caSAndroid Build Coastguard Worker         *(void**)iter->pData = NULL;
1252*c8d645caSAndroid Build Coastguard Worker     }
1253*c8d645caSAndroid Build Coastguard Worker }
1254*c8d645caSAndroid Build Coastguard Worker 
pb_release(const pb_field_t fields[],void * dest_struct)1255*c8d645caSAndroid Build Coastguard Worker void pb_release(const pb_field_t fields[], void *dest_struct)
1256*c8d645caSAndroid Build Coastguard Worker {
1257*c8d645caSAndroid Build Coastguard Worker     pb_field_iter_t iter;
1258*c8d645caSAndroid Build Coastguard Worker 
1259*c8d645caSAndroid Build Coastguard Worker     if (!dest_struct)
1260*c8d645caSAndroid Build Coastguard Worker         return; /* Ignore NULL pointers, similar to free() */
1261*c8d645caSAndroid Build Coastguard Worker 
1262*c8d645caSAndroid Build Coastguard Worker     if (!pb_field_iter_begin(&iter, fields, dest_struct))
1263*c8d645caSAndroid Build Coastguard Worker         return; /* Empty message type */
1264*c8d645caSAndroid Build Coastguard Worker 
1265*c8d645caSAndroid Build Coastguard Worker     do
1266*c8d645caSAndroid Build Coastguard Worker     {
1267*c8d645caSAndroid Build Coastguard Worker         pb_release_single_field(&iter);
1268*c8d645caSAndroid Build Coastguard Worker     } while (pb_field_iter_next(&iter));
1269*c8d645caSAndroid Build Coastguard Worker }
1270*c8d645caSAndroid Build Coastguard Worker #endif
1271*c8d645caSAndroid Build Coastguard Worker 
1272*c8d645caSAndroid Build Coastguard Worker /* Field decoders */
1273*c8d645caSAndroid Build Coastguard Worker 
pb_decode_bool(pb_istream_t * stream,bool * dest)1274*c8d645caSAndroid Build Coastguard Worker bool pb_decode_bool(pb_istream_t *stream, bool *dest)
1275*c8d645caSAndroid Build Coastguard Worker {
1276*c8d645caSAndroid Build Coastguard Worker     return pb_dec_bool(stream, NULL, (void*)dest);
1277*c8d645caSAndroid Build Coastguard Worker }
1278*c8d645caSAndroid Build Coastguard Worker 
pb_decode_svarint(pb_istream_t * stream,pb_int64_t * dest)1279*c8d645caSAndroid Build Coastguard Worker bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest)
1280*c8d645caSAndroid Build Coastguard Worker {
1281*c8d645caSAndroid Build Coastguard Worker     pb_uint64_t value;
1282*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint(stream, &value))
1283*c8d645caSAndroid Build Coastguard Worker         return false;
1284*c8d645caSAndroid Build Coastguard Worker 
1285*c8d645caSAndroid Build Coastguard Worker     if (value & 1)
1286*c8d645caSAndroid Build Coastguard Worker         *dest = (pb_int64_t)(~(value >> 1));
1287*c8d645caSAndroid Build Coastguard Worker     else
1288*c8d645caSAndroid Build Coastguard Worker         *dest = (pb_int64_t)(value >> 1);
1289*c8d645caSAndroid Build Coastguard Worker 
1290*c8d645caSAndroid Build Coastguard Worker     return true;
1291*c8d645caSAndroid Build Coastguard Worker }
1292*c8d645caSAndroid Build Coastguard Worker 
pb_decode_fixed32(pb_istream_t * stream,void * dest)1293*c8d645caSAndroid Build Coastguard Worker bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
1294*c8d645caSAndroid Build Coastguard Worker {
1295*c8d645caSAndroid Build Coastguard Worker     pb_byte_t bytes[4];
1296*c8d645caSAndroid Build Coastguard Worker 
1297*c8d645caSAndroid Build Coastguard Worker     if (!pb_read(stream, bytes, 4))
1298*c8d645caSAndroid Build Coastguard Worker         return false;
1299*c8d645caSAndroid Build Coastguard Worker 
1300*c8d645caSAndroid Build Coastguard Worker     *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) |
1301*c8d645caSAndroid Build Coastguard Worker                        ((uint32_t)bytes[1] << 8) |
1302*c8d645caSAndroid Build Coastguard Worker                        ((uint32_t)bytes[2] << 16) |
1303*c8d645caSAndroid Build Coastguard Worker                        ((uint32_t)bytes[3] << 24);
1304*c8d645caSAndroid Build Coastguard Worker     return true;
1305*c8d645caSAndroid Build Coastguard Worker }
1306*c8d645caSAndroid Build Coastguard Worker 
1307*c8d645caSAndroid Build Coastguard Worker #ifndef PB_WITHOUT_64BIT
pb_decode_fixed64(pb_istream_t * stream,void * dest)1308*c8d645caSAndroid Build Coastguard Worker bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
1309*c8d645caSAndroid Build Coastguard Worker {
1310*c8d645caSAndroid Build Coastguard Worker     pb_byte_t bytes[8];
1311*c8d645caSAndroid Build Coastguard Worker 
1312*c8d645caSAndroid Build Coastguard Worker     if (!pb_read(stream, bytes, 8))
1313*c8d645caSAndroid Build Coastguard Worker         return false;
1314*c8d645caSAndroid Build Coastguard Worker 
1315*c8d645caSAndroid Build Coastguard Worker     *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) |
1316*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[1] << 8) |
1317*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[2] << 16) |
1318*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[3] << 24) |
1319*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[4] << 32) |
1320*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[5] << 40) |
1321*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[6] << 48) |
1322*c8d645caSAndroid Build Coastguard Worker                        ((uint64_t)bytes[7] << 56);
1323*c8d645caSAndroid Build Coastguard Worker 
1324*c8d645caSAndroid Build Coastguard Worker     return true;
1325*c8d645caSAndroid Build Coastguard Worker }
1326*c8d645caSAndroid Build Coastguard Worker #endif
1327*c8d645caSAndroid Build Coastguard Worker 
pb_dec_bool(pb_istream_t * stream,const pb_field_t * field,void * dest)1328*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_t *field, void *dest)
1329*c8d645caSAndroid Build Coastguard Worker {
1330*c8d645caSAndroid Build Coastguard Worker     uint32_t value;
1331*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(field);
1332*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &value))
1333*c8d645caSAndroid Build Coastguard Worker         return false;
1334*c8d645caSAndroid Build Coastguard Worker 
1335*c8d645caSAndroid Build Coastguard Worker     *(bool*)dest = (value != 0);
1336*c8d645caSAndroid Build Coastguard Worker     return true;
1337*c8d645caSAndroid Build Coastguard Worker }
1338*c8d645caSAndroid Build Coastguard Worker 
pb_dec_varint(pb_istream_t * stream,const pb_field_t * field,void * dest)1339*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
1340*c8d645caSAndroid Build Coastguard Worker {
1341*c8d645caSAndroid Build Coastguard Worker     pb_uint64_t value;
1342*c8d645caSAndroid Build Coastguard Worker     pb_int64_t svalue;
1343*c8d645caSAndroid Build Coastguard Worker     pb_int64_t clamped;
1344*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint(stream, &value))
1345*c8d645caSAndroid Build Coastguard Worker         return false;
1346*c8d645caSAndroid Build Coastguard Worker 
1347*c8d645caSAndroid Build Coastguard Worker     /* See issue 97: Google's C++ protobuf allows negative varint values to
1348*c8d645caSAndroid Build Coastguard Worker      * be cast as int32_t, instead of the int64_t that should be used when
1349*c8d645caSAndroid Build Coastguard Worker      * encoding. Previous nanopb versions had a bug in encoding. In order to
1350*c8d645caSAndroid Build Coastguard Worker      * not break decoding of such messages, we cast <=32 bit fields to
1351*c8d645caSAndroid Build Coastguard Worker      * int32_t first to get the sign correct.
1352*c8d645caSAndroid Build Coastguard Worker      */
1353*c8d645caSAndroid Build Coastguard Worker     if (field->data_size == sizeof(pb_int64_t))
1354*c8d645caSAndroid Build Coastguard Worker         svalue = (pb_int64_t)value;
1355*c8d645caSAndroid Build Coastguard Worker     else
1356*c8d645caSAndroid Build Coastguard Worker         svalue = (int32_t)value;
1357*c8d645caSAndroid Build Coastguard Worker 
1358*c8d645caSAndroid Build Coastguard Worker     /* Cast to the proper field size, while checking for overflows */
1359*c8d645caSAndroid Build Coastguard Worker     if (field->data_size == sizeof(pb_int64_t))
1360*c8d645caSAndroid Build Coastguard Worker         clamped = *(pb_int64_t*)dest = svalue;
1361*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int32_t))
1362*c8d645caSAndroid Build Coastguard Worker         clamped = *(int32_t*)dest = (int32_t)svalue;
1363*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int_least16_t))
1364*c8d645caSAndroid Build Coastguard Worker         clamped = *(int_least16_t*)dest = (int_least16_t)svalue;
1365*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int_least8_t))
1366*c8d645caSAndroid Build Coastguard Worker         clamped = *(int_least8_t*)dest = (int_least8_t)svalue;
1367*c8d645caSAndroid Build Coastguard Worker     else
1368*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid data_size");
1369*c8d645caSAndroid Build Coastguard Worker 
1370*c8d645caSAndroid Build Coastguard Worker     if (clamped != svalue)
1371*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "integer too large");
1372*c8d645caSAndroid Build Coastguard Worker 
1373*c8d645caSAndroid Build Coastguard Worker     return true;
1374*c8d645caSAndroid Build Coastguard Worker }
1375*c8d645caSAndroid Build Coastguard Worker 
pb_dec_uvarint(pb_istream_t * stream,const pb_field_t * field,void * dest)1376*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
1377*c8d645caSAndroid Build Coastguard Worker {
1378*c8d645caSAndroid Build Coastguard Worker     pb_uint64_t value, clamped;
1379*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint(stream, &value))
1380*c8d645caSAndroid Build Coastguard Worker         return false;
1381*c8d645caSAndroid Build Coastguard Worker 
1382*c8d645caSAndroid Build Coastguard Worker     /* Cast to the proper field size, while checking for overflows */
1383*c8d645caSAndroid Build Coastguard Worker     if (field->data_size == sizeof(pb_uint64_t))
1384*c8d645caSAndroid Build Coastguard Worker         clamped = *(pb_uint64_t*)dest = value;
1385*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(uint32_t))
1386*c8d645caSAndroid Build Coastguard Worker         clamped = *(uint32_t*)dest = (uint32_t)value;
1387*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(uint_least16_t))
1388*c8d645caSAndroid Build Coastguard Worker         clamped = *(uint_least16_t*)dest = (uint_least16_t)value;
1389*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(uint_least8_t))
1390*c8d645caSAndroid Build Coastguard Worker         clamped = *(uint_least8_t*)dest = (uint_least8_t)value;
1391*c8d645caSAndroid Build Coastguard Worker     else
1392*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid data_size");
1393*c8d645caSAndroid Build Coastguard Worker 
1394*c8d645caSAndroid Build Coastguard Worker     if (clamped != value)
1395*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "integer too large");
1396*c8d645caSAndroid Build Coastguard Worker 
1397*c8d645caSAndroid Build Coastguard Worker     return true;
1398*c8d645caSAndroid Build Coastguard Worker }
1399*c8d645caSAndroid Build Coastguard Worker 
pb_dec_svarint(pb_istream_t * stream,const pb_field_t * field,void * dest)1400*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
1401*c8d645caSAndroid Build Coastguard Worker {
1402*c8d645caSAndroid Build Coastguard Worker     pb_int64_t value, clamped;
1403*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_svarint(stream, &value))
1404*c8d645caSAndroid Build Coastguard Worker         return false;
1405*c8d645caSAndroid Build Coastguard Worker 
1406*c8d645caSAndroid Build Coastguard Worker     /* Cast to the proper field size, while checking for overflows */
1407*c8d645caSAndroid Build Coastguard Worker     if (field->data_size == sizeof(pb_int64_t))
1408*c8d645caSAndroid Build Coastguard Worker         clamped = *(pb_int64_t*)dest = value;
1409*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int32_t))
1410*c8d645caSAndroid Build Coastguard Worker         clamped = *(int32_t*)dest = (int32_t)value;
1411*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int_least16_t))
1412*c8d645caSAndroid Build Coastguard Worker         clamped = *(int_least16_t*)dest = (int_least16_t)value;
1413*c8d645caSAndroid Build Coastguard Worker     else if (field->data_size == sizeof(int_least8_t))
1414*c8d645caSAndroid Build Coastguard Worker         clamped = *(int_least8_t*)dest = (int_least8_t)value;
1415*c8d645caSAndroid Build Coastguard Worker     else
1416*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid data_size");
1417*c8d645caSAndroid Build Coastguard Worker 
1418*c8d645caSAndroid Build Coastguard Worker     if (clamped != value)
1419*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "integer too large");
1420*c8d645caSAndroid Build Coastguard Worker 
1421*c8d645caSAndroid Build Coastguard Worker     return true;
1422*c8d645caSAndroid Build Coastguard Worker }
1423*c8d645caSAndroid Build Coastguard Worker 
pb_dec_fixed32(pb_istream_t * stream,const pb_field_t * field,void * dest)1424*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
1425*c8d645caSAndroid Build Coastguard Worker {
1426*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(field);
1427*c8d645caSAndroid Build Coastguard Worker     return pb_decode_fixed32(stream, dest);
1428*c8d645caSAndroid Build Coastguard Worker }
1429*c8d645caSAndroid Build Coastguard Worker 
pb_dec_fixed64(pb_istream_t * stream,const pb_field_t * field,void * dest)1430*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
1431*c8d645caSAndroid Build Coastguard Worker {
1432*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(field);
1433*c8d645caSAndroid Build Coastguard Worker #ifndef PB_WITHOUT_64BIT
1434*c8d645caSAndroid Build Coastguard Worker     return pb_decode_fixed64(stream, dest);
1435*c8d645caSAndroid Build Coastguard Worker #else
1436*c8d645caSAndroid Build Coastguard Worker     PB_UNUSED(dest);
1437*c8d645caSAndroid Build Coastguard Worker     PB_RETURN_ERROR(stream, "no 64bit support");
1438*c8d645caSAndroid Build Coastguard Worker #endif
1439*c8d645caSAndroid Build Coastguard Worker }
1440*c8d645caSAndroid Build Coastguard Worker 
pb_dec_bytes(pb_istream_t * stream,const pb_field_t * field,void * dest)1441*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
1442*c8d645caSAndroid Build Coastguard Worker {
1443*c8d645caSAndroid Build Coastguard Worker     uint32_t size;
1444*c8d645caSAndroid Build Coastguard Worker     size_t alloc_size;
1445*c8d645caSAndroid Build Coastguard Worker     pb_bytes_array_t *bdest;
1446*c8d645caSAndroid Build Coastguard Worker 
1447*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &size))
1448*c8d645caSAndroid Build Coastguard Worker         return false;
1449*c8d645caSAndroid Build Coastguard Worker 
1450*c8d645caSAndroid Build Coastguard Worker     if (size > PB_SIZE_MAX)
1451*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "bytes overflow");
1452*c8d645caSAndroid Build Coastguard Worker 
1453*c8d645caSAndroid Build Coastguard Worker     alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size);
1454*c8d645caSAndroid Build Coastguard Worker     if (size > alloc_size)
1455*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "size too large");
1456*c8d645caSAndroid Build Coastguard Worker 
1457*c8d645caSAndroid Build Coastguard Worker     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
1458*c8d645caSAndroid Build Coastguard Worker     {
1459*c8d645caSAndroid Build Coastguard Worker #ifndef PB_ENABLE_MALLOC
1460*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "no malloc support");
1461*c8d645caSAndroid Build Coastguard Worker #else
1462*c8d645caSAndroid Build Coastguard Worker         if (stream->bytes_left < size)
1463*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "end-of-stream");
1464*c8d645caSAndroid Build Coastguard Worker 
1465*c8d645caSAndroid Build Coastguard Worker         if (!allocate_field(stream, dest, alloc_size, 1))
1466*c8d645caSAndroid Build Coastguard Worker             return false;
1467*c8d645caSAndroid Build Coastguard Worker         bdest = *(pb_bytes_array_t**)dest;
1468*c8d645caSAndroid Build Coastguard Worker #endif
1469*c8d645caSAndroid Build Coastguard Worker     }
1470*c8d645caSAndroid Build Coastguard Worker     else
1471*c8d645caSAndroid Build Coastguard Worker     {
1472*c8d645caSAndroid Build Coastguard Worker         if (alloc_size > field->data_size)
1473*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "bytes overflow");
1474*c8d645caSAndroid Build Coastguard Worker         bdest = (pb_bytes_array_t*)dest;
1475*c8d645caSAndroid Build Coastguard Worker     }
1476*c8d645caSAndroid Build Coastguard Worker 
1477*c8d645caSAndroid Build Coastguard Worker     bdest->size = (pb_size_t)size;
1478*c8d645caSAndroid Build Coastguard Worker     return pb_read(stream, bdest->bytes, size);
1479*c8d645caSAndroid Build Coastguard Worker }
1480*c8d645caSAndroid Build Coastguard Worker 
pb_dec_string(pb_istream_t * stream,const pb_field_t * field,void * dest)1481*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
1482*c8d645caSAndroid Build Coastguard Worker {
1483*c8d645caSAndroid Build Coastguard Worker     uint32_t size;
1484*c8d645caSAndroid Build Coastguard Worker     size_t alloc_size;
1485*c8d645caSAndroid Build Coastguard Worker     bool status;
1486*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &size))
1487*c8d645caSAndroid Build Coastguard Worker         return false;
1488*c8d645caSAndroid Build Coastguard Worker 
1489*c8d645caSAndroid Build Coastguard Worker     /* Space for null terminator */
1490*c8d645caSAndroid Build Coastguard Worker     alloc_size = size + 1;
1491*c8d645caSAndroid Build Coastguard Worker 
1492*c8d645caSAndroid Build Coastguard Worker     if (alloc_size < size)
1493*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "size too large");
1494*c8d645caSAndroid Build Coastguard Worker 
1495*c8d645caSAndroid Build Coastguard Worker     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
1496*c8d645caSAndroid Build Coastguard Worker     {
1497*c8d645caSAndroid Build Coastguard Worker #ifndef PB_ENABLE_MALLOC
1498*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "no malloc support");
1499*c8d645caSAndroid Build Coastguard Worker #else
1500*c8d645caSAndroid Build Coastguard Worker         if (stream->bytes_left < size)
1501*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "end-of-stream");
1502*c8d645caSAndroid Build Coastguard Worker 
1503*c8d645caSAndroid Build Coastguard Worker         if (!allocate_field(stream, dest, alloc_size, 1))
1504*c8d645caSAndroid Build Coastguard Worker             return false;
1505*c8d645caSAndroid Build Coastguard Worker         dest = *(void**)dest;
1506*c8d645caSAndroid Build Coastguard Worker #endif
1507*c8d645caSAndroid Build Coastguard Worker     }
1508*c8d645caSAndroid Build Coastguard Worker     else
1509*c8d645caSAndroid Build Coastguard Worker     {
1510*c8d645caSAndroid Build Coastguard Worker         if (alloc_size > field->data_size)
1511*c8d645caSAndroid Build Coastguard Worker             PB_RETURN_ERROR(stream, "string overflow");
1512*c8d645caSAndroid Build Coastguard Worker     }
1513*c8d645caSAndroid Build Coastguard Worker 
1514*c8d645caSAndroid Build Coastguard Worker     status = pb_read(stream, (pb_byte_t*)dest, size);
1515*c8d645caSAndroid Build Coastguard Worker     *((pb_byte_t*)dest + size) = 0;
1516*c8d645caSAndroid Build Coastguard Worker     return status;
1517*c8d645caSAndroid Build Coastguard Worker }
1518*c8d645caSAndroid Build Coastguard Worker 
pb_dec_submessage(pb_istream_t * stream,const pb_field_t * field,void * dest)1519*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
1520*c8d645caSAndroid Build Coastguard Worker {
1521*c8d645caSAndroid Build Coastguard Worker     bool status;
1522*c8d645caSAndroid Build Coastguard Worker     pb_istream_t substream;
1523*c8d645caSAndroid Build Coastguard Worker     const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr;
1524*c8d645caSAndroid Build Coastguard Worker 
1525*c8d645caSAndroid Build Coastguard Worker     if (!pb_make_string_substream(stream, &substream))
1526*c8d645caSAndroid Build Coastguard Worker         return false;
1527*c8d645caSAndroid Build Coastguard Worker 
1528*c8d645caSAndroid Build Coastguard Worker     if (field->ptr == NULL)
1529*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "invalid field descriptor");
1530*c8d645caSAndroid Build Coastguard Worker 
1531*c8d645caSAndroid Build Coastguard Worker     /* New array entries need to be initialized, while required and optional
1532*c8d645caSAndroid Build Coastguard Worker      * submessages have already been initialized in the top-level pb_decode. */
1533*c8d645caSAndroid Build Coastguard Worker     if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
1534*c8d645caSAndroid Build Coastguard Worker         status = pb_decode(&substream, submsg_fields, dest);
1535*c8d645caSAndroid Build Coastguard Worker     else
1536*c8d645caSAndroid Build Coastguard Worker         status = pb_decode_noinit(&substream, submsg_fields, dest);
1537*c8d645caSAndroid Build Coastguard Worker 
1538*c8d645caSAndroid Build Coastguard Worker     if (!pb_close_string_substream(stream, &substream))
1539*c8d645caSAndroid Build Coastguard Worker         return false;
1540*c8d645caSAndroid Build Coastguard Worker     return status;
1541*c8d645caSAndroid Build Coastguard Worker }
1542*c8d645caSAndroid Build Coastguard Worker 
pb_dec_fixed_length_bytes(pb_istream_t * stream,const pb_field_t * field,void * dest)1543*c8d645caSAndroid Build Coastguard Worker static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
1544*c8d645caSAndroid Build Coastguard Worker {
1545*c8d645caSAndroid Build Coastguard Worker     uint32_t size;
1546*c8d645caSAndroid Build Coastguard Worker 
1547*c8d645caSAndroid Build Coastguard Worker     if (!pb_decode_varint32(stream, &size))
1548*c8d645caSAndroid Build Coastguard Worker         return false;
1549*c8d645caSAndroid Build Coastguard Worker 
1550*c8d645caSAndroid Build Coastguard Worker     if (size > PB_SIZE_MAX)
1551*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "bytes overflow");
1552*c8d645caSAndroid Build Coastguard Worker 
1553*c8d645caSAndroid Build Coastguard Worker     if (size == 0)
1554*c8d645caSAndroid Build Coastguard Worker     {
1555*c8d645caSAndroid Build Coastguard Worker         /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */
1556*c8d645caSAndroid Build Coastguard Worker         memset(dest, 0, field->data_size);
1557*c8d645caSAndroid Build Coastguard Worker         return true;
1558*c8d645caSAndroid Build Coastguard Worker     }
1559*c8d645caSAndroid Build Coastguard Worker 
1560*c8d645caSAndroid Build Coastguard Worker     if (size != field->data_size)
1561*c8d645caSAndroid Build Coastguard Worker         PB_RETURN_ERROR(stream, "incorrect fixed length bytes size");
1562*c8d645caSAndroid Build Coastguard Worker 
1563*c8d645caSAndroid Build Coastguard Worker     return pb_read(stream, (pb_byte_t*)dest, field->data_size);
1564*c8d645caSAndroid Build Coastguard Worker }
1565