• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include "upb/decode.h"
3 
4 #include <setjmp.h>
5 #include <string.h>
6 
7 #include "upb/decode.int.h"
8 #include "upb/upb.h"
9 #include "upb/upb.int.h"
10 
11 /* Must be last. */
12 #include "upb/port_def.inc"
13 
14 /* Maps descriptor type -> elem_size_lg2.  */
15 static const uint8_t desctype_to_elem_size_lg2[] = {
16     -1,               /* invalid descriptor type */
17     3,  /* DOUBLE */
18     2,   /* FLOAT */
19     3,   /* INT64 */
20     3,  /* UINT64 */
21     2,   /* INT32 */
22     3,  /* FIXED64 */
23     2,  /* FIXED32 */
24     0,    /* BOOL */
25     UPB_SIZE(3, 4),  /* STRING */
26     UPB_SIZE(2, 3),  /* GROUP */
27     UPB_SIZE(2, 3),  /* MESSAGE */
28     UPB_SIZE(3, 4),  /* BYTES */
29     2,  /* UINT32 */
30     2,    /* ENUM */
31     2,   /* SFIXED32 */
32     3,   /* SFIXED64 */
33     2,   /* SINT32 */
34     3,   /* SINT64 */
35 };
36 
37 /* Maps descriptor type -> upb map size.  */
38 static const uint8_t desctype_to_mapsize[] = {
39     -1,                 /* invalid descriptor type */
40     8,                  /* DOUBLE */
41     4,                  /* FLOAT */
42     8,                  /* INT64 */
43     8,                  /* UINT64 */
44     4,                  /* INT32 */
45     8,                  /* FIXED64 */
46     4,                  /* FIXED32 */
47     1,                  /* BOOL */
48     UPB_MAPTYPE_STRING, /* STRING */
49     sizeof(void *),     /* GROUP */
50     sizeof(void *),     /* MESSAGE */
51     UPB_MAPTYPE_STRING, /* BYTES */
52     4,                  /* UINT32 */
53     4,                  /* ENUM */
54     4,                  /* SFIXED32 */
55     8,                  /* SFIXED64 */
56     4,                  /* SINT32 */
57     8,                  /* SINT64 */
58 };
59 
60 static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
61                                    (1 << UPB_DTYPE_FIXED32) |
62                                    (1 << UPB_DTYPE_SFIXED32);
63 
64 static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
65                                    (1 << UPB_DTYPE_FIXED64) |
66                                    (1 << UPB_DTYPE_SFIXED64);
67 
68 /* Op: an action to be performed for a wire-type/field-type combination. */
69 #define OP_SCALAR_LG2(n) (n)      /* n in [0, 2, 3] => op in [0, 2, 3] */
70 #define OP_STRING 4
71 #define OP_BYTES 5
72 #define OP_SUBMSG 6
73 /* Ops above are scalar-only. Repeated fields can use any op.  */
74 #define OP_FIXPCK_LG2(n) (n + 5)  /* n in [2, 3] => op in [7, 8] */
75 #define OP_VARPCK_LG2(n) (n + 9)  /* n in [0, 2, 3] => op in [9, 11, 12] */
76 
77 static const int8_t varint_ops[19] = {
78     -1,               /* field not found */
79     -1,               /* DOUBLE */
80     -1,               /* FLOAT */
81     OP_SCALAR_LG2(3), /* INT64 */
82     OP_SCALAR_LG2(3), /* UINT64 */
83     OP_SCALAR_LG2(2), /* INT32 */
84     -1,               /* FIXED64 */
85     -1,               /* FIXED32 */
86     OP_SCALAR_LG2(0), /* BOOL */
87     -1,               /* STRING */
88     -1,               /* GROUP */
89     -1,               /* MESSAGE */
90     -1,               /* BYTES */
91     OP_SCALAR_LG2(2), /* UINT32 */
92     OP_SCALAR_LG2(2), /* ENUM */
93     -1,               /* SFIXED32 */
94     -1,               /* SFIXED64 */
95     OP_SCALAR_LG2(2), /* SINT32 */
96     OP_SCALAR_LG2(3), /* SINT64 */
97 };
98 
99 static const int8_t delim_ops[37] = {
100     /* For non-repeated field type. */
101     -1,        /* field not found */
102     -1,        /* DOUBLE */
103     -1,        /* FLOAT */
104     -1,        /* INT64 */
105     -1,        /* UINT64 */
106     -1,        /* INT32 */
107     -1,        /* FIXED64 */
108     -1,        /* FIXED32 */
109     -1,        /* BOOL */
110     OP_STRING, /* STRING */
111     -1,        /* GROUP */
112     OP_SUBMSG, /* MESSAGE */
113     OP_BYTES,  /* BYTES */
114     -1,        /* UINT32 */
115     -1,        /* ENUM */
116     -1,        /* SFIXED32 */
117     -1,        /* SFIXED64 */
118     -1,        /* SINT32 */
119     -1,        /* SINT64 */
120     /* For repeated field type. */
121     OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
122     OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
123     OP_VARPCK_LG2(3), /* REPEATED INT64 */
124     OP_VARPCK_LG2(3), /* REPEATED UINT64 */
125     OP_VARPCK_LG2(2), /* REPEATED INT32 */
126     OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
127     OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
128     OP_VARPCK_LG2(0), /* REPEATED BOOL */
129     OP_STRING,        /* REPEATED STRING */
130     OP_SUBMSG,        /* REPEATED GROUP */
131     OP_SUBMSG,        /* REPEATED MESSAGE */
132     OP_BYTES,         /* REPEATED BYTES */
133     OP_VARPCK_LG2(2), /* REPEATED UINT32 */
134     OP_VARPCK_LG2(2), /* REPEATED ENUM */
135     OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
136     OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
137     OP_VARPCK_LG2(2), /* REPEATED SINT32 */
138     OP_VARPCK_LG2(3), /* REPEATED SINT64 */
139 };
140 
141 typedef union {
142   bool bool_val;
143   uint32_t uint32_val;
144   uint64_t uint64_val;
145   uint32_t size;
146 } wireval;
147 
148 static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
149                               const upb_msglayout *layout);
150 
decode_err(upb_decstate * d)151 UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); }
152 
fastdecode_err(upb_decstate * d)153 const char *fastdecode_err(upb_decstate *d) {
154   longjmp(d->err, 1);
155   return NULL;
156 }
157 
158 const uint8_t upb_utf8_offsets[] = {
159     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
160     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
161     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
162     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
163     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164     1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
168     2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
169     4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
170 };
171 
decode_verifyutf8(upb_decstate * d,const char * buf,int len)172 static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
173   if (!decode_verifyutf8_inl(buf, len)) decode_err(d);
174 }
175 
decode_reserve(upb_decstate * d,upb_array * arr,size_t elem)176 static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
177   bool need_realloc = arr->size - arr->len < elem;
178   if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) {
179     decode_err(d);
180   }
181   return need_realloc;
182 }
183 
184 typedef struct {
185   const char *ptr;
186   uint64_t val;
187 } decode_vret;
188 
189 UPB_NOINLINE
decode_longvarint64(const char * ptr,uint64_t val)190 static decode_vret decode_longvarint64(const char *ptr, uint64_t val) {
191   decode_vret ret = {NULL, 0};
192   uint64_t byte;
193   int i;
194   for (i = 1; i < 10; i++) {
195     byte = (uint8_t)ptr[i];
196     val += (byte - 1) << (i * 7);
197     if (!(byte & 0x80)) {
198       ret.ptr = ptr + i + 1;
199       ret.val = val;
200       return ret;
201     }
202   }
203   return ret;
204 }
205 
206 UPB_FORCEINLINE
decode_varint64(upb_decstate * d,const char * ptr,uint64_t * val)207 static const char *decode_varint64(upb_decstate *d, const char *ptr,
208                                    uint64_t *val) {
209   uint64_t byte = (uint8_t)*ptr;
210   if (UPB_LIKELY((byte & 0x80) == 0)) {
211     *val = byte;
212     return ptr + 1;
213   } else {
214     decode_vret res = decode_longvarint64(ptr, byte);
215     if (!res.ptr) decode_err(d);
216     *val = res.val;
217     return res.ptr;
218   }
219 }
220 
221 UPB_FORCEINLINE
decode_tag(upb_decstate * d,const char * ptr,uint32_t * val)222 static const char *decode_tag(upb_decstate *d, const char *ptr,
223                                    uint32_t *val) {
224   uint64_t byte = (uint8_t)*ptr;
225   if (UPB_LIKELY((byte & 0x80) == 0)) {
226     *val = byte;
227     return ptr + 1;
228   } else {
229     const char *start = ptr;
230     decode_vret res = decode_longvarint64(ptr, byte);
231     ptr = res.ptr;
232     *val = res.val;
233     if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d);
234     return ptr;
235   }
236 }
237 
decode_munge(int type,wireval * val)238 static void decode_munge(int type, wireval *val) {
239   switch (type) {
240     case UPB_DESCRIPTOR_TYPE_BOOL:
241       val->bool_val = val->uint64_val != 0;
242       break;
243     case UPB_DESCRIPTOR_TYPE_SINT32: {
244       uint32_t n = val->uint32_val;
245       val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
246       break;
247     }
248     case UPB_DESCRIPTOR_TYPE_SINT64: {
249       uint64_t n = val->uint64_val;
250       val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
251       break;
252     }
253     case UPB_DESCRIPTOR_TYPE_INT32:
254     case UPB_DESCRIPTOR_TYPE_UINT32:
255       if (!_upb_isle()) {
256         /* The next stage will memcpy(dst, &val, 4) */
257         val->uint32_val = val->uint64_val;
258       }
259       break;
260   }
261 }
262 
upb_find_field(const upb_msglayout * l,uint32_t field_number)263 static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
264                                                  uint32_t field_number) {
265   static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
266 
267   /* Lots of optimization opportunities here. */
268   int i;
269   if (l == NULL) return &none;
270   for (i = 0; i < l->field_count; i++) {
271     if (l->fields[i].number == field_number) {
272       return &l->fields[i];
273     }
274   }
275 
276   return &none; /* Unknown field. */
277 }
278 
decode_newsubmsg(upb_decstate * d,const upb_msglayout * layout,const upb_msglayout_field * field)279 static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
280                                  const upb_msglayout_field *field) {
281   const upb_msglayout *subl = layout->submsgs[field->submsg_index];
282   return _upb_msg_new_inl(subl, &d->arena);
283 }
284 
285 UPB_NOINLINE
decode_isdonefallback(upb_decstate * d,const char * ptr,int overrun)286 const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
287                                   int overrun) {
288   ptr = decode_isdonefallback_inl(d, ptr, overrun);
289   if (ptr == NULL) {
290     decode_err(d);
291   }
292   return ptr;
293 }
294 
decode_readstr(upb_decstate * d,const char * ptr,int size,upb_strview * str)295 static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
296                                   upb_strview *str) {
297   if (d->alias) {
298     str->data = ptr;
299   } else {
300     char *data =  upb_arena_malloc(&d->arena, size);
301     if (!data) decode_err(d);
302     memcpy(data, ptr, size);
303     str->data = data;
304   }
305   str->size = size;
306   return ptr + size;
307 }
308 
309 UPB_FORCEINLINE
decode_tosubmsg(upb_decstate * d,const char * ptr,upb_msg * submsg,const upb_msglayout * layout,const upb_msglayout_field * field,int size)310 static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
311                                    upb_msg *submsg, const upb_msglayout *layout,
312                                    const upb_msglayout_field *field, int size) {
313   const upb_msglayout *subl = layout->submsgs[field->submsg_index];
314   int saved_delta = decode_pushlimit(d, ptr, size);
315   if (--d->depth < 0) decode_err(d);
316   if (!decode_isdone(d, &ptr)) {
317     ptr = decode_msg(d, ptr, submsg, subl);
318   }
319   if (d->end_group != DECODE_NOGROUP) decode_err(d);
320   decode_poplimit(d, ptr, saved_delta);
321   d->depth++;
322   return ptr;
323 }
324 
325 UPB_FORCEINLINE
decode_group(upb_decstate * d,const char * ptr,upb_msg * submsg,const upb_msglayout * subl,uint32_t number)326 static const char *decode_group(upb_decstate *d, const char *ptr,
327                                 upb_msg *submsg, const upb_msglayout *subl,
328                                 uint32_t number) {
329   if (--d->depth < 0) decode_err(d);
330   if (decode_isdone(d, &ptr)) {
331     decode_err(d);
332   }
333   ptr = decode_msg(d, ptr, submsg, subl);
334   if (d->end_group != number) decode_err(d);
335   d->end_group = DECODE_NOGROUP;
336   d->depth++;
337   return ptr;
338 }
339 
340 UPB_FORCEINLINE
decode_togroup(upb_decstate * d,const char * ptr,upb_msg * submsg,const upb_msglayout * layout,const upb_msglayout_field * field)341 static const char *decode_togroup(upb_decstate *d, const char *ptr,
342                                   upb_msg *submsg, const upb_msglayout *layout,
343                                   const upb_msglayout_field *field) {
344   const upb_msglayout *subl = layout->submsgs[field->submsg_index];
345   return decode_group(d, ptr, submsg, subl, field->number);
346 }
347 
decode_toarray(upb_decstate * d,const char * ptr,upb_msg * msg,const upb_msglayout * layout,const upb_msglayout_field * field,wireval val,int op)348 static const char *decode_toarray(upb_decstate *d, const char *ptr,
349                                   upb_msg *msg, const upb_msglayout *layout,
350                                   const upb_msglayout_field *field, wireval val,
351                                   int op) {
352   upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
353   upb_array *arr = *arrp;
354   void *mem;
355 
356   if (arr) {
357     decode_reserve(d, arr, 1);
358   } else {
359     size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype];
360     arr = _upb_array_new(&d->arena, 4, lg2);
361     if (!arr) decode_err(d);
362     *arrp = arr;
363   }
364 
365   switch (op) {
366     case OP_SCALAR_LG2(0):
367     case OP_SCALAR_LG2(2):
368     case OP_SCALAR_LG2(3):
369       /* Append scalar value. */
370       mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
371       arr->len++;
372       memcpy(mem, &val, 1 << op);
373       return ptr;
374     case OP_STRING:
375       decode_verifyutf8(d, ptr, val.size);
376       /* Fallthrough. */
377     case OP_BYTES: {
378       /* Append bytes. */
379       upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
380       arr->len++;
381       return decode_readstr(d, ptr, val.size, str);
382     }
383     case OP_SUBMSG: {
384       /* Append submessage / group. */
385       upb_msg *submsg = decode_newsubmsg(d, layout, field);
386       *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
387           submsg;
388       arr->len++;
389       if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
390         return decode_togroup(d, ptr, submsg, layout, field);
391       } else {
392         return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
393       }
394     }
395     case OP_FIXPCK_LG2(2):
396     case OP_FIXPCK_LG2(3): {
397       /* Fixed packed. */
398       int lg2 = op - OP_FIXPCK_LG2(0);
399       int mask = (1 << lg2) - 1;
400       size_t count = val.size >> lg2;
401       if ((val.size & mask) != 0) {
402         decode_err(d); /* Length isn't a round multiple of elem size. */
403       }
404       decode_reserve(d, arr, count);
405       mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
406       arr->len += count;
407       memcpy(mem, ptr, val.size);  /* XXX: ptr boundary. */
408       return ptr + val.size;
409     }
410     case OP_VARPCK_LG2(0):
411     case OP_VARPCK_LG2(2):
412     case OP_VARPCK_LG2(3): {
413       /* Varint packed. */
414       int lg2 = op - OP_VARPCK_LG2(0);
415       int scale = 1 << lg2;
416       int saved_limit = decode_pushlimit(d, ptr, val.size);
417       char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
418       while (!decode_isdone(d, &ptr)) {
419         wireval elem;
420         ptr = decode_varint64(d, ptr, &elem.uint64_val);
421         decode_munge(field->descriptortype, &elem);
422         if (decode_reserve(d, arr, 1)) {
423           out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
424         }
425         arr->len++;
426         memcpy(out, &elem, scale);
427         out += scale;
428       }
429       decode_poplimit(d, ptr, saved_limit);
430       return ptr;
431     }
432     default:
433       UPB_UNREACHABLE();
434   }
435 }
436 
decode_tomap(upb_decstate * d,const char * ptr,upb_msg * msg,const upb_msglayout * layout,const upb_msglayout_field * field,wireval val)437 static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
438                                 const upb_msglayout *layout,
439                                 const upb_msglayout_field *field, wireval val) {
440   upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
441   upb_map *map = *map_p;
442   upb_map_entry ent;
443   const upb_msglayout *entry = layout->submsgs[field->submsg_index];
444 
445   if (!map) {
446     /* Lazily create map. */
447     const upb_msglayout *entry = layout->submsgs[field->submsg_index];
448     const upb_msglayout_field *key_field = &entry->fields[0];
449     const upb_msglayout_field *val_field = &entry->fields[1];
450     char key_size = desctype_to_mapsize[key_field->descriptortype];
451     char val_size = desctype_to_mapsize[val_field->descriptortype];
452     UPB_ASSERT(key_field->offset == 0);
453     UPB_ASSERT(val_field->offset == sizeof(upb_strview));
454     map = _upb_map_new(&d->arena, key_size, val_size);
455     *map_p = map;
456   }
457 
458   /* Parse map entry. */
459   memset(&ent, 0, sizeof(ent));
460 
461   if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
462       entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
463     /* Create proactively to handle the case where it doesn't appear. */
464     ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
465   }
466 
467   ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
468   _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
469   return ptr;
470 }
471 
decode_tomsg(upb_decstate * d,const char * ptr,upb_msg * msg,const upb_msglayout * layout,const upb_msglayout_field * field,wireval val,int op)472 static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
473                                 const upb_msglayout *layout,
474                                 const upb_msglayout_field *field, wireval val,
475                                 int op) {
476   void *mem = UPB_PTR_AT(msg, field->offset, void);
477   int type = field->descriptortype;
478 
479   /* Set presence if necessary. */
480   if (field->presence < 0) {
481     /* Oneof case */
482     uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
483     if (op == OP_SUBMSG && *oneof_case != field->number) {
484       memset(mem, 0, sizeof(void*));
485     }
486     *oneof_case = field->number;
487   } else if (field->presence > 0) {
488     _upb_sethas_field(msg, field);
489   }
490 
491   /* Store into message. */
492   switch (op) {
493     case OP_SUBMSG: {
494       upb_msg **submsgp = mem;
495       upb_msg *submsg = *submsgp;
496       if (!submsg) {
497         submsg = decode_newsubmsg(d, layout, field);
498         *submsgp = submsg;
499       }
500       if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
501         ptr = decode_togroup(d, ptr, submsg, layout, field);
502       } else {
503         ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
504       }
505       break;
506     }
507     case OP_STRING:
508       decode_verifyutf8(d, ptr, val.size);
509       /* Fallthrough. */
510     case OP_BYTES:
511       return decode_readstr(d, ptr, val.size, mem);
512     case OP_SCALAR_LG2(3):
513       memcpy(mem, &val, 8);
514       break;
515     case OP_SCALAR_LG2(2):
516       memcpy(mem, &val, 4);
517       break;
518     case OP_SCALAR_LG2(0):
519       memcpy(mem, &val, 1);
520       break;
521     default:
522       UPB_UNREACHABLE();
523   }
524 
525   return ptr;
526 }
527 
528 UPB_FORCEINLINE
decode_tryfastdispatch(upb_decstate * d,const char ** ptr,upb_msg * msg,const upb_msglayout * layout)529 static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
530                                    upb_msg *msg, const upb_msglayout *layout) {
531 #if UPB_FASTTABLE
532   if (layout && layout->table_mask != (unsigned char)-1) {
533     uint16_t tag = fastdecode_loadtag(*ptr);
534     intptr_t table = decode_totable(layout);
535     *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag);
536     return true;
537   }
538 #endif
539   return false;
540 }
541 
542 UPB_NOINLINE
decode_msg(upb_decstate * d,const char * ptr,upb_msg * msg,const upb_msglayout * layout)543 static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
544                               const upb_msglayout *layout) {
545   while (true) {
546     uint32_t tag;
547     const upb_msglayout_field *field;
548     int field_number;
549     int wire_type;
550     const char *field_start = ptr;
551     wireval val;
552     int op;
553 
554     UPB_ASSERT(ptr < d->limit_ptr);
555     ptr = decode_tag(d, ptr, &tag);
556     field_number = tag >> 3;
557     wire_type = tag & 7;
558 
559     field = upb_find_field(layout, field_number);
560 
561     switch (wire_type) {
562       case UPB_WIRE_TYPE_VARINT:
563         ptr = decode_varint64(d, ptr, &val.uint64_val);
564         op = varint_ops[field->descriptortype];
565         decode_munge(field->descriptortype, &val);
566         break;
567       case UPB_WIRE_TYPE_32BIT:
568         memcpy(&val.uint32_val, ptr, 4);
569         val.uint32_val = _upb_be_swap32(val.uint32_val);
570         ptr += 4;
571         op = OP_SCALAR_LG2(2);
572         if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
573         break;
574       case UPB_WIRE_TYPE_64BIT:
575         memcpy(&val.uint64_val, ptr, 8);
576         val.uint64_val = _upb_be_swap64(val.uint64_val);
577         ptr += 8;
578         op = OP_SCALAR_LG2(3);
579         if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
580         break;
581       case UPB_WIRE_TYPE_DELIMITED: {
582         int ndx = field->descriptortype;
583         uint64_t size;
584         if (_upb_isrepeated(field)) ndx += 18;
585         ptr = decode_varint64(d, ptr, &size);
586         if (size >= INT32_MAX ||
587             ptr - d->end + (int32_t)size > d->limit) {
588           decode_err(d); /* Length overflow. */
589         }
590         op = delim_ops[ndx];
591         val.size = size;
592         break;
593       }
594       case UPB_WIRE_TYPE_START_GROUP:
595         val.uint32_val = field_number;
596         op = OP_SUBMSG;
597         if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
598         break;
599       case UPB_WIRE_TYPE_END_GROUP:
600         d->end_group = field_number;
601         return ptr;
602       default:
603         decode_err(d);
604     }
605 
606     if (op >= 0) {
607       /* Parse, using op for dispatch. */
608       switch (field->label) {
609         case UPB_LABEL_REPEATED:
610         case _UPB_LABEL_PACKED:
611           ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
612           break;
613         case _UPB_LABEL_MAP:
614           ptr = decode_tomap(d, ptr, msg, layout, field, val);
615           break;
616         default:
617           ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
618           break;
619       }
620     } else {
621     unknown:
622       /* Skip unknown field. */
623       if (field_number == 0) decode_err(d);
624       if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
625       if (msg) {
626         if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
627           d->unknown = field_start;
628           d->unknown_msg = msg;
629           ptr = decode_group(d, ptr, NULL, NULL, field_number);
630           d->unknown_msg = NULL;
631           field_start = d->unknown;
632         }
633         if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
634                                  &d->arena)) {
635           decode_err(d);
636         }
637       } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
638         ptr = decode_group(d, ptr, NULL, NULL, field_number);
639       }
640     }
641 
642     if (decode_isdone(d, &ptr)) return ptr;
643     if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr;
644   }
645 }
646 
fastdecode_generic(struct upb_decstate * d,const char * ptr,upb_msg * msg,intptr_t table,uint64_t hasbits,uint64_t data)647 const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
648                                upb_msg *msg, intptr_t table, uint64_t hasbits,
649                                uint64_t data) {
650   (void)data;
651   *(uint32_t*)msg |= hasbits;
652   return decode_msg(d, ptr, msg, decode_totablep(table));
653 }
654 
_upb_decode(const char * buf,size_t size,void * msg,const upb_msglayout * l,upb_arena * arena,int options)655 bool _upb_decode(const char *buf, size_t size, void *msg,
656                  const upb_msglayout *l, upb_arena *arena, int options) {
657   bool ok;
658   upb_decstate state;
659   unsigned depth = (unsigned)options >> 16;
660 
661   if (size == 0) {
662     return true;
663   } else if (size <= 16) {
664     memset(&state.patch, 0, 32);
665     memcpy(&state.patch, buf, size);
666     buf = state.patch;
667     state.end = buf + size;
668     state.limit = 0;
669     state.alias = false;
670   } else {
671     state.end = buf + size - 16;
672     state.limit = 16;
673     state.alias = options & UPB_DECODE_ALIAS;
674   }
675 
676   state.limit_ptr = state.end;
677   state.unknown_msg = NULL;
678   state.depth = depth ? depth : 64;
679   state.end_group = DECODE_NOGROUP;
680   state.arena.head = arena->head;
681   state.arena.last_size = arena->last_size;
682   state.arena.parent = arena;
683 
684   if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
685     ok = false;
686   } else {
687     if (!decode_tryfastdispatch(&state, &buf, msg, l)) {
688       decode_msg(&state, buf, msg, l);
689     }
690     ok = state.end_group == DECODE_NOGROUP;
691   }
692 
693   arena->head.ptr = state.arena.head.ptr;
694   arena->head.end = state.arena.head.end;
695   return ok;
696 }
697 
698 #undef OP_SCALAR_LG2
699 #undef OP_FIXPCK_LG2
700 #undef OP_VARPCK_LG2
701 #undef OP_STRING
702 #undef OP_SUBMSG
703