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