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
cbor_load(cbor_data source,size_t source_size,struct cbor_load_result * result)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
_cbor_copy_int(cbor_item_t * item,bool negative)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
_cbor_copy_float_ctrl(cbor_item_t * item)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
cbor_copy(cbor_item_t * item)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
cbor_copy_definite(cbor_item_t * item)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
_pow(int b,int ex)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
_cbor_type_marquee(FILE * out,char * label,int indent)446 static void _cbor_type_marquee(FILE* out, char* label, int indent) {
447 fprintf(out, "%*.*s[%s] ", indent, indent, " ", label);
448 }
449
_cbor_nested_describe(cbor_item_t * item,FILE * out,int indent)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
cbor_describe(cbor_item_t * item,FILE * out)565 void cbor_describe(cbor_item_t* item, FILE* out) {
566 _cbor_nested_describe(item, out, 0);
567 }
568
569 #endif
570