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