xref: /netbsd-src/external/mit/libcbor/dist/src/cbor/streaming.c (revision 5dd36a3bc8bf2a9dec29ceb6349550414570c447)
1 /*
2  * Copyright (c) 2014-2019 Pavel Kalvoda <me@pavelkalvoda.com>
3  *
4  * libcbor is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7 
8 #include "streaming.h"
9 #include "internal/loaders.h"
10 
_cbor_claim_bytes(size_t required,size_t provided,struct cbor_decoder_result * result)11 bool static _cbor_claim_bytes(size_t required, size_t provided,
12                               struct cbor_decoder_result *result) {
13   if (required > (provided - result->read)) {
14     /* We need to keep all the metadata if parsing is to be resumed */
15     result->read = 0;
16     result->status = CBOR_DECODER_NEDATA;
17     result->required = required;
18     return false;
19   } else {
20     result->read += required;
21     result->required = 0;
22     return true;
23   }
24 }
25 
cbor_stream_decode(cbor_data source,size_t source_size,const struct cbor_callbacks * callbacks,void * context)26 struct cbor_decoder_result cbor_stream_decode(
27     cbor_data source, size_t source_size,
28     const struct cbor_callbacks *callbacks, void *context) {
29   /* If we have no data, we cannot read even the MTB */
30   if (source_size < 1) {
31     return (struct cbor_decoder_result){0, CBOR_DECODER_EBUFFER};
32   }
33 
34   /* If we have a byte, assume it's the MTB */
35   struct cbor_decoder_result result = {1, CBOR_DECODER_FINISHED};
36 
37   switch (*source) {
38     case 0x00: /* Fallthrough */
39     case 0x01: /* Fallthrough */
40     case 0x02: /* Fallthrough */
41     case 0x03: /* Fallthrough */
42     case 0x04: /* Fallthrough */
43     case 0x05: /* Fallthrough */
44     case 0x06: /* Fallthrough */
45     case 0x07: /* Fallthrough */
46     case 0x08: /* Fallthrough */
47     case 0x09: /* Fallthrough */
48     case 0x0A: /* Fallthrough */
49     case 0x0B: /* Fallthrough */
50     case 0x0C: /* Fallthrough */
51     case 0x0D: /* Fallthrough */
52     case 0x0E: /* Fallthrough */
53     case 0x0F: /* Fallthrough */
54     case 0x10: /* Fallthrough */
55     case 0x11: /* Fallthrough */
56     case 0x12: /* Fallthrough */
57     case 0x13: /* Fallthrough */
58     case 0x14: /* Fallthrough */
59     case 0x15: /* Fallthrough */
60     case 0x16: /* Fallthrough */
61     case 0x17:
62       /* Embedded one byte unsigned integer */
63       {
64         callbacks->uint8(context, _cbor_load_uint8(source));
65         return result;
66       }
67     case 0x18:
68       /* One byte unsigned integer */
69       {
70         if (_cbor_claim_bytes(1, source_size, &result)) {
71           callbacks->uint8(context, _cbor_load_uint8(source + 1));
72         }
73         return result;
74       }
75     case 0x19:
76       /* Two bytes unsigned integer */
77       {
78         if (_cbor_claim_bytes(2, source_size, &result)) {
79           callbacks->uint16(context, _cbor_load_uint16(source + 1));
80         }
81         return result;
82       }
83     case 0x1A:
84       /* Four bytes unsigned integer */
85       {
86         if (_cbor_claim_bytes(4, source_size, &result)) {
87           callbacks->uint32(context, _cbor_load_uint32(source + 1));
88         }
89         return result;
90       }
91     case 0x1B:
92       /* Eight bytes unsigned integer */
93       {
94         if (_cbor_claim_bytes(8, source_size, &result)) {
95           callbacks->uint64(context, _cbor_load_uint64(source + 1));
96         }
97         return result;
98       }
99     case 0x1C: /* Fallthrough */
100     case 0x1D: /* Fallthrough */
101     case 0x1E: /* Fallthrough */
102     case 0x1F:
103       /* Reserved */
104       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
105     case 0x20: /* Fallthrough */
106     case 0x21: /* Fallthrough */
107     case 0x22: /* Fallthrough */
108     case 0x23: /* Fallthrough */
109     case 0x24: /* Fallthrough */
110     case 0x25: /* Fallthrough */
111     case 0x26: /* Fallthrough */
112     case 0x27: /* Fallthrough */
113     case 0x28: /* Fallthrough */
114     case 0x29: /* Fallthrough */
115     case 0x2A: /* Fallthrough */
116     case 0x2B: /* Fallthrough */
117     case 0x2C: /* Fallthrough */
118     case 0x2D: /* Fallthrough */
119     case 0x2E: /* Fallthrough */
120     case 0x2F: /* Fallthrough */
121     case 0x30: /* Fallthrough */
122     case 0x31: /* Fallthrough */
123     case 0x32: /* Fallthrough */
124     case 0x33: /* Fallthrough */
125     case 0x34: /* Fallthrough */
126     case 0x35: /* Fallthrough */
127     case 0x36: /* Fallthrough */
128     case 0x37:
129       /* Embedded one byte negative integer */
130       {
131         callbacks->negint8(context,
132                            _cbor_load_uint8(source) - 0x20); /* 0x20 offset */
133         return result;
134       }
135     case 0x38:
136       /* One byte negative integer */
137       {
138         if (_cbor_claim_bytes(1, source_size, &result)) {
139           callbacks->negint8(context, _cbor_load_uint8(source + 1));
140         }
141         return result;
142       }
143     case 0x39:
144       /* Two bytes negative integer */
145       {
146         if (_cbor_claim_bytes(2, source_size, &result)) {
147           callbacks->negint16(context, _cbor_load_uint16(source + 1));
148         }
149         return result;
150       }
151     case 0x3A:
152       /* Four bytes negative integer */
153       {
154         if (_cbor_claim_bytes(4, source_size, &result)) {
155           callbacks->negint32(context, _cbor_load_uint32(source + 1));
156         }
157         return result;
158       }
159     case 0x3B:
160       /* Eight bytes negative integer */
161       {
162         if (_cbor_claim_bytes(8, source_size, &result)) {
163           callbacks->negint64(context, _cbor_load_uint64(source + 1));
164         }
165         return result;
166       }
167     case 0x3C: /* Fallthrough */
168     case 0x3D: /* Fallthrough */
169     case 0x3E: /* Fallthrough */
170     case 0x3F:
171       /* Reserved */
172       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
173     case 0x40: /* Fallthrough */
174     case 0x41: /* Fallthrough */
175     case 0x42: /* Fallthrough */
176     case 0x43: /* Fallthrough */
177     case 0x44: /* Fallthrough */
178     case 0x45: /* Fallthrough */
179     case 0x46: /* Fallthrough */
180     case 0x47: /* Fallthrough */
181     case 0x48: /* Fallthrough */
182     case 0x49: /* Fallthrough */
183     case 0x4A: /* Fallthrough */
184     case 0x4B: /* Fallthrough */
185     case 0x4C: /* Fallthrough */
186     case 0x4D: /* Fallthrough */
187     case 0x4E: /* Fallthrough */
188     case 0x4F: /* Fallthrough */
189     case 0x50: /* Fallthrough */
190     case 0x51: /* Fallthrough */
191     case 0x52: /* Fallthrough */
192     case 0x53: /* Fallthrough */
193     case 0x54: /* Fallthrough */
194     case 0x55: /* Fallthrough */
195     case 0x56: /* Fallthrough */
196     case 0x57:
197       /* Embedded length byte string */
198       {
199         size_t length =
200             (size_t)_cbor_load_uint8(source) - 0x40; /* 0x40 offset */
201         if (_cbor_claim_bytes(length, source_size, &result)) {
202           callbacks->byte_string(context, source + 1, length);
203         }
204         return result;
205       }
206     case 0x58:
207       /* One byte length byte string */
208       // TODO template this?
209       {
210         if (_cbor_claim_bytes(1, source_size, &result)) {
211           size_t length = (size_t)_cbor_load_uint8(source + 1);
212           if (_cbor_claim_bytes(length, source_size, &result)) {
213             callbacks->byte_string(context, source + 1 + 1, length);
214           }
215         }
216         return result;
217       }
218     case 0x59:
219       /* Two bytes length byte string */
220       {
221         if (_cbor_claim_bytes(2, source_size, &result)) {
222           size_t length = (size_t)_cbor_load_uint16(source + 1);
223           if (_cbor_claim_bytes(length, source_size, &result)) {
224             callbacks->byte_string(context, source + 1 + 2, length);
225           }
226         }
227         return result;
228       }
229     case 0x5A:
230       /* Four bytes length byte string */
231       {
232         if (_cbor_claim_bytes(4, source_size, &result)) {
233           size_t length = (size_t)_cbor_load_uint32(source + 1);
234           if (_cbor_claim_bytes(length, source_size, &result)) {
235             callbacks->byte_string(context, source + 1 + 4, length);
236           }
237         }
238         return result;
239       }
240     case 0x5B:
241       /* Eight bytes length byte string */
242       {
243         if (_cbor_claim_bytes(8, source_size, &result)) {
244           size_t length = (size_t)_cbor_load_uint64(source + 1);
245           if (_cbor_claim_bytes(length, source_size, &result)) {
246             callbacks->byte_string(context, source + 1 + 8, length);
247           }
248         }
249         return result;
250       }
251     case 0x5C: /* Fallthrough */
252     case 0x5D: /* Fallthrough */
253     case 0x5E:
254       /* Reserved */
255       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
256     case 0x5F:
257       /* Indefinite byte string */
258       {
259         callbacks->byte_string_start(context);
260         return result;
261       }
262     case 0x60: /* Fallthrough */
263     case 0x61: /* Fallthrough */
264     case 0x62: /* Fallthrough */
265     case 0x63: /* Fallthrough */
266     case 0x64: /* Fallthrough */
267     case 0x65: /* Fallthrough */
268     case 0x66: /* Fallthrough */
269     case 0x67: /* Fallthrough */
270     case 0x68: /* Fallthrough */
271     case 0x69: /* Fallthrough */
272     case 0x6A: /* Fallthrough */
273     case 0x6B: /* Fallthrough */
274     case 0x6C: /* Fallthrough */
275     case 0x6D: /* Fallthrough */
276     case 0x6E: /* Fallthrough */
277     case 0x6F: /* Fallthrough */
278     case 0x70: /* Fallthrough */
279     case 0x71: /* Fallthrough */
280     case 0x72: /* Fallthrough */
281     case 0x73: /* Fallthrough */
282     case 0x74: /* Fallthrough */
283     case 0x75: /* Fallthrough */
284     case 0x76: /* Fallthrough */
285     case 0x77:
286       /* Embedded one byte length string */
287       {
288         size_t length =
289             (size_t)_cbor_load_uint8(source) - 0x60; /* 0x60 offset */
290         if (_cbor_claim_bytes(length, source_size, &result)) {
291           callbacks->string(context, source + 1, length);
292         }
293         return result;
294       }
295     case 0x78:
296       /* One byte length string */
297       {
298         if (_cbor_claim_bytes(1, source_size, &result)) {
299           size_t length = (size_t)_cbor_load_uint8(source + 1);
300           if (_cbor_claim_bytes(length, source_size, &result)) {
301             callbacks->string(context, source + 1 + 1, length);
302           }
303         }
304         return result;
305       }
306     case 0x79:
307       /* Two bytes length string */
308       {
309         if (_cbor_claim_bytes(2, source_size, &result)) {
310           size_t length = (size_t)_cbor_load_uint16(source + 1);
311           if (_cbor_claim_bytes(length, source_size, &result)) {
312             callbacks->string(context, source + 1 + 2, length);
313           }
314         }
315         return result;
316       }
317     case 0x7A:
318       /* Four bytes length string */
319       {
320         if (_cbor_claim_bytes(4, source_size, &result)) {
321           size_t length = (size_t)_cbor_load_uint32(source + 1);
322           if (_cbor_claim_bytes(length, source_size, &result)) {
323             callbacks->string(context, source + 1 + 4, length);
324           }
325         }
326         return result;
327       }
328     case 0x7B:
329       /* Eight bytes length string */
330       {
331         if (_cbor_claim_bytes(8, source_size, &result)) {
332           size_t length = (size_t)_cbor_load_uint64(source + 1);
333           if (_cbor_claim_bytes(length, source_size, &result)) {
334             callbacks->string(context, source + 1 + 8, length);
335           }
336         }
337         return result;
338       }
339     case 0x7C: /* Fallthrough */
340     case 0x7D: /* Fallthrough */
341     case 0x7E:
342       /* Reserved */
343       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
344     case 0x7F:
345       /* Indefinite length string */
346       {
347         callbacks->string_start(context);
348         return result;
349       }
350     case 0x80: /* Fallthrough */
351     case 0x81: /* Fallthrough */
352     case 0x82: /* Fallthrough */
353     case 0x83: /* Fallthrough */
354     case 0x84: /* Fallthrough */
355     case 0x85: /* Fallthrough */
356     case 0x86: /* Fallthrough */
357     case 0x87: /* Fallthrough */
358     case 0x88: /* Fallthrough */
359     case 0x89: /* Fallthrough */
360     case 0x8A: /* Fallthrough */
361     case 0x8B: /* Fallthrough */
362     case 0x8C: /* Fallthrough */
363     case 0x8D: /* Fallthrough */
364     case 0x8E: /* Fallthrough */
365     case 0x8F: /* Fallthrough */
366     case 0x90: /* Fallthrough */
367     case 0x91: /* Fallthrough */
368     case 0x92: /* Fallthrough */
369     case 0x93: /* Fallthrough */
370     case 0x94: /* Fallthrough */
371     case 0x95: /* Fallthrough */
372     case 0x96: /* Fallthrough */
373     case 0x97:
374       /* Embedded one byte length array */
375       {
376         callbacks->array_start(
377             context, (size_t)_cbor_load_uint8(source) - 0x80); /* 0x40 offset */
378         return result;
379       }
380     case 0x98:
381       /* One byte length array */
382       {
383         if (_cbor_claim_bytes(1, source_size, &result)) {
384           callbacks->array_start(context, (size_t)_cbor_load_uint8(source + 1));
385         }
386         return result;
387       }
388     case 0x99:
389       /* Two bytes length array */
390       {
391         if (_cbor_claim_bytes(2, source_size, &result)) {
392           callbacks->array_start(context,
393                                  (size_t)_cbor_load_uint16(source + 1));
394         }
395         return result;
396       }
397     case 0x9A:
398       /* Four bytes length array */
399       {
400         if (_cbor_claim_bytes(4, source_size, &result)) {
401           callbacks->array_start(context,
402                                  (size_t)_cbor_load_uint32(source + 1));
403         }
404         return result;
405       }
406     case 0x9B:
407       /* Eight bytes length array */
408       {
409         if (_cbor_claim_bytes(8, source_size, &result)) {
410           callbacks->array_start(context,
411                                  (size_t)_cbor_load_uint64(source + 1));
412         }
413         return result;
414       }
415     case 0x9C: /* Fallthrough */
416     case 0x9D: /* Fallthrough */
417     case 0x9E:
418       /* Reserved */
419       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
420     case 0x9F:
421       /* Indefinite length array */
422       {
423         callbacks->indef_array_start(context);
424         return result;
425       }
426     case 0xA0: /* Fallthrough */
427     case 0xA1: /* Fallthrough */
428     case 0xA2: /* Fallthrough */
429     case 0xA3: /* Fallthrough */
430     case 0xA4: /* Fallthrough */
431     case 0xA5: /* Fallthrough */
432     case 0xA6: /* Fallthrough */
433     case 0xA7: /* Fallthrough */
434     case 0xA8: /* Fallthrough */
435     case 0xA9: /* Fallthrough */
436     case 0xAA: /* Fallthrough */
437     case 0xAB: /* Fallthrough */
438     case 0xAC: /* Fallthrough */
439     case 0xAD: /* Fallthrough */
440     case 0xAE: /* Fallthrough */
441     case 0xAF: /* Fallthrough */
442     case 0xB0: /* Fallthrough */
443     case 0xB1: /* Fallthrough */
444     case 0xB2: /* Fallthrough */
445     case 0xB3: /* Fallthrough */
446     case 0xB4: /* Fallthrough */
447     case 0xB5: /* Fallthrough */
448     case 0xB6: /* Fallthrough */
449     case 0xB7:
450       /* Embedded one byte length map */
451       {
452         callbacks->map_start(
453             context, (size_t)_cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */
454         return result;
455       }
456     case 0xB8:
457       /* One byte length map */
458       {
459         if (_cbor_claim_bytes(1, source_size, &result)) {
460           callbacks->map_start(context, (size_t)_cbor_load_uint8(source + 1));
461         }
462         return result;
463       }
464     case 0xB9:
465       /* Two bytes length map */
466       {
467         if (_cbor_claim_bytes(2, source_size, &result)) {
468           callbacks->map_start(context, (size_t)_cbor_load_uint16(source + 1));
469         }
470         return result;
471       }
472     case 0xBA:
473       /* Four bytes length map */
474       {
475         if (_cbor_claim_bytes(4, source_size, &result)) {
476           callbacks->map_start(context, (size_t)_cbor_load_uint32(source + 1));
477         }
478         return result;
479       }
480     case 0xBB:
481       /* Eight bytes length map */
482       {
483         if (_cbor_claim_bytes(8, source_size, &result)) {
484           callbacks->map_start(context, (size_t)_cbor_load_uint64(source + 1));
485         }
486         return result;
487       }
488     case 0xBC: /* Fallthrough */
489     case 0xBD: /* Fallthrough */
490     case 0xBE:
491       /* Reserved */
492       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
493     case 0xBF:
494       /* Indefinite length map */
495       {
496         callbacks->indef_map_start(context);
497         return result;
498       }
499     case 0xC0:
500       /* Text date/time - RFC 3339 tag, fallthrough */
501     case 0xC1:
502       /* Epoch date tag, fallthrough */
503     case 0xC2:
504       /* Positive bignum tag, fallthrough */
505     case 0xC3:
506       /* Negative bignum tag, fallthrough */
507     case 0xC4:
508       /* Fraction, fallthrough */
509     case 0xC5:
510       /* Big float */
511       {
512         callbacks->tag(context,
513                        _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
514         return result;
515       }
516     case 0xC6: /* Fallthrough */
517     case 0xC7: /* Fallthrough */
518     case 0xC8: /* Fallthrough */
519     case 0xC9: /* Fallthrough */
520     case 0xCA: /* Fallthrough */
521     case 0xCB: /* Fallthrough */
522     case 0xCC: /* Fallthrough */
523     case 0xCD: /* Fallthrough */
524     case 0xCE: /* Fallthrough */
525     case 0xCF: /* Fallthrough */
526     case 0xD0: /* Fallthrough */
527     case 0xD1: /* Fallthrough */
528     case 0xD2: /* Fallthrough */
529     case 0xD3: /* Fallthrough */
530     case 0xD4: /* Unassigned tag value */
531     {
532       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
533     }
534     case 0xD5: /* Expected b64url conversion tag - fallthrough */
535     case 0xD6: /* Expected b64 conversion tag - fallthrough */
536     case 0xD7: /* Expected b16 conversion tag */
537     {
538       callbacks->tag(context,
539                      _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
540       return result;
541     }
542     case 0xD8: /* 1B tag */
543     {
544       if (_cbor_claim_bytes(1, source_size, &result)) {
545         callbacks->tag(context, _cbor_load_uint8(source + 1));
546       }
547       return result;
548     }
549     case 0xD9: /* 2B tag */
550     {
551       if (_cbor_claim_bytes(2, source_size, &result)) {
552         callbacks->tag(context, _cbor_load_uint16(source + 1));
553       }
554       return result;
555     }
556     case 0xDA: /* 4B tag */
557     {
558       if (_cbor_claim_bytes(4, source_size, &result)) {
559         callbacks->tag(context, _cbor_load_uint32(source + 1));
560       }
561       return result;
562     }
563     case 0xDB: /* 8B tag */
564     {
565       if (_cbor_claim_bytes(8, source_size, &result)) {
566         callbacks->tag(context, _cbor_load_uint64(source + 1));
567       }
568       return result;
569     }
570     case 0xDC: /* Fallthrough */
571     case 0xDD: /* Fallthrough */
572     case 0xDE: /* Fallthrough */
573     case 0xDF: /* Reserved */
574     {
575       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
576     }
577     case 0xE0: /* Fallthrough */
578     case 0xE1: /* Fallthrough */
579     case 0xE2: /* Fallthrough */
580     case 0xE3: /* Fallthrough */
581     case 0xE4: /* Fallthrough */
582     case 0xE5: /* Fallthrough */
583     case 0xE6: /* Fallthrough */
584     case 0xE7: /* Fallthrough */
585     case 0xE8: /* Fallthrough */
586     case 0xE9: /* Fallthrough */
587     case 0xEA: /* Fallthrough */
588     case 0xEB: /* Fallthrough */
589     case 0xEC: /* Fallthrough */
590     case 0xED: /* Fallthrough */
591     case 0xEE: /* Fallthrough */
592     case 0xEF: /* Fallthrough */
593     case 0xF0: /* Fallthrough */
594     case 0xF1: /* Fallthrough */
595     case 0xF2: /* Fallthrough */
596     case 0xF3: /* Simple value - unassigned */
597     {
598       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
599     }
600     case 0xF4:
601       /* False */
602       {
603         callbacks->boolean(context, false);
604         return result;
605       }
606     case 0xF5:
607       /* True */
608       {
609         callbacks->boolean(context, true);
610         return result;
611       }
612     case 0xF6:
613       /* Null */
614       {
615         callbacks->null(context);
616         return result;
617       }
618     case 0xF7:
619       /* Undefined */
620       {
621         callbacks->undefined(context);
622         return result;
623       }
624     case 0xF8:
625       /* 1B simple value, unassigned */
626       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
627     case 0xF9:
628       /* 2B float */
629       {
630         if (_cbor_claim_bytes(2, source_size, &result)) {
631           callbacks->float2(context, _cbor_load_half(source + 1));
632         }
633         return result;
634       }
635     case 0xFA:
636       /* 4B float */
637       {
638         if (_cbor_claim_bytes(4, source_size, &result)) {
639           callbacks->float4(context, _cbor_load_float(source + 1));
640         }
641         return result;
642       }
643     case 0xFB:
644       /* 8B float */
645       {
646         if (_cbor_claim_bytes(8, source_size, &result)) {
647           callbacks->float8(context, _cbor_load_double(source + 1));
648         }
649         return result;
650       }
651     case 0xFC: /* Fallthrough */
652     case 0xFD: /* Fallthrough */
653     case 0xFE:
654       /* Reserved */
655       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
656     case 0xFF:
657       /* Break */
658       {
659         callbacks->indef_break(context);
660         return result;
661       }
662     default: /* Never happens - this shuts up the compiler */
663     {
664       return result;
665     }
666   }
667 }
668