Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libcbor/src/cbor/streaming.c
39507 views
1
/*
2
* Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]>
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
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
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
602