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 <stdbool.h> 9 #include <string.h> 10 11 #include "cbor.h" 12 #include "cbor/internal/builder_callbacks.h" 13 #include "cbor/internal/loaders.h" 14 15 cbor_item_t* cbor_load(cbor_data source, size_t source_size, 16 struct cbor_load_result* result) { 17 /* Context stack */ 18 static struct cbor_callbacks callbacks = { 19 .uint8 = &cbor_builder_uint8_callback, 20 .uint16 = &cbor_builder_uint16_callback, 21 .uint32 = &cbor_builder_uint32_callback, 22 .uint64 = &cbor_builder_uint64_callback, 23 24 .negint8 = &cbor_builder_negint8_callback, 25 .negint16 = &cbor_builder_negint16_callback, 26 .negint32 = &cbor_builder_negint32_callback, 27 .negint64 = &cbor_builder_negint64_callback, 28 29 .byte_string = &cbor_builder_byte_string_callback, 30 .byte_string_start = &cbor_builder_byte_string_start_callback, 31 32 .string = &cbor_builder_string_callback, 33 .string_start = &cbor_builder_string_start_callback, 34 35 .array_start = &cbor_builder_array_start_callback, 36 .indef_array_start = &cbor_builder_indef_array_start_callback, 37 38 .map_start = &cbor_builder_map_start_callback, 39 .indef_map_start = &cbor_builder_indef_map_start_callback, 40 41 .tag = &cbor_builder_tag_callback, 42 43 .null = &cbor_builder_null_callback, 44 .undefined = &cbor_builder_undefined_callback, 45 .boolean = &cbor_builder_boolean_callback, 46 .float2 = &cbor_builder_float2_callback, 47 .float4 = &cbor_builder_float4_callback, 48 .float8 = &cbor_builder_float8_callback, 49 .indef_break = &cbor_builder_indef_break_callback}; 50 51 if (source_size == 0) { 52 result->error.code = CBOR_ERR_NODATA; 53 return NULL; 54 } 55 struct _cbor_stack stack = _cbor_stack_init(); 56 57 /* Target for callbacks */ 58 struct _cbor_decoder_context context = (struct _cbor_decoder_context){ 59 .stack = &stack, .creation_failed = false, .syntax_error = false}; 60 struct cbor_decoder_result decode_result; 61 *result = 62 (struct cbor_load_result){.read = 0, .error = {.code = CBOR_ERR_NONE}}; 63 64 do { 65 if (source_size > result->read) { /* Check for overflows */ 66 decode_result = 67 cbor_stream_decode(source + result->read, source_size - result->read, 68 &callbacks, &context); 69 } else { 70 result->error = (struct cbor_error){.code = CBOR_ERR_NOTENOUGHDATA, 71 .position = result->read}; 72 goto error; 73 } 74 75 switch (decode_result.status) { 76 case CBOR_DECODER_FINISHED: 77 /* Everything OK */ 78 { 79 result->read += decode_result.read; 80 break; 81 } 82 case CBOR_DECODER_NEDATA: 83 /* Data length doesn't match MTB expectation */ 84 { 85 result->error.code = CBOR_ERR_NOTENOUGHDATA; 86 goto error; 87 } 88 case CBOR_DECODER_ERROR: 89 /* Reserved/malformed item */ 90 { 91 result->error.code = CBOR_ERR_MALFORMATED; 92 goto error; 93 } 94 } 95 96 if (context.creation_failed) { 97 /* Most likely unsuccessful allocation - our callback has failed */ 98 result->error.code = CBOR_ERR_MEMERROR; 99 goto error; 100 } else if (context.syntax_error) { 101 result->error.code = CBOR_ERR_SYNTAXERROR; 102 goto error; 103 } 104 } while (stack.size > 0); 105 106 return context.root; 107 108 error: 109 result->error.position = result->read; 110 // debug_print("Failed with decoder error %d at %d\n", result->error.code, 111 // result->error.position); cbor_describe(stack.top->item, stdout); 112 /* Free the stack */ 113 while (stack.size > 0) { 114 cbor_decref(&stack.top->item); 115 _cbor_stack_pop(&stack); 116 } 117 return NULL; 118 } 119 120 static cbor_item_t* _cbor_copy_int(cbor_item_t* item, bool negative) { 121 CBOR_ASSERT(cbor_isa_uint(item) || cbor_isa_negint(item)); 122 CBOR_ASSERT(cbor_int_get_width(item) >= CBOR_INT_8 && 123 cbor_int_get_width(item) <= CBOR_INT_64); 124 cbor_item_t* res = NULL; 125 switch (cbor_int_get_width(item)) { 126 case CBOR_INT_8: 127 res = cbor_build_uint8(cbor_get_uint8(item)); 128 break; 129 case CBOR_INT_16: 130 res = cbor_build_uint16(cbor_get_uint16(item)); 131 break; 132 case CBOR_INT_32: 133 res = cbor_build_uint32(cbor_get_uint32(item)); 134 break; 135 case CBOR_INT_64: 136 res = cbor_build_uint64(cbor_get_uint64(item)); 137 break; 138 } 139 140 if (negative) cbor_mark_negint(res); 141 142 return res; 143 } 144 145 static cbor_item_t* _cbor_copy_float_ctrl(cbor_item_t* item) { 146 CBOR_ASSERT(cbor_isa_float_ctrl(item)); 147 CBOR_ASSERT(cbor_float_get_width(item) >= CBOR_FLOAT_0 && 148 cbor_float_get_width(item) <= CBOR_FLOAT_64); 149 switch (cbor_float_get_width(item)) { 150 case CBOR_FLOAT_0: 151 return cbor_build_ctrl(cbor_ctrl_value(item)); 152 case CBOR_FLOAT_16: 153 return cbor_build_float2(cbor_float_get_float2(item)); 154 case CBOR_FLOAT_32: 155 return cbor_build_float4(cbor_float_get_float4(item)); 156 case CBOR_FLOAT_64: 157 return cbor_build_float8(cbor_float_get_float8(item)); 158 default: // LCOV_EXCL_START 159 _CBOR_UNREACHABLE; 160 return NULL; // LCOV_EXCL_START 161 } 162 } 163 164 cbor_item_t* cbor_copy(cbor_item_t* item) { 165 CBOR_ASSERT_VALID_TYPE(cbor_typeof(item)); 166 switch (cbor_typeof(item)) { 167 case CBOR_TYPE_UINT: 168 return _cbor_copy_int(item, false); 169 case CBOR_TYPE_NEGINT: 170 return _cbor_copy_int(item, true); 171 case CBOR_TYPE_BYTESTRING: 172 if (cbor_bytestring_is_definite(item)) { 173 return cbor_build_bytestring(cbor_bytestring_handle(item), 174 cbor_bytestring_length(item)); 175 } else { 176 cbor_item_t* res = cbor_new_indefinite_bytestring(); 177 if (res == NULL) { 178 return NULL; 179 } 180 181 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { 182 cbor_item_t* chunk_copy = 183 cbor_copy(cbor_bytestring_chunks_handle(item)[i]); 184 if (chunk_copy == NULL) { 185 cbor_decref(&res); 186 return NULL; 187 } 188 if (!cbor_bytestring_add_chunk(res, chunk_copy)) { 189 cbor_decref(&chunk_copy); 190 cbor_decref(&res); 191 return NULL; 192 } 193 cbor_decref(&chunk_copy); 194 } 195 return res; 196 } 197 case CBOR_TYPE_STRING: 198 if (cbor_string_is_definite(item)) { 199 return cbor_build_stringn((const char*)cbor_string_handle(item), 200 cbor_string_length(item)); 201 } else { 202 cbor_item_t* res = cbor_new_indefinite_string(); 203 if (res == NULL) { 204 return NULL; 205 } 206 207 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { 208 cbor_item_t* chunk_copy = 209 cbor_copy(cbor_string_chunks_handle(item)[i]); 210 if (chunk_copy == NULL) { 211 cbor_decref(&res); 212 return NULL; 213 } 214 if (!cbor_string_add_chunk(res, chunk_copy)) { 215 cbor_decref(&chunk_copy); 216 cbor_decref(&res); 217 return NULL; 218 } 219 cbor_decref(&chunk_copy); 220 } 221 return res; 222 } 223 case CBOR_TYPE_ARRAY: { 224 cbor_item_t* res; 225 if (cbor_array_is_definite(item)) { 226 res = cbor_new_definite_array(cbor_array_size(item)); 227 } else { 228 res = cbor_new_indefinite_array(); 229 } 230 if (res == NULL) { 231 return NULL; 232 } 233 234 for (size_t i = 0; i < cbor_array_size(item); i++) { 235 cbor_item_t* entry_copy = cbor_copy(cbor_move(cbor_array_get(item, i))); 236 if (entry_copy == NULL) { 237 cbor_decref(&res); 238 return NULL; 239 } 240 if (!cbor_array_push(res, entry_copy)) { 241 cbor_decref(&entry_copy); 242 cbor_decref(&res); 243 return NULL; 244 } 245 cbor_decref(&entry_copy); 246 } 247 return res; 248 } 249 case CBOR_TYPE_MAP: { 250 cbor_item_t* res; 251 if (cbor_map_is_definite(item)) { 252 res = cbor_new_definite_map(cbor_map_size(item)); 253 } else { 254 res = cbor_new_indefinite_map(); 255 } 256 if (res == NULL) { 257 return NULL; 258 } 259 260 struct cbor_pair* it = cbor_map_handle(item); 261 for (size_t i = 0; i < cbor_map_size(item); i++) { 262 cbor_item_t* key_copy = cbor_copy(it[i].key); 263 if (key_copy == NULL) { 264 cbor_decref(&res); 265 return NULL; 266 } 267 cbor_item_t* value_copy = cbor_copy(it[i].value); 268 if (value_copy == NULL) { 269 cbor_decref(&res); 270 cbor_decref(&key_copy); 271 return NULL; 272 } 273 if (!cbor_map_add(res, (struct cbor_pair){.key = key_copy, 274 .value = value_copy})) { 275 cbor_decref(&res); 276 cbor_decref(&key_copy); 277 cbor_decref(&value_copy); 278 return NULL; 279 } 280 cbor_decref(&key_copy); 281 cbor_decref(&value_copy); 282 } 283 return res; 284 } 285 case CBOR_TYPE_TAG: { 286 cbor_item_t* item_copy = cbor_copy(cbor_move(cbor_tag_item(item))); 287 if (item_copy == NULL) { 288 return NULL; 289 } 290 cbor_item_t* tag = cbor_build_tag(cbor_tag_value(item), item_copy); 291 cbor_decref(&item_copy); 292 return tag; 293 } 294 case CBOR_TYPE_FLOAT_CTRL: 295 return _cbor_copy_float_ctrl(item); 296 default: // LCOV_EXCL_START 297 _CBOR_UNREACHABLE; 298 return NULL; // LCOV_EXCL_STOP 299 } 300 } 301 302 cbor_item_t* cbor_copy_definite(cbor_item_t* item) { 303 CBOR_ASSERT_VALID_TYPE(cbor_typeof(item)); 304 switch (cbor_typeof(item)) { 305 case CBOR_TYPE_UINT: 306 case CBOR_TYPE_NEGINT: 307 return cbor_copy(item); 308 case CBOR_TYPE_BYTESTRING: 309 if (cbor_bytestring_is_definite(item)) { 310 return cbor_copy(item); 311 } else { 312 size_t total_length = 0; 313 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { 314 total_length += 315 cbor_bytestring_length(cbor_bytestring_chunks_handle(item)[i]); 316 } 317 318 unsigned char* combined_data = _cbor_malloc(total_length); 319 if (combined_data == NULL) { 320 return NULL; 321 } 322 323 size_t offset = 0; 324 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { 325 cbor_item_t* chunk = cbor_bytestring_chunks_handle(item)[i]; 326 memcpy(combined_data + offset, cbor_bytestring_handle(chunk), 327 cbor_bytestring_length(chunk)); 328 offset += cbor_bytestring_length(chunk); 329 } 330 331 cbor_item_t* res = cbor_new_definite_bytestring(); 332 cbor_bytestring_set_handle(res, combined_data, total_length); 333 return res; 334 } 335 case CBOR_TYPE_STRING: 336 if (cbor_string_is_definite(item)) { 337 return cbor_copy(item); 338 } else { 339 size_t total_length = 0; 340 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { 341 total_length += 342 cbor_string_length(cbor_string_chunks_handle(item)[i]); 343 } 344 345 unsigned char* combined_data = _cbor_malloc(total_length); 346 if (combined_data == NULL) { 347 return NULL; 348 } 349 350 size_t offset = 0; 351 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { 352 cbor_item_t* chunk = cbor_string_chunks_handle(item)[i]; 353 memcpy(combined_data + offset, cbor_string_handle(chunk), 354 cbor_string_length(chunk)); 355 offset += cbor_string_length(chunk); 356 } 357 358 cbor_item_t* res = cbor_new_definite_string(); 359 cbor_string_set_handle(res, combined_data, total_length); 360 return res; 361 } 362 case CBOR_TYPE_ARRAY: { 363 cbor_item_t* res = cbor_new_definite_array(cbor_array_size(item)); 364 if (res == NULL) { 365 return NULL; 366 } 367 368 for (size_t i = 0; i < cbor_array_size(item); i++) { 369 cbor_item_t* entry_copy = 370 cbor_copy_definite(cbor_array_handle(item)[i]); 371 if (entry_copy == NULL) { 372 cbor_decref(&res); 373 return NULL; 374 } 375 // Cannot fail since we have a definite array preallocated 376 // cppcheck-suppress syntaxError 377 const bool item_pushed _CBOR_UNUSED = cbor_array_push(res, entry_copy); 378 CBOR_ASSERT(item_pushed); 379 cbor_decref(&entry_copy); 380 } 381 return res; 382 } 383 case CBOR_TYPE_MAP: { 384 cbor_item_t* res; 385 res = cbor_new_definite_map(cbor_map_size(item)); 386 if (res == NULL) { 387 return NULL; 388 } 389 390 struct cbor_pair* it = cbor_map_handle(item); 391 for (size_t i = 0; i < cbor_map_size(item); i++) { 392 cbor_item_t* key_copy = cbor_copy_definite(it[i].key); 393 if (key_copy == NULL) { 394 cbor_decref(&res); 395 return NULL; 396 } 397 cbor_item_t* value_copy = cbor_copy_definite(it[i].value); 398 if (value_copy == NULL) { 399 cbor_decref(&res); 400 cbor_decref(&key_copy); 401 return NULL; 402 } 403 // Cannot fail since we have a definite map preallocated 404 // cppcheck-suppress syntaxError 405 const bool item_added _CBOR_UNUSED = cbor_map_add( 406 res, (struct cbor_pair){.key = key_copy, .value = value_copy}); 407 CBOR_ASSERT(item_added); 408 cbor_decref(&key_copy); 409 cbor_decref(&value_copy); 410 } 411 return res; 412 } 413 case CBOR_TYPE_TAG: { 414 cbor_item_t* item_copy = 415 cbor_copy_definite(cbor_move(cbor_tag_item(item))); 416 if (item_copy == NULL) { 417 return NULL; 418 } 419 cbor_item_t* tag = cbor_build_tag(cbor_tag_value(item), item_copy); 420 cbor_decref(&item_copy); 421 return tag; 422 } 423 case CBOR_TYPE_FLOAT_CTRL: 424 return cbor_copy(item); 425 default: // LCOV_EXCL_START 426 _CBOR_UNREACHABLE; 427 return NULL; // LCOV_EXCL_STOP 428 } 429 } 430 431 #if CBOR_PRETTY_PRINTER 432 433 #include <inttypes.h> 434 #include <locale.h> 435 #include <wchar.h> 436 437 #define __STDC_FORMAT_MACROS 438 439 static int _pow(int b, int ex) { 440 if (ex == 0) return 1; 441 int res = b; 442 while (--ex > 0) res *= b; 443 return res; 444 } 445 446 static void _cbor_type_marquee(FILE* out, char* label, int indent) { 447 fprintf(out, "%*.*s[%s] ", indent, indent, " ", label); 448 } 449 450 static void _cbor_nested_describe(cbor_item_t* item, FILE* out, int indent) { 451 CBOR_ASSERT(cbor_typeof(item) >= CBOR_TYPE_UINT && 452 cbor_typeof(item) <= CBOR_TYPE_FLOAT_CTRL); 453 const int indent_offset = 4; 454 switch (cbor_typeof(item)) { 455 case CBOR_TYPE_UINT: { 456 _cbor_type_marquee(out, "CBOR_TYPE_UINT", indent); 457 fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); 458 fprintf(out, "Value: %" PRIu64 "\n", cbor_get_int(item)); 459 break; 460 } 461 case CBOR_TYPE_NEGINT: { 462 _cbor_type_marquee(out, "CBOR_TYPE_NEGINT", indent); 463 fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); 464 fprintf(out, "Value: -%" PRIu64 " - 1\n", cbor_get_int(item)); 465 break; 466 } 467 case CBOR_TYPE_BYTESTRING: { 468 _cbor_type_marquee(out, "CBOR_TYPE_BYTESTRING", indent); 469 if (cbor_bytestring_is_indefinite(item)) { 470 fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n", 471 cbor_bytestring_chunk_count(item)); 472 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) 473 _cbor_nested_describe(cbor_bytestring_chunks_handle(item)[i], out, 474 indent + indent_offset); 475 } else { 476 const unsigned char* data = cbor_bytestring_handle(item); 477 fprintf(out, "Definite, Length: %zuB, Data:\n", 478 cbor_bytestring_length(item)); 479 fprintf(out, "%*s", indent + indent_offset, " "); 480 for (size_t i = 0; i < cbor_bytestring_length(item); i++) 481 fprintf(out, "%02x", (int)(data[i] & 0xff)); 482 fprintf(out, "\n"); 483 } 484 break; 485 } 486 case CBOR_TYPE_STRING: { 487 _cbor_type_marquee(out, "CBOR_TYPE_STRING", indent); 488 if (cbor_string_is_indefinite(item)) { 489 fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n", 490 cbor_string_chunk_count(item)); 491 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) 492 _cbor_nested_describe(cbor_string_chunks_handle(item)[i], out, 493 indent + indent_offset); 494 } else { 495 fprintf(out, "Definite, Length: %zuB, Codepoints: %zu, Data:\n", 496 cbor_string_length(item), cbor_string_codepoint_count(item)); 497 fprintf(out, "%*s", indent + indent_offset, " "); 498 // Note: The string is not escaped, whitespace and control character 499 // will be printed in verbatim and take effect. 500 fwrite(cbor_string_handle(item), sizeof(unsigned char), 501 cbor_string_length(item), out); 502 fprintf(out, "\n"); 503 } 504 break; 505 } 506 case CBOR_TYPE_ARRAY: { 507 _cbor_type_marquee(out, "CBOR_TYPE_ARRAY", indent); 508 if (cbor_array_is_definite(item)) { 509 fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_array_size(item)); 510 } else { 511 fprintf(out, "Indefinite, Size: %zu, Contents:\n", 512 cbor_array_size(item)); 513 } 514 515 for (size_t i = 0; i < cbor_array_size(item); i++) 516 _cbor_nested_describe(cbor_array_handle(item)[i], out, 517 indent + indent_offset); 518 break; 519 } 520 case CBOR_TYPE_MAP: { 521 _cbor_type_marquee(out, "CBOR_TYPE_MAP", indent); 522 if (cbor_map_is_definite(item)) { 523 fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_map_size(item)); 524 } else { 525 fprintf(out, "Indefinite, Size: %zu, Contents:\n", cbor_map_size(item)); 526 } 527 528 // TODO: Label and group keys and values 529 for (size_t i = 0; i < cbor_map_size(item); i++) { 530 fprintf(out, "%*sMap entry %zu\n", indent + indent_offset, " ", i); 531 _cbor_nested_describe(cbor_map_handle(item)[i].key, out, 532 indent + 2 * indent_offset); 533 _cbor_nested_describe(cbor_map_handle(item)[i].value, out, 534 indent + 2 * indent_offset); 535 } 536 break; 537 } 538 case CBOR_TYPE_TAG: { 539 _cbor_type_marquee(out, "CBOR_TYPE_TAG", indent); 540 fprintf(out, "Value: %" PRIu64 "\n", cbor_tag_value(item)); 541 _cbor_nested_describe(cbor_move(cbor_tag_item(item)), out, 542 indent + indent_offset); 543 break; 544 } 545 case CBOR_TYPE_FLOAT_CTRL: { 546 _cbor_type_marquee(out, "CBOR_TYPE_FLOAT_CTRL", indent); 547 if (cbor_float_ctrl_is_ctrl(item)) { 548 if (cbor_is_bool(item)) 549 fprintf(out, "Bool: %s\n", cbor_get_bool(item) ? "true" : "false"); 550 else if (cbor_is_undef(item)) 551 fprintf(out, "Undefined\n"); 552 else if (cbor_is_null(item)) 553 fprintf(out, "Null\n"); 554 else 555 fprintf(out, "Simple value: %d\n", cbor_ctrl_value(item)); 556 } else { 557 fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item))); 558 fprintf(out, "Value: %lf\n", cbor_float_get_float(item)); 559 } 560 break; 561 } 562 } 563 } 564 565 void cbor_describe(cbor_item_t* item, FILE* out) { 566 _cbor_nested_describe(item, out, 0); 567 } 568 569 #endif 570