Fix bug in decoder with packed arrays.
[apps/agl-service-can-low-level.git] / pb_decode.c
1 /* pb_decode.c -- decode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6
7 #ifdef __GNUC__
8 /* Verify that we remember to check all return values for proper error propagation */
9 #define checkreturn __attribute__((warn_unused_result))
10 #else
11 #define checkreturn
12 #endif
13
14 #include "pb.h"
15 #include "pb_decode.h"
16 #include <string.h>
17
18 typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn;
19
20 /* --- Function pointers to field decoders ---
21  * Order in the array must match pb_action_t LTYPE numbering.
22  */
23 static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
24     &pb_dec_varint,
25     &pb_dec_svarint,
26     &pb_dec_fixed32,
27     &pb_dec_fixed64,
28     
29     &pb_dec_bytes,
30     &pb_dec_string,
31     &pb_dec_submessage
32 };
33
34 /**************
35  * pb_istream *
36  **************/
37
38 bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
39 {
40     if (stream->bytes_left < count)
41         return false;
42     
43     if (!stream->callback(stream, buf, count))
44         return false;
45     
46     stream->bytes_left -= count;
47     return true;
48 }
49
50 static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t count)
51 {
52     uint8_t *source = (uint8_t*)stream->state;
53     
54     if (buf != NULL)
55         memcpy(buf, source, count);
56     
57     stream->state = source + count;
58     return true;
59 }
60
61 pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
62 {
63     pb_istream_t stream;
64     stream.callback = &buf_read;
65     stream.state = buf;
66     stream.bytes_left = bufsize;
67     return stream;
68 }
69
70 /********************
71  * Helper functions *
72  ********************/
73
74 static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
75 {
76     uint64_t temp;
77     bool status = pb_decode_varint(stream, &temp);
78     *dest = (uint32_t)temp;
79     return status;
80 }
81
82 bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
83 {
84     uint8_t byte;
85     uint8_t bitpos = 0;
86     *dest = 0;
87     
88     while (bitpos < 64 && pb_read(stream, &byte, 1))
89     {
90         *dest |= (uint64_t)(byte & 0x7F) << bitpos;
91         bitpos += 7;
92         
93         if (!(byte & 0x80))
94             return true;
95     }
96     
97     return false;
98 }
99
100 bool checkreturn pb_skip_varint(pb_istream_t *stream)
101 {
102     uint8_t byte;
103     do
104     {
105         if (!pb_read(stream, &byte, 1))
106             return false;
107     } while (byte & 0x80);
108     return true;
109 }
110
111 bool checkreturn pb_skip_string(pb_istream_t *stream)
112 {
113     uint32_t length;
114     if (!pb_decode_varint32(stream, &length))
115         return false;
116     
117     return pb_read(stream, NULL, length);
118 }
119
120 bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
121 {
122     uint32_t temp;
123     *eof = false;
124     *wire_type = 0;
125     *tag = 0;
126     
127     if (!pb_decode_varint32(stream, &temp))
128     {
129         if (stream->bytes_left == 0)
130             *eof = true;
131
132         return false;
133     }
134     
135     if (temp == 0)
136     {
137         *eof = true; /* Special feature: allow 0-terminated messages. */
138         return false;
139     }
140     
141     *tag = temp >> 3;
142     *wire_type = (pb_wire_type_t)(temp & 7);
143     return true;
144 }
145
146 bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
147 {
148     switch (wire_type)
149     {
150         case PB_WT_VARINT: return pb_skip_varint(stream);
151         case PB_WT_64BIT: return pb_read(stream, NULL, 8);
152         case PB_WT_STRING: return pb_skip_string(stream);
153         case PB_WT_32BIT: return pb_read(stream, NULL, 4);
154         default: return false;
155     }
156 }
157
158 /* Read a raw value to buffer, for the purpose of passing it to callback as
159  * a substream. Size is maximum size on call, and actual size on return.
160  */
161 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, uint8_t *buf, size_t *size)
162 {
163     size_t max_size = *size;
164     switch (wire_type)
165     {
166         case PB_WT_VARINT:
167             *size = 0;
168             do
169             {
170                 (*size)++;
171                 if (*size > max_size) return false;
172                 if (!pb_read(stream, buf, 1)) return false;
173             } while (*buf++ & 0x80);
174             return true;
175             
176         case PB_WT_64BIT:
177             *size = 8;
178             return pb_read(stream, buf, 8);
179         
180         case PB_WT_32BIT:
181             *size = 4;
182             return pb_read(stream, buf, 4);
183         
184         default: return false;
185     }
186 }
187
188 /* Decode string length from stream and return a substream with limited length.
189  * Before disposing the substream, remember to copy the substream->state back
190  * to stream->state.
191  */
192 static bool checkreturn make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
193 {
194     uint32_t size;
195     if (!pb_decode_varint32(stream, &size))
196         return false;
197     
198     *substream = *stream;
199     if (substream->bytes_left < size)
200         return false;
201     
202     substream->bytes_left = size;
203     stream->bytes_left -= size;
204     return true;
205 }
206
207 /* Iterator for pb_field_t list */
208 typedef struct {
209     const pb_field_t *start; /* Start of the pb_field_t array */
210     const pb_field_t *current; /* Current position of the iterator */
211     int field_index; /* Zero-based index of the field. */
212     int required_field_index; /* Zero-based index that counts only the required fields */
213     void *dest_struct; /* Pointer to the destination structure to decode to */
214     void *pData; /* Pointer where to store current field value */
215     void *pSize; /* Pointer where to store the size of current array field */
216 } pb_field_iterator_t;
217
218 static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct)
219 {
220     iter->start = iter->current = fields;
221     iter->field_index = 0;
222     iter->required_field_index = 0;
223     iter->pData = (char*)dest_struct + iter->current->data_offset;
224     iter->pSize = (char*)iter->pData + iter->current->size_offset;
225     iter->dest_struct = dest_struct;
226 }
227
228 static bool pb_field_next(pb_field_iterator_t *iter)
229 {
230     bool notwrapped = true;
231     size_t prev_size = iter->current->data_size;
232     
233     if (PB_HTYPE(iter->current->type) == PB_HTYPE_ARRAY)
234         prev_size *= iter->current->array_size;
235     
236     if (PB_HTYPE(iter->current->type) == PB_HTYPE_REQUIRED)
237         iter->required_field_index++;
238     
239     iter->current++;
240     iter->field_index++;
241     if (iter->current->tag == 0)
242     {
243         iter->current = iter->start;
244         iter->field_index = 0;
245         iter->required_field_index = 0;
246         iter->pData = iter->dest_struct;
247         prev_size = 0;
248         notwrapped = false;
249     }
250     
251     iter->pData = (char*)iter->pData + prev_size + iter->current->data_offset;
252     iter->pSize = (char*)iter->pData + iter->current->size_offset;
253     return notwrapped;
254 }
255
256 static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag)
257 {
258     int start = iter->field_index;
259     
260     do {
261         if (iter->current->tag == tag)
262             return true;
263         pb_field_next(iter);
264     } while (iter->field_index != start);
265     
266     return false;
267 }
268
269 /*************************
270  * Decode a single field *
271  *************************/
272
273 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
274 {
275     pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)];
276     
277     switch (PB_HTYPE(iter->current->type))
278     {
279         case PB_HTYPE_REQUIRED:
280             return func(stream, iter->current, iter->pData);
281             
282         case PB_HTYPE_OPTIONAL:
283             *(bool*)iter->pSize = true;
284             return func(stream, iter->current, iter->pData);
285     
286         case PB_HTYPE_ARRAY:
287             if (wire_type == PB_WT_STRING
288                 && PB_LTYPE(iter->current->type) <= PB_LTYPE_LAST_PACKABLE)
289             {
290                 /* Packed array */
291                 bool status;
292                 size_t *size = (size_t*)iter->pSize;
293                 pb_istream_t substream;
294                 if (!make_string_substream(stream, &substream))
295                     return false;
296                 
297                 while (substream.bytes_left && *size < iter->current->array_size)
298                 {
299                     void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
300                     if (!func(&substream, iter->current, pItem))
301                         return false;
302                     (*size)++;
303                 }
304                 status = (substream.bytes_left == 0);
305                 stream->state = substream.state;
306                 return status;
307             }
308             else
309             {
310                 /* Repeated field */
311                 size_t *size = (size_t*)iter->pSize;
312                 void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
313                 if (*size >= iter->current->array_size)
314                     return false;
315                 
316                 (*size)++;
317                 return func(stream, iter->current, pItem);
318             }
319         
320         case PB_HTYPE_CALLBACK:
321         {
322             pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
323             
324             if (pCallback->funcs.decode == NULL)
325                 return pb_skip_field(stream, wire_type);
326             
327             if (wire_type == PB_WT_STRING)
328             {
329                 pb_istream_t substream;
330                 
331                 if (!make_string_substream(stream, &substream))
332                     return false;
333                 
334                 while (substream.bytes_left)
335                 {
336                     if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg))
337                         return false;
338                 }
339                 
340                 stream->state = substream.state;
341                 return true;
342             }
343             else
344             {
345                 /* Copy the single scalar value to stack.
346                  * This is required so that we can limit the stream length,
347                  * which in turn allows to use same callback for packed and
348                  * not-packed fields. */
349                 pb_istream_t substream;
350                 uint8_t buffer[10];
351                 size_t size = sizeof(buffer);
352                 
353                 if (!read_raw_value(stream, wire_type, buffer, &size))
354                     return false;
355                 substream = pb_istream_from_buffer(buffer, size);
356                 
357                 return pCallback->funcs.decode(&substream, iter->current, pCallback->arg);
358             }
359         }
360         
361         default:
362             return false;
363     }
364 }
365
366 /* Initialize message fields to default values, recursively */
367 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
368 {
369     pb_field_iterator_t iter;
370     pb_field_init(&iter, fields, dest_struct);
371     
372     /* Initialize size/has fields and apply default values */
373     do
374     {
375         if (iter.current->tag == 0)
376             continue;
377         
378         /* Initialize the size field for optional/repeated fields to 0. */
379         if (PB_HTYPE(iter.current->type) == PB_HTYPE_OPTIONAL)
380         {
381             *(bool*)iter.pSize = false;
382         }
383         else if (PB_HTYPE(iter.current->type) == PB_HTYPE_ARRAY)
384         {
385             *(size_t*)iter.pSize = 0;
386             continue; /* Array is empty, no need to initialize contents */
387         }
388         
389         /* Initialize field contents to default value */
390         if (PB_HTYPE(iter.current->type) == PB_HTYPE_CALLBACK)
391         {
392             continue; /* Don't overwrite callback */
393         }
394         else if (PB_LTYPE(iter.current->type) == PB_LTYPE_SUBMESSAGE)
395         {
396             pb_message_set_to_defaults(iter.current->ptr, iter.pData);
397         }
398         else if (iter.current->ptr != NULL)
399         {
400             memcpy(iter.pData, iter.current->ptr, iter.current->data_size);
401         }
402         else
403         {
404             memset(iter.pData, 0, iter.current->data_size);
405         }
406     } while (pb_field_next(&iter));
407 }
408
409 /*********************
410  * Decode all fields *
411  *********************/
412
413 bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
414 {
415     uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */
416     pb_field_iterator_t iter;
417     
418     pb_message_set_to_defaults(fields, dest_struct);
419     
420     pb_field_init(&iter, fields, dest_struct);
421     
422     while (stream->bytes_left)
423     {
424         uint32_t tag;
425         pb_wire_type_t wire_type;
426         bool eof;
427         
428         if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
429         {
430             if (eof)
431                 break;
432             else
433                 return false;
434         }
435         
436         if (!pb_field_find(&iter, tag))
437         {
438             /* No match found, skip data */
439             if (!pb_skip_field(stream, wire_type))
440                 return false;
441             continue;
442         }
443         
444         if (PB_HTYPE(iter.current->type) == PB_HTYPE_REQUIRED
445             && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
446         {
447             fields_seen[iter.required_field_index >> 3] |= 1 << (iter.required_field_index & 7);
448         }
449             
450         if (!decode_field(stream, wire_type, &iter))
451             return false;
452     }
453     
454     /* Check that all required fields were present. */
455     pb_field_init(&iter, fields, dest_struct);
456     do {
457         if (PB_HTYPE(iter.current->type) == PB_HTYPE_REQUIRED &&
458             iter.required_field_index < PB_MAX_REQUIRED_FIELDS &&
459             !(fields_seen[iter.required_field_index >> 3] & (1 << (iter.required_field_index & 7))))
460         {
461             return false;
462         }
463     } while (pb_field_next(&iter));
464     
465     return true;
466 }
467
468 /* Field decoders */
469
470 /* Copy destsize bytes from src so that values are casted properly.
471  * On little endian machine, copy first n bytes of src
472  * On big endian machine, copy last n bytes of src
473  * srcsize must always be larger than destsize
474  */
475 static void endian_copy(void *dest, void *src, size_t destsize, size_t srcsize)
476 {
477 #ifdef __BIG_ENDIAN__
478     memcpy(dest, (char*)src + (srcsize - destsize), destsize);
479 #else
480     UNUSED(srcsize);
481     memcpy(dest, src, destsize);
482 #endif
483 }
484
485 bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
486 {
487     uint64_t temp;
488     bool status = pb_decode_varint(stream, &temp);
489     endian_copy(dest, &temp, field->data_size, sizeof(temp));
490     return status;
491 }
492
493 bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
494 {
495     uint64_t temp;
496     bool status = pb_decode_varint(stream, &temp);
497     temp = (temp >> 1) ^ -(int64_t)(temp & 1);
498     endian_copy(dest, &temp, field->data_size, sizeof(temp));
499     return status;
500 }
501
502 bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
503 {
504 #ifdef __BIG_ENDIAN__
505     uint8_t bytes[4] = {0};
506     bool status = pb_read(stream, bytes, 4);
507     if (status) {
508         uint8_t *d = (uint8_t*)dest;
509         d[0] = bytes[3];
510         d[1] = bytes[2];
511         d[2] = bytes[1];
512         d[3] = bytes[0];
513     }
514     return status;
515 #else
516     UNUSED(field);
517     return pb_read(stream, (uint8_t*)dest, 4);
518 #endif
519 }
520
521 bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
522 {
523 #ifdef __BIG_ENDIAN__
524     uint8_t bytes[8] = {0};
525     bool status = pb_read(stream, bytes, 8);
526     if (status) {
527         uint8_t *d = (uint8_t*)dest;
528         d[0] = bytes[7];
529         d[1] = bytes[6];
530         d[2] = bytes[5]; 
531         d[3] = bytes[4];
532         d[4] = bytes[3];
533         d[5] = bytes[2];
534         d[6] = bytes[1];
535         d[7] = bytes[0];
536     }
537     return status;
538 #else
539     UNUSED(field);
540     return pb_read(stream, (uint8_t*)dest, 8);
541 #endif
542 }
543
544 bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
545 {
546     pb_bytes_array_t *x = (pb_bytes_array_t*)dest;
547     
548     uint32_t temp;
549     if (!pb_decode_varint32(stream, &temp))
550         return false;
551     x->size = temp;
552     
553     /* Check length, noting the space taken by the size_t header. */
554     if (x->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
555         return false;
556     
557     return pb_read(stream, x->bytes, x->size);
558 }
559
560 bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
561 {
562     uint32_t size;
563     bool status;
564     if (!pb_decode_varint32(stream, &size))
565         return false;
566     
567     /* Check length, noting the null terminator */
568     if (size + 1 > field->data_size)
569         return false;
570     
571     status = pb_read(stream, (uint8_t*)dest, size);
572     *((uint8_t*)dest + size) = 0;
573     return status;
574 }
575
576 bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
577 {
578     bool status;
579     pb_istream_t substream;
580     
581     if (!make_string_substream(stream, &substream))
582         return false;
583     
584     if (field->ptr == NULL)
585         return false;
586     
587     status = pb_decode(&substream, (pb_field_t*)field->ptr, dest);
588     stream->state = substream.state;
589     return status;
590 }