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