From: djm Date: Sat, 31 Dec 2022 03:35:21 +0000 (+0000) Subject: update to upstream libcbor v.0.10.0 and crank major. Also includes X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=4dcc46c4d04180142eda526ce521dfb137776d05;p=openbsd update to upstream libcbor v.0.10.0 and crank major. Also includes e308674c5d to fix PR259. This release includes a number of memory leak fixes. Disable the upsteam custom allocators feature. Feedback/ok tb@ Thanks also to Pedro Martelletto for pointing out the new release as well as PR259. --- diff --git a/lib/libcbor/Makefile b/lib/libcbor/Makefile index 204997cb948..561cba6e4bc 100644 --- a/lib/libcbor/Makefile +++ b/lib/libcbor/Makefile @@ -1,8 +1,10 @@ -# $OpenBSD: Makefile,v 1.3 2020/08/03 02:34:31 djm Exp $ +# $OpenBSD: Makefile,v 1.4 2022/12/31 03:35:21 djm Exp $ .PATH: ${.CURDIR}/src ${.CURDIR}/src/cbor ${.CURDIR}/src/cbor/internal CFLAGS+= -I${.CURDIR}/src -DHAVE_ENDIAN_H -std=c99 +# We don't support custom allocators. +CFLAGS+= -D_cbor_malloc=malloc -D_cbor_realloc=realloc -D_cbor_free=free LIB= cbor SRCS= cbor.c @@ -26,6 +28,8 @@ HDRS+= cbor/arrays.h cbor/bytestrings.h cbor/callbacks.h cbor/common.h HDRS+= cbor/configuration.h cbor/data.h cbor/encoding.h cbor/floats_ctrls.h HDRS+= cbor/ints.h cbor/maps.h cbor/serialization.h cbor/streaming.h HDRS+= cbor/strings.h cbor/tags.h +# This file is generated by upstream's CMake rules. +HDRS+= cbor/cbor_export.h NOMAN= diff --git a/lib/libcbor/README.md b/lib/libcbor/README.md index 0b897564d03..bd762436b7e 100644 --- a/lib/libcbor/README.md +++ b/lib/libcbor/README.md @@ -22,7 +22,7 @@ Get the latest documentation at [libcbor.readthedocs.org](http://libcbor.readthe ## Contributions -All bug reports and contributions are welcome. Please see https://github.com/PJK/libcbor for more info. +Bug reports and contributions are welcome. Please see [CONTRIBUTING.md](https://github.com/PJK/libcbor/blob/master/CONTRIBUTING.md) for more info. Kudos to all the [contributors](https://github.com/PJK/libcbor/graphs/contributors)! diff --git a/lib/libcbor/README.openbsd b/lib/libcbor/README.openbsd index add7f5024f9..a811509a0b0 100644 --- a/lib/libcbor/README.openbsd +++ b/lib/libcbor/README.openbsd @@ -1,4 +1,9 @@ -This is an import of https://github.com/pjk/libcbor v0.7.0 +This is an import of https://github.com/pjk/libcbor v0.10.0 with +e308674c5d to fix https://github.com/PJK/libcbor/issues/259 Apart from README.md and LICENSE.md, only the src/ directory has been imported. + +Note that the custom allocator feature (cbor_set_allocs()) has been +disabled in this import and the allocation functions _cbor_malloc, etc. +are #defined to the usual libc implementations. diff --git a/lib/libcbor/shlib_version b/lib/libcbor/shlib_version index 1edea46de91..b52599a164f 100644 --- a/lib/libcbor/shlib_version +++ b/lib/libcbor/shlib_version @@ -1,2 +1,2 @@ -major=1 +major=2 minor=0 diff --git a/lib/libcbor/src/allocators.c b/lib/libcbor/src/allocators.c index 273e09321a6..43c5440ddb2 100644 --- a/lib/libcbor/src/allocators.c +++ b/lib/libcbor/src/allocators.c @@ -7,9 +7,9 @@ #include "cbor/common.h" -_cbor_malloc_t _cbor_malloc = malloc; -_cbor_realloc_t _cbor_realloc = realloc; -_cbor_free_t _cbor_free = free; +CBOR_EXPORT _cbor_malloc_t _cbor_malloc = malloc; +CBOR_EXPORT _cbor_realloc_t _cbor_realloc = realloc; +CBOR_EXPORT _cbor_free_t _cbor_free = free; void cbor_set_allocs(_cbor_malloc_t custom_malloc, _cbor_realloc_t custom_realloc, _cbor_free_t custom_free) { diff --git a/lib/libcbor/src/cbor.c b/lib/libcbor/src/cbor.c index 24e5aa3d7f3..626ddddaecf 100644 --- a/lib/libcbor/src/cbor.c +++ b/lib/libcbor/src/cbor.c @@ -82,10 +82,8 @@ cbor_item_t *cbor_load(cbor_data source, size_t source_size, result->error.code = CBOR_ERR_NOTENOUGHDATA; goto error; } - case CBOR_DECODER_EBUFFER: - /* Fallthrough */ case CBOR_DECODER_ERROR: - /* Reserved/malformated item */ + /* Reserved/malformed item */ { result->error.code = CBOR_ERR_MALFORMATED; goto error; @@ -102,9 +100,7 @@ cbor_item_t *cbor_load(cbor_data source, size_t source_size, } } while (stack.size > 0); - /* Move the result before free */ - cbor_item_t *result_item = context.root; - return result_item; + return context.root; error: result->error.position = result->read; @@ -133,8 +129,6 @@ static cbor_item_t *_cbor_copy_int(cbor_item_t *item, bool negative) { case CBOR_INT_64: res = cbor_build_uint64(cbor_get_uint64(item)); break; - default: - return NULL; } if (negative) cbor_mark_negint(res); @@ -143,6 +137,7 @@ static cbor_item_t *_cbor_copy_int(cbor_item_t *item, bool negative) { } static cbor_item_t *_cbor_copy_float_ctrl(cbor_item_t *item) { + // cppcheck-suppress missingReturn switch (cbor_float_get_width(item)) { case CBOR_FLOAT_0: return cbor_build_ctrl(cbor_ctrl_value(item)); @@ -153,11 +148,10 @@ static cbor_item_t *_cbor_copy_float_ctrl(cbor_item_t *item) { case CBOR_FLOAT_64: return cbor_build_float8(cbor_float_get_float8(item)); } - - return NULL; } cbor_item_t *cbor_copy(cbor_item_t *item) { + // cppcheck-suppress missingReturn switch (cbor_typeof(item)) { case CBOR_TYPE_UINT: return _cbor_copy_int(item, false); @@ -169,10 +163,24 @@ cbor_item_t *cbor_copy(cbor_item_t *item) { cbor_bytestring_length(item)); } else { cbor_item_t *res = cbor_new_indefinite_bytestring(); - for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) - cbor_bytestring_add_chunk( - res, - cbor_move(cbor_copy(cbor_bytestring_chunks_handle(item)[i]))); + if (res == NULL) { + return NULL; + } + + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { + cbor_item_t *chunk_copy = + cbor_copy(cbor_bytestring_chunks_handle(item)[i]); + if (chunk_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_bytestring_add_chunk(res, chunk_copy)) { + cbor_decref(&chunk_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&chunk_copy); + } return res; } case CBOR_TYPE_STRING: @@ -181,45 +189,100 @@ cbor_item_t *cbor_copy(cbor_item_t *item) { cbor_string_length(item)); } else { cbor_item_t *res = cbor_new_indefinite_string(); - for (size_t i = 0; i < cbor_string_chunk_count(item); i++) - cbor_string_add_chunk( - res, cbor_move(cbor_copy(cbor_string_chunks_handle(item)[i]))); + if (res == NULL) { + return NULL; + } + + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { + cbor_item_t *chunk_copy = + cbor_copy(cbor_string_chunks_handle(item)[i]); + if (chunk_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_string_add_chunk(res, chunk_copy)) { + cbor_decref(&chunk_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&chunk_copy); + } return res; } case CBOR_TYPE_ARRAY: { cbor_item_t *res; - if (cbor_array_is_definite(item)) + if (cbor_array_is_definite(item)) { res = cbor_new_definite_array(cbor_array_size(item)); - else + } else { res = cbor_new_indefinite_array(); + } + if (res == NULL) { + return NULL; + } - for (size_t i = 0; i < cbor_array_size(item); i++) - cbor_array_push( - res, cbor_move(cbor_copy(cbor_move(cbor_array_get(item, i))))); + for (size_t i = 0; i < cbor_array_size(item); i++) { + cbor_item_t *entry_copy = cbor_copy(cbor_move(cbor_array_get(item, i))); + if (entry_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_array_push(res, entry_copy)) { + cbor_decref(&entry_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&entry_copy); + } return res; } case CBOR_TYPE_MAP: { cbor_item_t *res; - if (cbor_map_is_definite(item)) + if (cbor_map_is_definite(item)) { res = cbor_new_definite_map(cbor_map_size(item)); - else + } else { res = cbor_new_indefinite_map(); + } + if (res == NULL) { + return NULL; + } struct cbor_pair *it = cbor_map_handle(item); - for (size_t i = 0; i < cbor_map_size(item); i++) - cbor_map_add(res, (struct cbor_pair){ - .key = cbor_move(cbor_copy(it[i].key)), - .value = cbor_move(cbor_copy(it[i].value))}); + for (size_t i = 0; i < cbor_map_size(item); i++) { + cbor_item_t *key_copy = cbor_copy(it[i].key); + if (key_copy == NULL) { + cbor_decref(&res); + return NULL; + } + cbor_item_t *value_copy = cbor_copy(it[i].value); + if (value_copy == NULL) { + cbor_decref(&res); + cbor_decref(&key_copy); + return NULL; + } + if (!cbor_map_add(res, (struct cbor_pair){.key = key_copy, + .value = value_copy})) { + cbor_decref(&res); + cbor_decref(&key_copy); + cbor_decref(&value_copy); + return NULL; + } + cbor_decref(&key_copy); + cbor_decref(&value_copy); + } return res; } - case CBOR_TYPE_TAG: - return cbor_build_tag(cbor_tag_value(item), - cbor_move(cbor_copy(cbor_tag_item(item)))); + case CBOR_TYPE_TAG: { + cbor_item_t *item_copy = cbor_copy(cbor_move(cbor_tag_item(item))); + if (item_copy == NULL) { + return NULL; + } + cbor_item_t *tag = cbor_build_tag(cbor_tag_value(item), item_copy); + cbor_decref(&item_copy); + return tag; + } case CBOR_TYPE_FLOAT_CTRL: return _cbor_copy_float_ctrl(item); } - - return NULL; } #if CBOR_PRETTY_PRINTER @@ -246,13 +309,13 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); fprintf(out, "Value: %" PRIu64 "\n", cbor_get_int(item)); break; - }; + } case CBOR_TYPE_NEGINT: { fprintf(out, "%*s[CBOR_TYPE_NEGINT] ", indent, " "); fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); fprintf(out, "Value: -%" PRIu64 " -1\n", cbor_get_int(item)); break; - }; + } case CBOR_TYPE_BYTESTRING: { fprintf(out, "%*s[CBOR_TYPE_BYTESTRING] ", indent, " "); if (cbor_bytestring_is_indefinite(item)) { @@ -265,7 +328,7 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { fprintf(out, "Definite, length %zuB\n", cbor_bytestring_length(item)); } break; - }; + } case CBOR_TYPE_STRING: { fprintf(out, "%*s[CBOR_TYPE_STRING] ", indent, " "); if (cbor_string_is_indefinite(item)) { @@ -286,7 +349,7 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { fprintf(out, "\n"); } break; - }; + } case CBOR_TYPE_ARRAY: { fprintf(out, "%*s[CBOR_TYPE_ARRAY] ", indent, " "); if (cbor_array_is_definite(item)) { @@ -298,7 +361,7 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { for (size_t i = 0; i < cbor_array_size(item); i++) _cbor_nested_describe(cbor_array_handle(item)[i], out, indent + 4); break; - }; + } case CBOR_TYPE_MAP: { fprintf(out, "%*s[CBOR_TYPE_MAP] ", indent, " "); if (cbor_map_is_definite(item)) { @@ -312,13 +375,13 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { _cbor_nested_describe(cbor_map_handle(item)[i].value, out, indent + 4); } break; - }; + } case CBOR_TYPE_TAG: { fprintf(out, "%*s[CBOR_TYPE_TAG] ", indent, " "); fprintf(out, "Value: %" PRIu64 "\n", cbor_tag_value(item)); - _cbor_nested_describe(cbor_tag_item(item), out, indent + 4); + _cbor_nested_describe(cbor_move(cbor_tag_item(item)), out, indent + 4); break; - }; + } case CBOR_TYPE_FLOAT_CTRL: { fprintf(out, "%*s[CBOR_TYPE_FLOAT_CTRL] ", indent, " "); if (cbor_float_ctrl_is_ctrl(item)) { @@ -335,7 +398,7 @@ static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { fprintf(out, "value: %lf\n", cbor_float_get_float(item)); } break; - }; + } } } diff --git a/lib/libcbor/src/cbor.h b/lib/libcbor/src/cbor.h index f4dfc9e3d75..f3860107947 100644 --- a/lib/libcbor/src/cbor.h +++ b/lib/libcbor/src/cbor.h @@ -20,6 +20,7 @@ #include "cbor/tags.h" #include "cbor/callbacks.h" +#include "cbor/cbor_export.h" #include "cbor/encoding.h" #include "cbor/serialization.h" #include "cbor/streaming.h" @@ -42,22 +43,22 @@ extern "C" { * @return **new** CBOR item or `NULL` on failure. In that case, \p result * contains location and description of the error. */ -cbor_item_t* cbor_load(cbor_data source, size_t source_size, - struct cbor_load_result* result); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_load( + cbor_data source, size_t source_size, struct cbor_load_result* result); -/** Deep copy of an item +/** Take a deep copy of an item * * All the reference counts in the new structure are set to one. * * @param item[borrow] item to copy - * @return **new** CBOR deep copy + * @return **new** CBOR deep copy or `NULL` on failure. */ -cbor_item_t* cbor_copy(cbor_item_t* item); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_copy(cbor_item_t* item); #if CBOR_PRETTY_PRINTER #include -void cbor_describe(cbor_item_t* item, FILE* out); +CBOR_EXPORT void cbor_describe(cbor_item_t* item, FILE* out); #endif #ifdef __cplusplus diff --git a/lib/libcbor/src/cbor/arrays.c b/lib/libcbor/src/cbor/arrays.c index c1d01afafee..a23bbe3cd15 100644 --- a/lib/libcbor/src/cbor/arrays.c +++ b/lib/libcbor/src/cbor/arrays.c @@ -10,12 +10,12 @@ #include "internal/memory_utils.h" size_t cbor_array_size(const cbor_item_t *item) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.end_ptr; } size_t cbor_array_allocated(const cbor_item_t *item) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.allocated; } @@ -31,9 +31,6 @@ bool cbor_array_set(cbor_item_t *item, size_t index, cbor_item_t *value) { } else { return false; } - // TODO: This is unreachable and the index checking logic above seems - // suspicious -- out of bounds index is a caller error. Figure out & fix. - return true; } bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value) { @@ -45,7 +42,7 @@ bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value) { } bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) { - assert(cbor_isa_array(array)); + CBOR_ASSERT(cbor_isa_array(array)); struct _cbor_array_metadata *metadata = (struct _cbor_array_metadata *)&array->metadata; cbor_item_t **data = (cbor_item_t **)array->data; @@ -59,7 +56,6 @@ bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) { /* Exponential realloc */ if (metadata->end_ptr >= metadata->allocated) { // Check for overflows first - // TODO: Explicitly test this if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { return false; } @@ -84,22 +80,22 @@ bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) { } bool cbor_array_is_definite(const cbor_item_t *item) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE; } bool cbor_array_is_indefinite(const cbor_item_t *item) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE; } cbor_item_t **cbor_array_handle(const cbor_item_t *item) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); return (cbor_item_t **)item->data; } cbor_item_t *cbor_new_definite_array(size_t size) { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); cbor_item_t **data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size); _CBOR_DEPENDENT_NOTNULL(item, data); @@ -119,8 +115,8 @@ cbor_item_t *cbor_new_definite_array(size_t size) { return item; } -cbor_item_t *cbor_new_indefinite_array() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_indefinite_array(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ diff --git a/lib/libcbor/src/cbor/arrays.h b/lib/libcbor/src/cbor/arrays.h index 38519750442..cc5a7c019b9 100644 --- a/lib/libcbor/src/cbor/arrays.h +++ b/lib/libcbor/src/cbor/arrays.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_ARRAYS_H #define LIBCBOR_ARRAYS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -19,14 +20,16 @@ extern "C" { * @param item[borrow] An array * @return The number of members */ -size_t cbor_array_size(const cbor_item_t* item); +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_array_size(const cbor_item_t* item); /** Get the size of the allocated storage * * @param item[borrow] An array * @return The size of the allocated storage (number of items) */ -size_t cbor_array_allocated(const cbor_item_t* item); +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_array_allocated(const cbor_item_t* item); /** Get item by index * @@ -34,18 +37,22 @@ size_t cbor_array_allocated(const cbor_item_t* item); * @param index The index * @return **incref** The item, or `NULL` in case of boundary violation */ -cbor_item_t* cbor_array_get(const cbor_item_t* item, size_t index); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_array_get(const cbor_item_t* item, size_t index); /** Set item by index * - * Creating arrays with holes is not possible + * If the index is out of bounds, the array is not modified and false is + * returned. Creating arrays with holes is not possible. * * @param item[borrow] An array * @param value[incref] The item to assign * @param index The index, first item is 0. * @return true on success, false on allocation failure. */ -bool cbor_array_set(cbor_item_t* item, size_t index, cbor_item_t* value); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_set(cbor_item_t* item, size_t index, + cbor_item_t* value); /** Replace item at an index * @@ -56,21 +63,25 @@ bool cbor_array_set(cbor_item_t* item, size_t index, cbor_item_t* value); * @param index The index, first item is 0. * @return true on success, false on allocation failure. */ -bool cbor_array_replace(cbor_item_t* item, size_t index, cbor_item_t* value); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_replace(cbor_item_t* item, size_t index, + cbor_item_t* value); /** Is the array definite? * * @param item[borrow] An array * @return Is the array definite? */ -bool cbor_array_is_definite(const cbor_item_t* item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_is_definite(const cbor_item_t* item); /** Is the array indefinite? * * @param item[borrow] An array * @return Is the array indefinite? */ -bool cbor_array_is_indefinite(const cbor_item_t* item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_is_indefinite(const cbor_item_t* item); /** Get the array contents * @@ -80,31 +91,35 @@ bool cbor_array_is_indefinite(const cbor_item_t* item); * @param item[borrow] An array * @return #cbor_array_size items */ -cbor_item_t** cbor_array_handle(const cbor_item_t* item); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t** cbor_array_handle(const cbor_item_t* item); /** Create new definite array * * @param size Number of slots to preallocate * @return **new** array or `NULL` upon malloc failure */ -cbor_item_t* cbor_new_definite_array(size_t size); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_new_definite_array(size_t size); /** Create new indefinite array * * @return **new** array or `NULL` upon malloc failure */ -cbor_item_t* cbor_new_indefinite_array(); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_new_indefinite_array(void); /** Append to the end * - * For indefinite items, storage may be realloacted. For definite items, only + * For indefinite items, storage may be reallocated. For definite items, only * the preallocated capacity is available. * * @param array[borrow] An array * @param pushee[incref] The item to push * @return true on success, false on failure */ -bool cbor_array_push(cbor_item_t* array, cbor_item_t* pushee); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_push(cbor_item_t* array, cbor_item_t* pushee); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/bytestrings.c b/lib/libcbor/src/cbor/bytestrings.c index 75a737bd92a..528937179ae 100644 --- a/lib/libcbor/src/cbor/bytestrings.c +++ b/lib/libcbor/src/cbor/bytestrings.c @@ -10,17 +10,17 @@ #include "internal/memory_utils.h" size_t cbor_bytestring_length(const cbor_item_t *item) { - assert(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); return item->metadata.bytestring_metadata.length; } unsigned char *cbor_bytestring_handle(const cbor_item_t *item) { - assert(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); return item->data; } bool cbor_bytestring_is_definite(const cbor_item_t *item) { - assert(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE; } @@ -28,25 +28,26 @@ bool cbor_bytestring_is_indefinite(const cbor_item_t *item) { return !cbor_bytestring_is_definite(item); } -cbor_item_t *cbor_new_definite_bytestring() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_definite_bytestring(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ .refcount = 1, .type = CBOR_TYPE_BYTESTRING, - .metadata = {.bytestring_metadata = {_CBOR_METADATA_DEFINITE, 0}}}; + .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_DEFINITE, + .length = 0}}}; return item; } -cbor_item_t *cbor_new_indefinite_bytestring() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_indefinite_bytestring(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ .refcount = 1, .type = CBOR_TYPE_BYTESTRING, .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}}, - .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))}; + .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))}; _CBOR_DEPENDENT_NOTNULL(item, item->data); *((struct cbor_indefinite_string_data *)item->data) = (struct cbor_indefinite_string_data){ @@ -60,7 +61,7 @@ cbor_item_t *cbor_new_indefinite_bytestring() { cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) { cbor_item_t *item = cbor_new_definite_bytestring(); _CBOR_NOTNULL(item); - void *content = _CBOR_MALLOC(length); + void *content = _cbor_malloc(length); _CBOR_DEPENDENT_NOTNULL(item, content); memcpy(content, handle, length); cbor_bytestring_set_handle(item, content, length); @@ -70,31 +71,32 @@ cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) { void cbor_bytestring_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length) { - assert(cbor_isa_bytestring(item)); - assert(cbor_bytestring_is_definite(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_definite(item)); item->data = data; item->metadata.bytestring_metadata.length = length; } cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) { - assert(cbor_isa_bytestring(item)); - assert(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); return ((struct cbor_indefinite_string_data *)item->data)->chunks; } size_t cbor_bytestring_chunk_count(const cbor_item_t *item) { - assert(cbor_isa_bytestring(item)); - assert(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); return ((struct cbor_indefinite_string_data *)item->data)->chunk_count; } bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { - assert(cbor_isa_bytestring(item)); - assert(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_bytestring(chunk)); + CBOR_ASSERT(cbor_bytestring_is_definite(chunk)); struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *)item->data; if (data->chunk_count == data->chunk_capacity) { - // TODO: Add a test for this if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { return false; } diff --git a/lib/libcbor/src/cbor/bytestrings.h b/lib/libcbor/src/cbor/bytestrings.h index 9f9322ca260..fecaee92f23 100644 --- a/lib/libcbor/src/cbor/bytestrings.h +++ b/lib/libcbor/src/cbor/bytestrings.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_BYTESTRINGS_H #define LIBCBOR_BYTESTRINGS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -27,21 +28,24 @@ extern "C" { * @param item[borrow] a definite bytestring * @return length of the binary data. Zero if no chunk has been attached yet */ -size_t cbor_bytestring_length(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_bytestring_length(const cbor_item_t *item); /** Is the byte string definite? * * @param item[borrow] a byte string * @return Is the byte string definite? */ -bool cbor_bytestring_is_definite(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_is_definite(const cbor_item_t *item); /** Is the byte string indefinite? * * @param item[borrow] a byte string * @return Is the byte string indefinite? */ -bool cbor_bytestring_is_indefinite(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_is_indefinite(const cbor_item_t *item); /** Get the handle to the binary data * @@ -52,7 +56,8 @@ bool cbor_bytestring_is_indefinite(const cbor_item_t *item); * @return The address of the binary data. `NULL` if no data have been assigned * yet. */ -cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item); /** Set the handle to the binary data * @@ -61,9 +66,9 @@ cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item); * libcbor will deallocate it when appropriate using its free function * @param length Length of the data block */ -void cbor_bytestring_set_handle(cbor_item_t *item, - cbor_mutable_data CBOR_RESTRICT_POINTER data, - size_t length); +CBOR_EXPORT void cbor_bytestring_set_handle( + cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length); /** Get the handle to the array of chunks * @@ -73,14 +78,17 @@ void cbor_bytestring_set_handle(cbor_item_t *item, * @param item[borrow] A indefinite byte string * @return array of #cbor_bytestring_chunk_count definite bytestrings */ -cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t **cbor_bytestring_chunks_handle( + const cbor_item_t *item); /** Get the number of chunks this string consist of * * @param item[borrow] A indefinite bytestring * @return The chunk count. 0 for freshly created items. */ -size_t cbor_bytestring_chunk_count(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_bytestring_chunk_count(const cbor_item_t *item); /** Appends a chunk to the bytestring * @@ -93,7 +101,9 @@ size_t cbor_bytestring_chunk_count(const cbor_item_t *item); * @return true on success, false on realloc failure. In that case, the refcount * of `chunk` is not increased and the `item` is left intact. */ -bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_add_chunk(cbor_item_t *item, + cbor_item_t *chunk); /** Creates a new definite byte string * @@ -101,15 +111,17 @@ bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk); * * @return **new** definite bytestring. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_definite_bytestring(); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_new_definite_bytestring(void); /** Creates a new indefinite byte string * - * The chunks array is initialized to `NULL` and chunkcount to 0 + * The chunks array is initialized to `NULL` and chunk count to 0 * * @return **new** indefinite bytestring. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_indefinite_bytestring(); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_new_indefinite_bytestring(void); /** Creates a new byte string and initializes it * @@ -120,7 +132,8 @@ cbor_item_t *cbor_new_indefinite_bytestring(); * @return A **new** byte string with content `handle`. `NULL` on malloc * failure. */ -cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/callbacks.c b/lib/libcbor/src/cbor/callbacks.c index 7d0f1c62a75..bdf3f79eee6 100644 --- a/lib/libcbor/src/cbor/callbacks.c +++ b/lib/libcbor/src/cbor/callbacks.c @@ -7,110 +7,115 @@ #include "callbacks.h" -#define CBOR_DUMMY_CALLBACK \ - {} +void cbor_null_uint8_callback(void *_CBOR_UNUSED(_ctx), + uint8_t _CBOR_UNUSED(_val)) {} -void cbor_null_uint8_callback(void *_ctx, uint8_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_uint16_callback(void *_CBOR_UNUSED(_ctx), + uint16_t _CBOR_UNUSED(_val)) {} - void cbor_null_uint16_callback(void *_ctx, - uint16_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_uint32_callback(void *_CBOR_UNUSED(_ctx), + uint32_t _CBOR_UNUSED(_val)) {} - void cbor_null_uint32_callback(void *_ctx, - uint32_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_uint64_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} - void cbor_null_uint64_callback(void *_ctx, - uint64_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_negint8_callback(void *_CBOR_UNUSED(_ctx), + uint8_t _CBOR_UNUSED(_val)) {} - void cbor_null_negint8_callback(void *_ctx, - uint8_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_negint16_callback(void *_CBOR_UNUSED(_ctx), + uint16_t _CBOR_UNUSED(_val)) {} - void cbor_null_negint16_callback(void *_ctx, - uint16_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_negint32_callback(void *_CBOR_UNUSED(_ctx), + uint32_t _CBOR_UNUSED(_val)) {} - void cbor_null_negint32_callback(void *_ctx, - uint32_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_negint64_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} - void cbor_null_negint64_callback(void *_ctx, - uint64_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_string_callback(void *_CBOR_UNUSED(_ctx), + cbor_data _CBOR_UNUSED(_val), + uint64_t _CBOR_UNUSED(_val2)) {} - void cbor_null_string_callback(void *_ctx, cbor_data _val, - size_t _val2) CBOR_DUMMY_CALLBACK +void cbor_null_string_start_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_byte_string_callback(void *_CBOR_UNUSED(_ctx), + cbor_data _CBOR_UNUSED(_val), + uint64_t _CBOR_UNUSED(_val2)) {} - void cbor_null_byte_string_callback(void *_ctx, cbor_data _val, - size_t _val2) CBOR_DUMMY_CALLBACK +void cbor_null_byte_string_start_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_byte_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_array_start_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} - void cbor_null_array_start_callback(void *_ctx, - size_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_indef_array_start_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_indef_array_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_map_start_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} - void cbor_null_map_start_callback(void *_ctx, - size_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_indef_map_start_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_indef_map_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_tag_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} - void cbor_null_tag_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK +void cbor_null_float2_callback(void *_CBOR_UNUSED(_ctx), + float _CBOR_UNUSED(_val)) {} - void cbor_null_float2_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK +void cbor_null_float4_callback(void *_CBOR_UNUSED(_ctx), + float _CBOR_UNUSED(_val)) {} - void cbor_null_float4_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK +void cbor_null_float8_callback(void *_CBOR_UNUSED(_ctx), + double _CBOR_UNUSED(_val)) {} - void cbor_null_float8_callback(void *_ctx, double _val) CBOR_DUMMY_CALLBACK +void cbor_null_null_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_null_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_undefined_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_undefined_callback(void *_ctx) CBOR_DUMMY_CALLBACK +void cbor_null_boolean_callback(void *_CBOR_UNUSED(_ctx), + bool _CBOR_UNUSED(_val)) {} - void cbor_null_boolean_callback(void *_ctx, bool _val) CBOR_DUMMY_CALLBACK +void cbor_null_indef_break_callback(void *_CBOR_UNUSED(_ctx)) {} - void cbor_null_indef_break_callback(void *_ctx) CBOR_DUMMY_CALLBACK +CBOR_EXPORT const struct cbor_callbacks cbor_empty_callbacks = { + /* Type 0 - Unsigned integers */ + .uint8 = cbor_null_uint8_callback, + .uint16 = cbor_null_uint16_callback, + .uint32 = cbor_null_uint32_callback, + .uint64 = cbor_null_uint64_callback, - const struct cbor_callbacks cbor_empty_callbacks = { - /* Type 0 - Unsigned integers */ - .uint8 = cbor_null_uint8_callback, - .uint16 = cbor_null_uint16_callback, - .uint32 = cbor_null_uint32_callback, - .uint64 = cbor_null_uint64_callback, + /* Type 1 - Negative integers */ + .negint8 = cbor_null_negint8_callback, + .negint16 = cbor_null_negint16_callback, + .negint32 = cbor_null_negint32_callback, + .negint64 = cbor_null_negint64_callback, - /* Type 1 - Negative integers */ - .negint8 = cbor_null_negint8_callback, - .negint16 = cbor_null_negint16_callback, - .negint32 = cbor_null_negint32_callback, - .negint64 = cbor_null_negint64_callback, + /* Type 2 - Byte strings */ + .byte_string_start = cbor_null_byte_string_start_callback, + .byte_string = cbor_null_byte_string_callback, - /* Type 2 - Byte strings */ - .byte_string_start = cbor_null_byte_string_start_callback, - .byte_string = cbor_null_byte_string_callback, + /* Type 3 - Strings */ + .string_start = cbor_null_string_start_callback, + .string = cbor_null_string_callback, - /* Type 3 - Strings */ - .string_start = cbor_null_string_start_callback, - .string = cbor_null_string_callback, + /* Type 4 - Arrays */ + .indef_array_start = cbor_null_indef_array_start_callback, + .array_start = cbor_null_array_start_callback, - /* Type 4 - Arrays */ - .indef_array_start = cbor_null_indef_array_start_callback, - .array_start = cbor_null_array_start_callback, + /* Type 5 - Maps */ + .indef_map_start = cbor_null_indef_map_start_callback, + .map_start = cbor_null_map_start_callback, - /* Type 5 - Maps */ - .indef_map_start = cbor_null_indef_map_start_callback, - .map_start = cbor_null_map_start_callback, + /* Type 6 - Tags */ + .tag = cbor_null_tag_callback, - /* Type 6 - Tags */ - .tag = cbor_null_tag_callback, + /* Type 7 - Floats & misc */ + /* Type names cannot be member names */ + .float2 = cbor_null_float2_callback, + /* 2B float is not supported in standard C */ + .float4 = cbor_null_float4_callback, + .float8 = cbor_null_float8_callback, + .undefined = cbor_null_undefined_callback, + .null = cbor_null_null_callback, + .boolean = cbor_null_boolean_callback, - /* Type 7 - Floats & misc */ - /* Type names cannot be member names */ - .float2 = cbor_null_float2_callback, - /* 2B float is not supported in standard C */ - .float4 = cbor_null_float4_callback, - .float8 = cbor_null_float8_callback, - .undefined = cbor_null_undefined_callback, - .null = cbor_null_null_callback, - .boolean = cbor_null_boolean_callback, - - /* Shared indefinites */ - .indef_break = cbor_null_indef_break_callback, + /* Shared indefinites */ + .indef_break = cbor_null_indef_break_callback, }; diff --git a/lib/libcbor/src/cbor/callbacks.h b/lib/libcbor/src/cbor/callbacks.h index 1d37f3ee865..c7ae20568dc 100644 --- a/lib/libcbor/src/cbor/callbacks.h +++ b/lib/libcbor/src/cbor/callbacks.h @@ -8,6 +8,9 @@ #ifndef LIBCBOR_CALLBACKS_H #define LIBCBOR_CALLBACKS_H +#include + +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -30,10 +33,10 @@ typedef void (*cbor_int64_callback)(void *, uint64_t); typedef void (*cbor_simple_callback)(void *); /** Callback prototype */ -typedef void (*cbor_string_callback)(void *, cbor_data, size_t); +typedef void (*cbor_string_callback)(void *, cbor_data, uint64_t); /** Callback prototype */ -typedef void (*cbor_collection_callback)(void *, size_t); +typedef void (*cbor_collection_callback)(void *, uint64_t); /** Callback prototype */ typedef void (*cbor_float_callback)(void *, float); @@ -105,79 +108,79 @@ struct cbor_callbacks { }; /** Dummy callback implementation - does nothing */ -void cbor_null_uint8_callback(void *, uint8_t); +CBOR_EXPORT void cbor_null_uint8_callback(void *, uint8_t); /** Dummy callback implementation - does nothing */ -void cbor_null_uint16_callback(void *, uint16_t); +CBOR_EXPORT void cbor_null_uint16_callback(void *, uint16_t); /** Dummy callback implementation - does nothing */ -void cbor_null_uint32_callback(void *, uint32_t); +CBOR_EXPORT void cbor_null_uint32_callback(void *, uint32_t); /** Dummy callback implementation - does nothing */ -void cbor_null_uint64_callback(void *, uint64_t); +CBOR_EXPORT void cbor_null_uint64_callback(void *, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_negint8_callback(void *, uint8_t); +CBOR_EXPORT void cbor_null_negint8_callback(void *, uint8_t); /** Dummy callback implementation - does nothing */ -void cbor_null_negint16_callback(void *, uint16_t); +CBOR_EXPORT void cbor_null_negint16_callback(void *, uint16_t); /** Dummy callback implementation - does nothing */ -void cbor_null_negint32_callback(void *, uint32_t); +CBOR_EXPORT void cbor_null_negint32_callback(void *, uint32_t); /** Dummy callback implementation - does nothing */ -void cbor_null_negint64_callback(void *, uint64_t); +CBOR_EXPORT void cbor_null_negint64_callback(void *, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_string_callback(void *, cbor_data, size_t); +CBOR_EXPORT void cbor_null_string_callback(void *, cbor_data, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_string_start_callback(void *); +CBOR_EXPORT void cbor_null_string_start_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_byte_string_callback(void *, cbor_data, size_t); +CBOR_EXPORT void cbor_null_byte_string_callback(void *, cbor_data, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_byte_string_start_callback(void *); +CBOR_EXPORT void cbor_null_byte_string_start_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_array_start_callback(void *, size_t); +CBOR_EXPORT void cbor_null_array_start_callback(void *, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_indef_array_start_callback(void *); +CBOR_EXPORT void cbor_null_indef_array_start_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_map_start_callback(void *, size_t); +CBOR_EXPORT void cbor_null_map_start_callback(void *, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_indef_map_start_callback(void *); +CBOR_EXPORT void cbor_null_indef_map_start_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_tag_callback(void *, uint64_t); +CBOR_EXPORT void cbor_null_tag_callback(void *, uint64_t); /** Dummy callback implementation - does nothing */ -void cbor_null_float2_callback(void *, float); +CBOR_EXPORT void cbor_null_float2_callback(void *, float); /** Dummy callback implementation - does nothing */ -void cbor_null_float4_callback(void *, float); +CBOR_EXPORT void cbor_null_float4_callback(void *, float); /** Dummy callback implementation - does nothing */ -void cbor_null_float8_callback(void *, double); +CBOR_EXPORT void cbor_null_float8_callback(void *, double); /** Dummy callback implementation - does nothing */ -void cbor_null_null_callback(void *); +CBOR_EXPORT void cbor_null_null_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_undefined_callback(void *); +CBOR_EXPORT void cbor_null_undefined_callback(void *); /** Dummy callback implementation - does nothing */ -void cbor_null_boolean_callback(void *, bool); +CBOR_EXPORT void cbor_null_boolean_callback(void *, bool); /** Dummy callback implementation - does nothing */ -void cbor_null_indef_break_callback(void *); +CBOR_EXPORT void cbor_null_indef_break_callback(void *); /** Dummy callback bundle - does nothing */ -extern const struct cbor_callbacks cbor_empty_callbacks; +CBOR_EXPORT extern const struct cbor_callbacks cbor_empty_callbacks; #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/cbor_export.h b/lib/libcbor/src/cbor/cbor_export.h new file mode 100644 index 00000000000..de549746472 --- /dev/null +++ b/lib/libcbor/src/cbor/cbor_export.h @@ -0,0 +1,42 @@ + +#ifndef CBOR_EXPORT_H +#define CBOR_EXPORT_H + +#ifdef CBOR_STATIC_DEFINE +# define CBOR_EXPORT +# define CBOR_NO_EXPORT +#else +# ifndef CBOR_EXPORT +# ifdef cbor_EXPORTS + /* We are building this library */ +# define CBOR_EXPORT +# else + /* We are using this library */ +# define CBOR_EXPORT +# endif +# endif + +# ifndef CBOR_NO_EXPORT +# define CBOR_NO_EXPORT +# endif +#endif + +#ifndef CBOR_DEPRECATED +# define CBOR_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef CBOR_DEPRECATED_EXPORT +# define CBOR_DEPRECATED_EXPORT CBOR_EXPORT CBOR_DEPRECATED +#endif + +#ifndef CBOR_DEPRECATED_NO_EXPORT +# define CBOR_DEPRECATED_NO_EXPORT CBOR_NO_EXPORT CBOR_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef CBOR_NO_DEPRECATED +# define CBOR_NO_DEPRECATED +# endif +#endif + +#endif /* CBOR_EXPORT_H */ diff --git a/lib/libcbor/src/cbor/common.c b/lib/libcbor/src/cbor/common.c index 7ccce38ac25..efbd37ed79d 100644 --- a/lib/libcbor/src/cbor/common.c +++ b/lib/libcbor/src/cbor/common.c @@ -15,6 +15,10 @@ #include "strings.h" #include "tags.h" +#ifdef DEBUG +bool _cbor_enable_assert = true; +#endif + bool cbor_isa_uint(const cbor_item_t *item) { return item->type == CBOR_TYPE_UINT; } @@ -78,7 +82,7 @@ cbor_item_t *cbor_incref(cbor_item_t *item) { void cbor_decref(cbor_item_t **item_ref) { cbor_item_t *item = *item_ref; - assert(item->refcount > 0); + CBOR_ASSERT(item->refcount > 0); if (--item->refcount == 0) { switch (item->type) { case CBOR_TYPE_UINT: @@ -88,29 +92,29 @@ void cbor_decref(cbor_item_t **item_ref) { { break; } case CBOR_TYPE_BYTESTRING: { if (cbor_bytestring_is_definite(item)) { - _CBOR_FREE(item->data); + _cbor_free(item->data); } else { /* We need to decref all chunks */ cbor_item_t **handle = cbor_bytestring_chunks_handle(item); for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) cbor_decref(&handle[i]); - _CBOR_FREE( + _cbor_free( ((struct cbor_indefinite_string_data *)item->data)->chunks); - _CBOR_FREE(item->data); + _cbor_free(item->data); } break; } case CBOR_TYPE_STRING: { if (cbor_string_is_definite(item)) { - _CBOR_FREE(item->data); + _cbor_free(item->data); } else { /* We need to decref all chunks */ cbor_item_t **handle = cbor_string_chunks_handle(item); for (size_t i = 0; i < cbor_string_chunk_count(item); i++) cbor_decref(&handle[i]); - _CBOR_FREE( + _cbor_free( ((struct cbor_indefinite_string_data *)item->data)->chunks); - _CBOR_FREE(item->data); + _cbor_free(item->data); } break; } @@ -120,7 +124,7 @@ void cbor_decref(cbor_item_t **item_ref) { size_t size = cbor_array_size(item); for (size_t i = 0; i < size; i++) if (handle[i] != NULL) cbor_decref(&handle[i]); - _CBOR_FREE(item->data); + _cbor_free(item->data); break; } case CBOR_TYPE_MAP: { @@ -130,13 +134,13 @@ void cbor_decref(cbor_item_t **item_ref) { cbor_decref(&handle->key); if (handle->value != NULL) cbor_decref(&handle->value); } - _CBOR_FREE(item->data); + _cbor_free(item->data); break; - }; + } case CBOR_TYPE_TAG: { if (item->metadata.tag_metadata.tagged_item != NULL) cbor_decref(&item->metadata.tag_metadata.tagged_item); - _CBOR_FREE(item->data); + _cbor_free(item->data); break; } case CBOR_TYPE_FLOAT_CTRL: { @@ -144,8 +148,7 @@ void cbor_decref(cbor_item_t **item_ref) { break; } } - _CBOR_FREE(item); - // TODO + _cbor_free(item); *item_ref = NULL; } } diff --git a/lib/libcbor/src/cbor/common.h b/lib/libcbor/src/cbor/common.h index d54a23cc81e..6a6f969f23f 100644 --- a/lib/libcbor/src/cbor/common.h +++ b/lib/libcbor/src/cbor/common.h @@ -13,6 +13,7 @@ #include #include #include +#include "cbor/cbor_export.h" #include "cbor/configuration.h" #include "data.h" @@ -20,7 +21,7 @@ extern "C" { /** - * C++ is not a subset of C99 -- 'restrict' qualifier is not a part of the + * C99 is not a subset of C++ -- 'restrict' qualifier is not a part of the * language. This is a workaround to keep it in C headers -- compilers allow * linking non-restrict signatures with restrict implementations. * @@ -39,9 +40,9 @@ static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION; static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION; static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; -#define CBOR_VERSION \ - TO_STR(CBOR_MAJOR_VERSION) \ - "." TO_STR(CBOR_MINOR_VERSION) "." TO_STR(CBOR_PATCH_VERSION) +#define CBOR_VERSION \ + _CBOR_TO_STR(CBOR_MAJOR_VERSION) \ + "." _CBOR_TO_STR(CBOR_MINOR_VERSION) "." _CBOR_TO_STR(CBOR_PATCH_VERSION) #define CBOR_HEX_VERSION \ ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION) @@ -49,20 +50,57 @@ static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; */ #ifdef DEBUG #include -#define debug_print(fmt, ...) \ +#define _cbor_debug_print(fmt, ...) \ do { \ if (DEBUG) \ fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \ __VA_ARGS__); \ } while (0) +extern bool _cbor_enable_assert; +// Like `assert`, but can be dynamically disabled in tests to allow testing +// invalid behaviors. +#define CBOR_ASSERT(e) assert(!_cbor_enable_assert || (e)) +#define _CBOR_TEST_DISABLE_ASSERT(block) \ + do { \ + _cbor_enable_assert = false; \ + block _cbor_enable_assert = true; \ + } while (0) #else #define debug_print(fmt, ...) \ do { \ } while (0) +#define CBOR_ASSERT(e) +#define _CBOR_TEST_DISABLE_ASSERT(block) \ + do { \ + block \ + } while (0) +#endif + +#define _CBOR_TO_STR_(x) #x +#define _CBOR_TO_STR(x) _CBOR_TO_STR_(x) /* enables proper double expansion */ + +#ifdef __GNUC__ +#define _CBOR_UNUSED(x) __attribute__((__unused__)) x +// TODO(https://github.com/PJK/libcbor/issues/247): Prefer [[nodiscard]] if +// available +#define _CBOR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define _CBOR_UNUSED(x) __pragma(warning(suppress : 4100 4101)) x +#define _CBOR_NODISCARD +#else +#define _CBOR_UNUSED(x) x +#define _CBOR_NODISCARD #endif -#define TO_STR_(x) #x -#define TO_STR(x) TO_STR_(x) /* enables proper double expansion */ +#if 0 /* custom allocators are not supported on OpenBSD */ +typedef void *(*_cbor_malloc_t)(size_t); +typedef void *(*_cbor_realloc_t)(void *, size_t); +typedef void (*_cbor_free_t)(void *); + +CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc; +CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc; +CBOR_EXPORT extern _cbor_free_t _cbor_free; +#endif // Macro to short-circuit builder functions when memory allocation fails #define _CBOR_NOTNULL(cbor_item) \ @@ -76,51 +114,32 @@ static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; #define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \ do { \ if (pointer == NULL) { \ - _CBOR_FREE(cbor_item); \ + _cbor_free(cbor_item); \ return NULL; \ } \ } while (0) -#if CBOR_CUSTOM_ALLOC - -typedef void *(*_cbor_malloc_t)(size_t); -typedef void *(*_cbor_realloc_t)(void *, size_t); -typedef void (*_cbor_free_t)(void *); - -extern _cbor_malloc_t _cbor_malloc; -extern _cbor_realloc_t _cbor_realloc; -extern _cbor_free_t _cbor_free; - /** Sets the memory management routines to use. - * - * Only available when `CBOR_CUSTOM_ALLOC` is truthy * * \rst * .. warning:: This function modifies the global state and should therefore be - * used accordingly. Changing the memory handlers while allocated items exist - * will result in a ``free``/``malloc`` mismatch. This function is not thread - * safe with respect to both itself and all the other *libcbor* functions that - * work with the heap. + * used accordingly. Changing the memory handlers while allocated items exist + * will result in a ``free``/``malloc`` mismatch. This function is not thread + * safe with respect to both itself and all the other *libcbor* functions that + * work with the heap. + * * .. note:: `realloc` implementation must correctly support `NULL` reallocation - * (see e.g. http://en.cppreference.com/w/c/memory/realloc) \endrst + * (see e.g. http://en.cppreference.com/w/c/memory/realloc) + * \endrst * * @param custom_malloc malloc implementation * @param custom_realloc realloc implementation * @param custom_free free implementation */ -void cbor_set_allocs(_cbor_malloc_t custom_malloc, - _cbor_realloc_t custom_realloc, _cbor_free_t custom_free); - -#define _CBOR_MALLOC _cbor_malloc -#define _CBOR_REALLOC _cbor_realloc -#define _CBOR_FREE _cbor_free - -#else - -#define _CBOR_MALLOC malloc -#define _CBOR_REALLOC realloc -#define _CBOR_FREE free - +#if 0 /* not on OpenBSD */ +CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc, + _cbor_realloc_t custom_realloc, + _cbor_free_t custom_free); #endif /* @@ -134,7 +153,8 @@ void cbor_set_allocs(_cbor_malloc_t custom_malloc, * @param item[borrow] * @return The type */ -cbor_type cbor_typeof( +_CBOR_NODISCARD +CBOR_EXPORT cbor_type cbor_typeof( const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */ /* Standard item types as described by the RFC */ @@ -143,49 +163,57 @@ cbor_type cbor_typeof( * @param item[borrow] the item * @return Is the item an #CBOR_TYPE_UINT? */ -bool cbor_isa_uint(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_NEGINT? */ -bool cbor_isa_negint(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_BYTESTRING? */ -bool cbor_isa_bytestring(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_STRING? */ -bool cbor_isa_string(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_string(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item an #CBOR_TYPE_ARRAY? */ -bool cbor_isa_array(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_array(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_MAP? */ -bool cbor_isa_map(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_map(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_TAG? */ -bool cbor_isa_tag(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t *item); /** Does the item have the appropriate major type? * @param item[borrow] the item * @return Is the item a #CBOR_TYPE_FLOAT_CTRL? */ -bool cbor_isa_float_ctrl(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t *item); /* Practical types with respect to their semantics (but not tag values) */ @@ -193,37 +221,48 @@ bool cbor_isa_float_ctrl(const cbor_item_t *item); * @param item[borrow] the item * @return Is the item an integer, either positive or negative? */ -bool cbor_is_int(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_int(const cbor_item_t *item); /** Is the item an a floating point number? * @param item[borrow] the item * @return Is the item a floating point number? */ -bool cbor_is_float(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_float(const cbor_item_t *item); /** Is the item an a boolean? * @param item[borrow] the item * @return Is the item a boolean? */ -bool cbor_is_bool(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_bool(const cbor_item_t *item); /** Does this item represent `null` + * * \rst * .. warning:: This is in no way related to the value of the pointer. Passing a - * null pointer will most likely result in a crash. \endrst + * null pointer will most likely result in a crash. + * \endrst + * * @param item[borrow] the item * @return Is the item (CBOR logical) null? */ -bool cbor_is_null(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_null(const cbor_item_t *item); /** Does this item represent `undefined` + * * \rst * .. warning:: Care must be taken to distinguish nulls and undefined values in - * C. \endrst + * C. + * \endrst + * * @param item[borrow] the item * @return Is the item (CBOR logical) undefined? */ -bool cbor_is_undef(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_undef(const cbor_item_t *item); /* * ============================================================================ @@ -238,7 +277,7 @@ bool cbor_is_undef(const cbor_item_t *item); * @param item[incref] item the item * @return the input reference */ -cbor_item_t *cbor_incref(cbor_item_t *item); +CBOR_EXPORT cbor_item_t *cbor_incref(cbor_item_t *item); /** Decreases the reference count by one, deallocating the item if needed * @@ -247,7 +286,7 @@ cbor_item_t *cbor_incref(cbor_item_t *item); * * @param item[take] the item. Set to `NULL` if deallocated */ -void cbor_decref(cbor_item_t **item); +CBOR_EXPORT void cbor_decref(cbor_item_t **item); /** Decreases the reference count by one, deallocating the item if needed * @@ -256,7 +295,7 @@ void cbor_decref(cbor_item_t **item); * * @param item[take] the item */ -void cbor_intermediate_decref(cbor_item_t *item); +CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t *item); /** Get the reference count * @@ -267,7 +306,8 @@ void cbor_intermediate_decref(cbor_item_t *item); * @param item[borrow] the item * @return the reference count */ -size_t cbor_refcount(const cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_refcount(const cbor_item_t *item); /** Provides CPP-like move construct * @@ -278,12 +318,14 @@ size_t cbor_refcount(const cbor_item_t *item); * * \rst * .. warning:: If the item is moved without correctly increasing the reference - * count afterwards, the memory will be leaked. \endrst + * count afterwards, the memory will be leaked. + * \endrst * * @param item[take] the item * @return the item with reference count decreased by one */ -cbor_item_t *cbor_move(cbor_item_t *item); +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_move(cbor_item_t *item); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/configuration.h b/lib/libcbor/src/cbor/configuration.h index 8e4e3be4bff..d4ea06ee11c 100644 --- a/lib/libcbor/src/cbor/configuration.h +++ b/lib/libcbor/src/cbor/configuration.h @@ -2,10 +2,9 @@ #define LIBCBOR_CONFIGURATION_H #define CBOR_MAJOR_VERSION 0 -#define CBOR_MINOR_VERSION 7 +#define CBOR_MINOR_VERSION 10 #define CBOR_PATCH_VERSION 0 -#define CBOR_CUSTOM_ALLOC 0 #define CBOR_BUFFER_GROWTH 2 #define CBOR_MAX_STACK_SIZE 2048 #define CBOR_PRETTY_PRINTER 1 diff --git a/lib/libcbor/src/cbor/configuration.h.in b/lib/libcbor/src/cbor/configuration.h.in index 6f65980aa8a..0052a150489 100644 --- a/lib/libcbor/src/cbor/configuration.h.in +++ b/lib/libcbor/src/cbor/configuration.h.in @@ -5,7 +5,6 @@ #define CBOR_MINOR_VERSION ${CBOR_VERSION_MINOR} #define CBOR_PATCH_VERSION ${CBOR_VERSION_PATCH} -#cmakedefine01 CBOR_CUSTOM_ALLOC #define CBOR_BUFFER_GROWTH ${CBOR_BUFFER_GROWTH} #define CBOR_MAX_STACK_SIZE ${CBOR_MAX_STACK_SIZE} #cmakedefine01 CBOR_PRETTY_PRINTER diff --git a/lib/libcbor/src/cbor/data.h b/lib/libcbor/src/cbor/data.h index 8dbf24824f8..a12e92f20c3 100644 --- a/lib/libcbor/src/cbor/data.h +++ b/lib/libcbor/src/cbor/data.h @@ -45,6 +45,8 @@ typedef enum { CBOR_ERR_NONE, CBOR_ERR_NOTENOUGHDATA, CBOR_ERR_NODATA, + // TODO: Should be "malformed" or at least "malformatted". Retained for + // backwards compatibility. CBOR_ERR_MALFORMATED, CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for your allocator? */ @@ -86,6 +88,11 @@ typedef enum { CBOR_CTRL_UNDEF = 23 } _cbor_ctrl; +// Metadata items use size_t (instead of uint64_t) because items in memory take +// up at least 1B per entry or string byte, so if size_t is narrower than +// uint64_t, we wouldn't be able to create them in the first place and can save +// some space. + /** Integers specific metadata */ struct _cbor_int_metadata { cbor_int_width width; @@ -199,29 +206,54 @@ struct cbor_pair { struct cbor_load_result { /** Error indicator */ struct cbor_error error; - /** Number of bytes read*/ + /** Number of bytes read */ size_t read; }; /** Streaming decoder result - status */ enum cbor_decoder_status { - CBOR_DECODER_FINISHED /** OK, finished */ - , - CBOR_DECODER_NEDATA /** Not enough data - mismatch with MTB */ - , - CBOR_DECODER_EBUFFER /** Buffer manipulation problem */ - , - CBOR_DECODER_ERROR /** Malformed or reserved MTB/value */ + /** Decoding finished successfully (a callback has been invoked) + * + * Note that this does *not* mean that the buffer has been fully decoded; + * there may still be unread bytes for which no callback has been involved. + */ + CBOR_DECODER_FINISHED, + /** Not enough data to invoke a callback */ + // TODO: The name is inconsistent with CBOR_ERR_NOTENOUGHDATA. Retained for + // backwards compatibility. + CBOR_DECODER_NEDATA, + /** Bad data (reserved MTB, malformed value, etc.) */ + CBOR_DECODER_ERROR }; /** Streaming decoder result */ struct cbor_decoder_result { - /** Bytes read */ + /** Input bytes read/consumed + * + * If this is less than the size of input buffer, the client will likely + * resume parsing starting at the next byte (e.g. `buffer + result.read`). + * + * Set to 0 if the #status is not #CBOR_DECODER_FINISHED. + */ size_t read; - /** The result */ + + /** The decoding status */ enum cbor_decoder_status status; - /** When status == CBOR_DECODER_NEDATA, - * the minimum number of bytes required to continue parsing */ + + /** Number of bytes in the input buffer needed to resume parsing + * + * Set to 0 unless the result status is #CBOR_DECODER_NEDATA. If it is, then: + * - If at least one byte was passed, #required will be set to the minimum + * number of bytes needed to invoke a decoded callback on the current + * prefix. + * + * For example: Attempting to decode a 1B buffer containing `0x19` will + * set #required to 3 as `0x19` signals a 2B integer item, so we need at + * least 3B to continue (the `0x19` MTB byte and two bytes of data needed + * to invoke #cbor_callbacks.uint16). + * + * - If there was no data at all, #read will always be set to 1 + */ size_t required; }; diff --git a/lib/libcbor/src/cbor/encoding.c b/lib/libcbor/src/cbor/encoding.c index 19281520edd..9d931d17570 100644 --- a/lib/libcbor/src/cbor/encoding.c +++ b/lib/libcbor/src/cbor/encoding.c @@ -135,17 +135,23 @@ size_t cbor_encode_half(float value, unsigned char *buffer, val & 0x7FFFFFu; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */ if (exp == 0xFF) { /* Infinity or NaNs */ if (value != value) { - res = (uint16_t)0x007e00; /* Not IEEE semantics - required by CBOR - [s. 3.9] */ + // We discard information bits in half-float NaNs. This is + // not required for the core CBOR protocol (it is only a suggestion in + // Section 3.9). + // See https://github.com/PJK/libcbor/issues/215 + res = (uint16_t)0x007e00; } else { - res = (uint16_t)((val & 0x80000000u) >> 16u | 0x7C00u | - (mant ? 1u : 0u) << 15u); + // If the mantissa is non-zero, we have a NaN, but those are handled + // above. See + // https://en.wikipedia.org/wiki/Half-precision_floating-point_format + CBOR_ASSERT(mant == 0u); + res = (uint16_t)((val & 0x80000000u) >> 16u | 0x7C00u); } } else if (exp == 0x00) { /* Zeroes or subnorms */ res = (uint16_t)((val & 0x80000000u) >> 16u | mant >> 13u); } else { /* Normal numbers */ int8_t logical_exp = (int8_t)(exp - 127); - assert(logical_exp == exp - 127); + CBOR_ASSERT(logical_exp == exp - 127); // Now we know that 2^exp <= 0 logically if (logical_exp < -24) { @@ -158,7 +164,9 @@ size_t cbor_encode_half(float value, unsigned char *buffer, value is lost. This is an implementation decision that works around the absence of standard half-float in the language. */ res = (uint16_t)((val & 0x80000000u) >> 16u) | // Extract sign bit - (uint16_t)(1u << (24u + logical_exp)); + ((uint16_t)(1u << (24u + logical_exp)) + + (uint16_t)(((mant >> (-logical_exp - 2)) + 1) >> + 1)); // Round half away from zero for simplicity } else { res = (uint16_t)((val & 0x80000000u) >> 16u | ((((uint8_t)logical_exp) + 15u) << 10u) | diff --git a/lib/libcbor/src/cbor/encoding.h b/lib/libcbor/src/cbor/encoding.h index 34a7382758a..bcc04f8a98e 100644 --- a/lib/libcbor/src/cbor/encoding.h +++ b/lib/libcbor/src/cbor/encoding.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_ENCODING_H #define LIBCBOR_ENCODING_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -15,54 +16,87 @@ extern "C" { #endif /* - * ============================================================================ - * Primitives encoding - * ============================================================================ + * All cbor_encode_* methods take 2 or 3 arguments: + * - a logical `value` to encode (except for trivial items such as NULLs) + * - an output `buffer` pointer + * - a `buffer_size` specification + * + * They serialize the `value` into one or more bytes and write the bytes to the + * output `buffer` and return either the number of bytes written, or 0 if the + * `buffer_size` was too small to small to fit the serialized value (in which + * case it is not modified). */ -size_t cbor_encode_uint8(uint8_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint8(uint8_t, unsigned char *, + size_t); -size_t cbor_encode_uint16(uint16_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint16(uint16_t, unsigned char *, + size_t); -size_t cbor_encode_uint32(uint32_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint32(uint32_t, unsigned char *, + size_t); -size_t cbor_encode_uint64(uint64_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint64(uint64_t, unsigned char *, + size_t); -size_t cbor_encode_uint(uint64_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint(uint64_t, unsigned char *, + size_t); -size_t cbor_encode_negint8(uint8_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint8(uint8_t, unsigned char *, + size_t); -size_t cbor_encode_negint16(uint16_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint16(uint16_t, + unsigned char *, + size_t); -size_t cbor_encode_negint32(uint32_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint32(uint32_t, + unsigned char *, + size_t); -size_t cbor_encode_negint64(uint64_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint64(uint64_t, + unsigned char *, + size_t); -size_t cbor_encode_negint(uint64_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint(uint64_t, unsigned char *, + size_t); -size_t cbor_encode_bytestring_start(size_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_bytestring_start(size_t, + unsigned char *, + size_t); -size_t cbor_encode_indef_bytestring_start(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_bytestring_start(unsigned char *, size_t); -size_t cbor_encode_string_start(size_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_string_start(size_t, + unsigned char *, + size_t); -size_t cbor_encode_indef_string_start(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_string_start(unsigned char *, size_t); -size_t cbor_encode_array_start(size_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_array_start(size_t, + unsigned char *, + size_t); -size_t cbor_encode_indef_array_start(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_array_start(unsigned char *, size_t); -size_t cbor_encode_map_start(size_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_map_start(size_t, + unsigned char *, + size_t); -size_t cbor_encode_indef_map_start(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_indef_map_start(unsigned char *, + size_t); -size_t cbor_encode_tag(uint64_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_tag(uint64_t, unsigned char *, + size_t); -size_t cbor_encode_bool(bool, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_bool(bool, unsigned char *, + size_t); -size_t cbor_encode_null(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_null(unsigned char *, size_t); -size_t cbor_encode_undef(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_undef(unsigned char *, size_t); /** Encodes a half-precision float * @@ -84,21 +118,20 @@ size_t cbor_encode_undef(unsigned char *, size_t); * lost. * - In all other cases, the sign bit, the exponent, and 10 most significant * bits of the significand are kept - * - * @param value - * @param buffer Target buffer - * @param buffer_size Available space in the buffer - * @return number of bytes written */ -size_t cbor_encode_half(float, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_half(float, unsigned char *, + size_t); -size_t cbor_encode_single(float, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_single(float, unsigned char *, + size_t); -size_t cbor_encode_double(double, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_double(double, unsigned char *, + size_t); -size_t cbor_encode_break(unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_break(unsigned char *, size_t); -size_t cbor_encode_ctrl(uint8_t, unsigned char *, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_ctrl(uint8_t, unsigned char *, + size_t); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/floats_ctrls.c b/lib/libcbor/src/cbor/floats_ctrls.c index b7e5fcef853..57bf477d4d3 100644 --- a/lib/libcbor/src/cbor/floats_ctrls.c +++ b/lib/libcbor/src/cbor/floats_ctrls.c @@ -10,41 +10,42 @@ #include "assert.h" cbor_float_width cbor_float_get_width(const cbor_item_t *item) { - assert(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_isa_float_ctrl(item)); return item->metadata.float_ctrl_metadata.width; } uint8_t cbor_ctrl_value(const cbor_item_t *item) { - assert(cbor_isa_float_ctrl(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_0); + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0); return item->metadata.float_ctrl_metadata.ctrl; } bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item) { - assert(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_isa_float_ctrl(item)); return cbor_float_get_width(item) == CBOR_FLOAT_0; } float cbor_float_get_float2(const cbor_item_t *item) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_16); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16); return *(float *)item->data; } float cbor_float_get_float4(const cbor_item_t *item) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_32); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32); return *(float *)item->data; } double cbor_float_get_float8(const cbor_item_t *item) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_64); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64); return *(double *)item->data; } double cbor_float_get_float(const cbor_item_t *item) { - assert(cbor_is_float(item)); + CBOR_ASSERT(cbor_is_float(item)); + // cppcheck-suppress missingReturn switch (cbor_float_get_width(item)) { case CBOR_FLOAT_0: return NAN; @@ -55,46 +56,45 @@ double cbor_float_get_float(const cbor_item_t *item) { case CBOR_FLOAT_64: return cbor_float_get_float8(item); } - return NAN; /* Compiler complaints */ } bool cbor_get_bool(const cbor_item_t *item) { - assert(cbor_is_bool(item)); + CBOR_ASSERT(cbor_is_bool(item)); return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE; } void cbor_set_float2(cbor_item_t *item, float value) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_16); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16); *((float *)item->data) = value; } void cbor_set_float4(cbor_item_t *item, float value) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_32); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32); *((float *)item->data) = value; } void cbor_set_float8(cbor_item_t *item, double value) { - assert(cbor_is_float(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_64); + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64); *((double *)item->data) = value; } void cbor_set_ctrl(cbor_item_t *item, uint8_t value) { - assert(cbor_isa_float_ctrl(item)); - assert(cbor_float_get_width(item) == CBOR_FLOAT_0); + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0); item->metadata.float_ctrl_metadata.ctrl = value; } void cbor_set_bool(cbor_item_t *item, bool value) { - assert(cbor_is_bool(item)); + CBOR_ASSERT(cbor_is_bool(item)); item->metadata.float_ctrl_metadata.ctrl = value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE; } -cbor_item_t *cbor_new_ctrl() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_ctrl(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -106,8 +106,8 @@ cbor_item_t *cbor_new_ctrl() { return item; } -cbor_item_t *cbor_new_float2() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4); +cbor_item_t *cbor_new_float2(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -118,8 +118,8 @@ cbor_item_t *cbor_new_float2() { return item; } -cbor_item_t *cbor_new_float4() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4); +cbor_item_t *cbor_new_float4(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -130,8 +130,8 @@ cbor_item_t *cbor_new_float4() { return item; } -cbor_item_t *cbor_new_float8() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8); +cbor_item_t *cbor_new_float8(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 8); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -142,14 +142,14 @@ cbor_item_t *cbor_new_float8() { return item; } -cbor_item_t *cbor_new_null() { +cbor_item_t *cbor_new_null(void) { cbor_item_t *item = cbor_new_ctrl(); _CBOR_NOTNULL(item); cbor_set_ctrl(item, CBOR_CTRL_NULL); return item; } -cbor_item_t *cbor_new_undef() { +cbor_item_t *cbor_new_undef(void) { cbor_item_t *item = cbor_new_ctrl(); _CBOR_NOTNULL(item); cbor_set_ctrl(item, CBOR_CTRL_UNDEF); diff --git a/lib/libcbor/src/cbor/floats_ctrls.h b/lib/libcbor/src/cbor/floats_ctrls.h index 74dd97ffde3..7065536736e 100644 --- a/lib/libcbor/src/cbor/floats_ctrls.h +++ b/lib/libcbor/src/cbor/floats_ctrls.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_FLOATS_CTRLS_H #define LIBCBOR_FLOATS_CTRLS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -25,14 +26,16 @@ extern "C" { * @param item[borrow] A float or ctrl item * @return Is this a ctrl value? */ -bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_float_ctrl_is_ctrl( + const cbor_item_t *item); /** Get the float width * * @param item[borrow] A float or ctrl item * @return The width. */ -cbor_float_width cbor_float_get_width(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_float_width +cbor_float_get_width(const cbor_item_t *item); /** Get a half precision float * @@ -41,16 +44,18 @@ cbor_float_width cbor_float_get_width(const cbor_item_t *item); * @param[borrow] A half precision float * @return half precision value */ -float cbor_float_get_float2(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT float cbor_float_get_float2( + const cbor_item_t *item); /** Get a single precision float * * The item must have the corresponding width * - * @param[borrow] A signle precision float + * @param[borrow] A single precision float * @return single precision value */ -float cbor_float_get_float4(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT float cbor_float_get_float4( + const cbor_item_t *item); /** Get a double precision float * @@ -59,7 +64,8 @@ float cbor_float_get_float4(const cbor_item_t *item); * @param[borrow] A double precision float * @return double precision value */ -double cbor_float_get_float8(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT double cbor_float_get_float8( + const cbor_item_t *item); /** Get the float value represented as double * @@ -68,14 +74,15 @@ double cbor_float_get_float8(const cbor_item_t *item); * @param[borrow] Any float * @return double precision value */ -double cbor_float_get_float(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT double cbor_float_get_float( + const cbor_item_t *item); /** Get value from a boolean ctrl item * * @param item[borrow] A ctrl item * @return boolean value */ -bool cbor_get_bool(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_get_bool(const cbor_item_t *item); /** Constructs a new ctrl item * @@ -83,7 +90,7 @@ bool cbor_get_bool(const cbor_item_t *item); * * @return **new** 1B ctrl or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_ctrl(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_ctrl(void); /** Constructs a new float item * @@ -91,7 +98,7 @@ cbor_item_t *cbor_new_ctrl(); * * @return **new** 2B float or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_float2(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float2(void); /** Constructs a new float item * @@ -99,7 +106,7 @@ cbor_item_t *cbor_new_float2(); * * @return **new** 4B float or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_float4(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float4(void); /** Constructs a new float item * @@ -107,102 +114,102 @@ cbor_item_t *cbor_new_float4(); * * @return **new** 8B float or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_float8(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float8(void); /** Constructs new null ctrl item * * @return **new** null ctrl item or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_null(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_null(void); /** Constructs new undef ctrl item * * @return **new** undef ctrl item or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_new_undef(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_undef(void); /** Constructs new boolean ctrl item * * @param value The value to use * @return **new** boolean ctrl item or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_build_bool(bool value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_bool(bool value); /** Assign a control value * * \rst * .. warning:: It is possible to produce an invalid CBOR value by assigning a - * invalid value using this mechanism. Please consult the standard before use. + * invalid value using this mechanism. Please consult the standard before use. * \endrst * * @param item[borrow] A ctrl item * @param value The simple value to assign. Please consult the standard for * allowed values */ -void cbor_set_ctrl(cbor_item_t *item, uint8_t value); +CBOR_EXPORT void cbor_set_ctrl(cbor_item_t *item, uint8_t value); /** Assign a boolean value to a boolean ctrl item * * @param item[borrow] A ctrl item * @param value The simple value to assign. */ -void cbor_set_bool(cbor_item_t *item, bool value); +CBOR_EXPORT void cbor_set_bool(cbor_item_t *item, bool value); /** Assigns a float value * * @param item[borrow] A half precision float * @param value The value to assign */ -void cbor_set_float2(cbor_item_t *item, float value); +CBOR_EXPORT void cbor_set_float2(cbor_item_t *item, float value); /** Assigns a float value * * @param item[borrow] A single precision float * @param value The value to assign */ -void cbor_set_float4(cbor_item_t *item, float value); +CBOR_EXPORT void cbor_set_float4(cbor_item_t *item, float value); /** Assigns a float value * * @param item[borrow] A double precision float * @param value The value to assign */ -void cbor_set_float8(cbor_item_t *item, double value); +CBOR_EXPORT void cbor_set_float8(cbor_item_t *item, double value); /** Reads the control value * * @param item[borrow] A ctrl item * @return the simple value */ -uint8_t cbor_ctrl_value(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint8_t cbor_ctrl_value(const cbor_item_t *item); /** Constructs a new float * * @param value the value to use * @return **new** float */ -cbor_item_t *cbor_build_float2(float value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float2(float value); /** Constructs a new float * * @param value the value to use * @return **new** float or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_build_float4(float value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float4(float value); /** Constructs a new float * * @param value the value to use * @return **new** float or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_build_float8(double value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float8(double value); /** Constructs a ctrl item * * @param value the value to use * @return **new** ctrl item or `NULL` upon memory allocation failure */ -cbor_item_t *cbor_build_ctrl(uint8_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_ctrl(uint8_t value); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/internal/builder_callbacks.c b/lib/libcbor/src/cbor/internal/builder_callbacks.c index f6c57113616..78277f050c2 100644 --- a/lib/libcbor/src/cbor/internal/builder_callbacks.c +++ b/lib/libcbor/src/cbor/internal/builder_callbacks.c @@ -6,9 +6,12 @@ */ #include "builder_callbacks.h" + #include + #include "../arrays.h" #include "../bytestrings.h" +#include "../common.h" #include "../floats_ctrls.h" #include "../ints.h" #include "../maps.h" @@ -16,73 +19,96 @@ #include "../tags.h" #include "unicode.h" +// `_cbor_builder_append` takes ownership of `item`. If adding the item to +// parent container fails, `item` will be deallocated to prevent memory. void _cbor_builder_append(cbor_item_t *item, struct _cbor_decoder_context *ctx) { if (ctx->stack->size == 0) { /* Top level item */ ctx->root = item; - } else { - /* Part of a bigger structure */ - switch (ctx->stack->top->item->type) { - case CBOR_TYPE_ARRAY: { - if (cbor_array_is_definite(ctx->stack->top->item)) { - /* - * We don't need an explicit check for whether the item still belongs - * into this array because if there are extra items, they will cause a - * syntax error when decoded. - */ - assert(ctx->stack->top->subitems > 0); - cbor_array_push(ctx->stack->top->item, item); - ctx->stack->top->subitems--; - if (ctx->stack->top->subitems == 0) { - cbor_item_t *item = ctx->stack->top->item; - _cbor_stack_pop(ctx->stack); - _cbor_builder_append(item, ctx); - } - cbor_decref(&item); - } else { - /* Indefinite array, don't bother with subitems */ - cbor_array_push(ctx->stack->top->item, item); + return; + } + /* Part of a bigger structure */ + switch (ctx->stack->top->item->type) { + // Handle Arrays and Maps since they can contain subitems of any type. + // Byte/string construction from chunks is handled in the respective chunk + // handlers. + case CBOR_TYPE_ARRAY: { + if (cbor_array_is_definite(ctx->stack->top->item)) { + // We don't need an explicit check for whether the item still belongs + // into this array because if there are extra items, they will cause a + // syntax error when decoded. + CBOR_ASSERT(ctx->stack->top->subitems > 0); + // This should never happen since the definite array should be + // preallocated for the expected number of items. + if (!cbor_array_push(ctx->stack->top->item, item)) { + ctx->creation_failed = true; cbor_decref(&item); + break; } - break; - } - case CBOR_TYPE_MAP: { - /* We use 0 and 1 subitems to distinguish between keys and values in - * indefinite items */ - if (ctx->stack->top->subitems % 2) { - /* Odd record, this is a value */ - _cbor_map_add_value(ctx->stack->top->item, cbor_move(item)); - } else { - /* Even record, this is a key */ - _cbor_map_add_key(ctx->stack->top->item, cbor_move(item)); + cbor_decref(&item); + ctx->stack->top->subitems--; + if (ctx->stack->top->subitems == 0) { + cbor_item_t *stack_item = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(stack_item, ctx); } - if (cbor_map_is_definite(ctx->stack->top->item)) { - ctx->stack->top->subitems--; - if (ctx->stack->top->subitems == 0) { - cbor_item_t *item = ctx->stack->top->item; - _cbor_stack_pop(ctx->stack); - _cbor_builder_append(item, ctx); - } - } else { - ctx->stack->top->subitems ^= - 1; /* Flip the indicator for indefinite items */ + } else { + /* Indefinite array, don't bother with subitems */ + if (!cbor_array_push(ctx->stack->top->item, item)) { + ctx->creation_failed = true; } - break; + cbor_decref(&item); } - case CBOR_TYPE_TAG: { - assert(ctx->stack->top->subitems == 1); - cbor_tag_set_item(ctx->stack->top->item, item); - cbor_decref(&item); /* Give up on our reference */ - cbor_item_t *item = ctx->stack->top->item; - _cbor_stack_pop(ctx->stack); - _cbor_builder_append(item, ctx); - break; + break; + } + case CBOR_TYPE_MAP: { + // Handle both definite and indefinite maps the same initially. + // Note: We use 0 and 1 subitems to distinguish between keys and values in + // indefinite items + if (ctx->stack->top->subitems % 2) { + /* Odd record, this is a value */ + if (!_cbor_map_add_value(ctx->stack->top->item, item)) { + ctx->creation_failed = true; + cbor_decref(&item); + break; + } + } else { + /* Even record, this is a key */ + if (!_cbor_map_add_key(ctx->stack->top->item, item)) { + ctx->creation_failed = true; + cbor_decref(&item); + break; + } } - default: { - cbor_decref(&item); - ctx->syntax_error = true; + cbor_decref(&item); + if (cbor_map_is_definite(ctx->stack->top->item)) { + CBOR_ASSERT(ctx->stack->top->subitems > 0); + ctx->stack->top->subitems--; + if (ctx->stack->top->subitems == 0) { + cbor_item_t *map_entry = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(map_entry, ctx); + } + } else { + ctx->stack->top->subitems ^= + 1; /* Flip the indicator for indefinite items */ } + break; + } + case CBOR_TYPE_TAG: { + CBOR_ASSERT(ctx->stack->top->subitems == 1); + cbor_tag_set_item(ctx->stack->top->item, item); + cbor_decref(&item); /* Give up on our reference */ + cbor_item_t *tagged_item = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(tagged_item, ctx); + break; + } + // We have an item to append but nothing to append it to. + default: { + cbor_decref(&item); + ctx->syntax_error = true; } } } @@ -95,6 +121,16 @@ void _cbor_builder_append(cbor_item_t *item, } \ } while (0) +// Check that the length fits into size_t. If not, we cannot possibly allocate +// the required memory and should fail fast. +#define CHECK_LENGTH(ctx, length) \ + do { \ + if (length > SIZE_MAX) { \ + ctx->creation_failed = true; \ + return; \ + } \ + } while (0) + #define PUSH_CTX_STACK(ctx, res, subitems) \ do { \ if (_cbor_stack_push(ctx->stack, res, subitems) == NULL) { \ @@ -151,6 +187,7 @@ void cbor_builder_negint8_callback(void *context, uint8_t value) { void cbor_builder_negint16_callback(void *context, uint16_t value) { struct _cbor_decoder_context *ctx = context; cbor_item_t *res = cbor_new_int16(); + CHECK_RES(ctx, res); cbor_mark_negint(res); cbor_set_uint16(res, value); _cbor_builder_append(res, ctx); @@ -175,34 +212,36 @@ void cbor_builder_negint64_callback(void *context, uint64_t value) { } void cbor_builder_byte_string_callback(void *context, cbor_data data, - size_t length) { + uint64_t length) { struct _cbor_decoder_context *ctx = context; - unsigned char *new_handle = _CBOR_MALLOC(length); + CHECK_LENGTH(ctx, length); + unsigned char *new_handle = _cbor_malloc(length); if (new_handle == NULL) { ctx->creation_failed = true; return; } memcpy(new_handle, data, length); - cbor_item_t *res = cbor_new_definite_bytestring(); + cbor_item_t *new_chunk = cbor_new_definite_bytestring(); - if (res == NULL) { - _CBOR_FREE(new_handle); + if (new_chunk == NULL) { + _cbor_free(new_handle); ctx->creation_failed = true; return; } - cbor_bytestring_set_handle(res, new_handle, length); + cbor_bytestring_set_handle(new_chunk, new_handle, length); - if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item)) { - if (cbor_bytestring_is_indefinite(ctx->stack->top->item)) { - cbor_bytestring_add_chunk(ctx->stack->top->item, cbor_move(res)); - } else { - cbor_decref(&res); - ctx->syntax_error = true; + // If an indef bytestring is on the stack, extend it (if it were closed, it + // would have been popped). Handle any syntax errors upstream. + if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item) && + cbor_bytestring_is_indefinite(ctx->stack->top->item)) { + if (!cbor_bytestring_add_chunk(ctx->stack->top->item, new_chunk)) { + ctx->creation_failed = true; } + cbor_decref(&new_chunk); } else { - _cbor_builder_append(res, ctx); + _cbor_builder_append(new_chunk, ctx); } } @@ -214,19 +253,20 @@ void cbor_builder_byte_string_start_callback(void *context) { } void cbor_builder_string_callback(void *context, cbor_data data, - size_t length) { + uint64_t length) { struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, length); struct _cbor_unicode_status unicode_status; - - size_t codepoint_count = + uint64_t codepoint_count = _cbor_unicode_codepoint_count(data, length, &unicode_status); - if (unicode_status.status == _CBOR_UNICODE_BADCP) { + if (unicode_status.status != _CBOR_UNICODE_OK) { ctx->syntax_error = true; return; } + CBOR_ASSERT(codepoint_count <= length); - unsigned char *new_handle = _CBOR_MALLOC(length); + unsigned char *new_handle = _cbor_malloc(length); if (new_handle == NULL) { ctx->creation_failed = true; @@ -234,25 +274,25 @@ void cbor_builder_string_callback(void *context, cbor_data data, } memcpy(new_handle, data, length); - cbor_item_t *res = cbor_new_definite_string(); - if (res == NULL) { - _CBOR_FREE(new_handle); + cbor_item_t *new_chunk = cbor_new_definite_string(); + if (new_chunk == NULL) { + _cbor_free(new_handle); ctx->creation_failed = true; return; } - cbor_string_set_handle(res, new_handle, length); - res->metadata.string_metadata.codepoint_count = codepoint_count; - - /* Careful here: order matters */ - if (ctx->stack->size > 0 && cbor_isa_string(ctx->stack->top->item)) { - if (cbor_string_is_indefinite(ctx->stack->top->item)) { - cbor_string_add_chunk(ctx->stack->top->item, cbor_move(res)); - } else { - cbor_decref(&res); - ctx->syntax_error = true; + cbor_string_set_handle(new_chunk, new_handle, length); + new_chunk->metadata.string_metadata.codepoint_count = codepoint_count; + + // If an indef string is on the stack, extend it (if it were closed, it would + // have been popped). Handle any syntax errors upstream. + if (ctx->stack->size > 0 && cbor_isa_string(ctx->stack->top->item) && + cbor_string_is_indefinite(ctx->stack->top->item)) { + if (!cbor_string_add_chunk(ctx->stack->top->item, new_chunk)) { + ctx->creation_failed = true; } + cbor_decref(&new_chunk); } else { - _cbor_builder_append(res, ctx); + _cbor_builder_append(new_chunk, ctx); } } @@ -263,8 +303,9 @@ void cbor_builder_string_start_callback(void *context) { PUSH_CTX_STACK(ctx, res, 0); } -void cbor_builder_array_start_callback(void *context, size_t size) { +void cbor_builder_array_start_callback(void *context, uint64_t size) { struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, size); cbor_item_t *res = cbor_new_definite_array(size); CHECK_RES(ctx, res); if (size > 0) { @@ -288,8 +329,9 @@ void cbor_builder_indef_map_start_callback(void *context) { PUSH_CTX_STACK(ctx, res, 0); } -void cbor_builder_map_start_callback(void *context, size_t size) { +void cbor_builder_map_start_callback(void *context, uint64_t size) { struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, size); cbor_item_t *res = cbor_new_definite_map(size); CHECK_RES(ctx, res); if (size > 0) { @@ -305,14 +347,13 @@ void cbor_builder_map_start_callback(void *context, size_t size) { bool _cbor_is_indefinite(cbor_item_t *item) { switch (item->type) { case CBOR_TYPE_BYTESTRING: - return item->metadata.bytestring_metadata.type == - _CBOR_METADATA_INDEFINITE; + return cbor_bytestring_is_indefinite(item); case CBOR_TYPE_STRING: - return item->metadata.string_metadata.type == _CBOR_METADATA_INDEFINITE; + return cbor_string_is_indefinite(item); case CBOR_TYPE_ARRAY: - return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE; + return cbor_array_is_indefinite(item); case CBOR_TYPE_MAP: - return item->metadata.map_metadata.type == _CBOR_METADATA_INDEFINITE; + return cbor_map_is_indefinite(item); default: return false; } @@ -340,6 +381,7 @@ void cbor_builder_indef_break_callback(void *context) { void cbor_builder_float2_callback(void *context, float value) { struct _cbor_decoder_context *ctx = context; cbor_item_t *res = cbor_new_float2(); + CHECK_RES(ctx, res); cbor_set_float2(res, value); _cbor_builder_append(res, ctx); } diff --git a/lib/libcbor/src/cbor/internal/builder_callbacks.h b/lib/libcbor/src/cbor/internal/builder_callbacks.h index a93afb1ca8f..7893960e413 100644 --- a/lib/libcbor/src/cbor/internal/builder_callbacks.h +++ b/lib/libcbor/src/cbor/internal/builder_callbacks.h @@ -26,6 +26,10 @@ struct _cbor_decoder_context { struct _cbor_stack *stack; }; +/** Internal helper: Append item to the top of the stack while handling errors. + */ +void _cbor_builder_append(cbor_item_t *item, struct _cbor_decoder_context *ctx); + void cbor_builder_uint8_callback(void *, uint8_t); void cbor_builder_uint16_callback(void *, uint16_t); @@ -42,19 +46,19 @@ void cbor_builder_negint32_callback(void *, uint32_t); void cbor_builder_negint64_callback(void *, uint64_t); -void cbor_builder_string_callback(void *, cbor_data, size_t); +void cbor_builder_string_callback(void *, cbor_data, uint64_t); void cbor_builder_string_start_callback(void *); -void cbor_builder_byte_string_callback(void *, cbor_data, size_t); +void cbor_builder_byte_string_callback(void *, cbor_data, uint64_t); void cbor_builder_byte_string_start_callback(void *); -void cbor_builder_array_start_callback(void *, size_t); +void cbor_builder_array_start_callback(void *, uint64_t); void cbor_builder_indef_array_start_callback(void *); -void cbor_builder_map_start_callback(void *, size_t); +void cbor_builder_map_start_callback(void *, uint64_t); void cbor_builder_indef_map_start_callback(void *); diff --git a/lib/libcbor/src/cbor/internal/encoders.c b/lib/libcbor/src/cbor/internal/encoders.c index 657e25c3987..49d4d7f33d2 100644 --- a/lib/libcbor/src/cbor/internal/encoders.c +++ b/lib/libcbor/src/cbor/internal/encoders.c @@ -33,8 +33,8 @@ size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, #ifdef IS_BIG_ENDIAN memcpy(buffer + 1, &value, 2); #else - buffer[1] = value >> 8; - buffer[2] = value; + buffer[1] = (unsigned char)(value >> 8); + buffer[2] = (unsigned char)value; #endif return 3; @@ -50,10 +50,10 @@ size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, #ifdef IS_BIG_ENDIAN memcpy(buffer + 1, &value, 4); #else - buffer[1] = value >> 24; - buffer[2] = value >> 16; - buffer[3] = value >> 8; - buffer[4] = value; + buffer[1] = (unsigned char)(value >> 24); + buffer[2] = (unsigned char)(value >> 16); + buffer[3] = (unsigned char)(value >> 8); + buffer[4] = (unsigned char)value; #endif return 5; @@ -69,14 +69,14 @@ size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, #ifdef IS_BIG_ENDIAN memcpy(buffer + 1, &value, 8); #else - buffer[1] = value >> 56; - buffer[2] = value >> 48; - buffer[3] = value >> 40; - buffer[4] = value >> 32; - buffer[5] = value >> 24; - buffer[6] = value >> 16; - buffer[7] = value >> 8; - buffer[8] = value; + buffer[1] = (unsigned char)(value >> 56); + buffer[2] = (unsigned char)(value >> 48); + buffer[3] = (unsigned char)(value >> 40); + buffer[4] = (unsigned char)(value >> 32); + buffer[5] = (unsigned char)(value >> 24); + buffer[6] = (unsigned char)(value >> 16); + buffer[7] = (unsigned char)(value >> 8); + buffer[8] = (unsigned char)value; #endif return 9; diff --git a/lib/libcbor/src/cbor/internal/encoders.h b/lib/libcbor/src/cbor/internal/encoders.h index 14ad5015cb5..7eadb712164 100644 --- a/lib/libcbor/src/cbor/internal/encoders.h +++ b/lib/libcbor/src/cbor/internal/encoders.h @@ -14,18 +14,23 @@ extern "C" { #endif +_CBOR_NODISCARD size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset); +_CBOR_NODISCARD size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset); +_CBOR_NODISCARD size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset); +_CBOR_NODISCARD size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset); +_CBOR_NODISCARD size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset); diff --git a/lib/libcbor/src/cbor/internal/loaders.c b/lib/libcbor/src/cbor/internal/loaders.c index af00f135527..c25c6335831 100644 --- a/lib/libcbor/src/cbor/internal/loaders.c +++ b/lib/libcbor/src/cbor/internal/loaders.c @@ -64,7 +64,7 @@ float _cbor_decode_half(unsigned char *halfp) { return (float)(half & 0x8000 ? -val : val); } -double _cbor_load_half(cbor_data source) { +float _cbor_load_half(cbor_data source) { /* Discard const */ return _cbor_decode_half((unsigned char *)source); } diff --git a/lib/libcbor/src/cbor/internal/loaders.h b/lib/libcbor/src/cbor/internal/loaders.h index a4c82b209f5..ce37563a3d8 100644 --- a/lib/libcbor/src/cbor/internal/loaders.h +++ b/lib/libcbor/src/cbor/internal/loaders.h @@ -15,18 +15,25 @@ extern "C" { #endif /* Read the given uint from the given location, no questions asked */ +_CBOR_NODISCARD uint8_t _cbor_load_uint8(const unsigned char *source); +_CBOR_NODISCARD uint16_t _cbor_load_uint16(const unsigned char *source); +_CBOR_NODISCARD uint32_t _cbor_load_uint32(const unsigned char *source); +_CBOR_NODISCARD uint64_t _cbor_load_uint64(const unsigned char *source); -double _cbor_load_half(cbor_data source); +_CBOR_NODISCARD +float _cbor_load_half(cbor_data source); +_CBOR_NODISCARD float _cbor_load_float(cbor_data source); +_CBOR_NODISCARD double _cbor_load_double(cbor_data source); #ifdef __cplusplus diff --git a/lib/libcbor/src/cbor/internal/memory_utils.c b/lib/libcbor/src/cbor/internal/memory_utils.c index 918b708e331..bbea63cb9f0 100644 --- a/lib/libcbor/src/cbor/internal/memory_utils.c +++ b/lib/libcbor/src/cbor/internal/memory_utils.c @@ -23,12 +23,25 @@ size_t _cbor_highest_bit(size_t number) { } bool _cbor_safe_to_multiply(size_t a, size_t b) { + if (a <= 1 || b <= 1) return true; return _cbor_highest_bit(a) + _cbor_highest_bit(b) <= sizeof(size_t) * 8; } +bool _cbor_safe_to_add(size_t a, size_t b) { + // Unsigned integer overflow doesn't constitute UB + size_t sum = a + b; + return sum >= a && sum >= b; +} + +size_t _cbor_safe_signaling_add(size_t a, size_t b) { + if (a == 0 || b == 0) return 0; + if (_cbor_safe_to_add(a, b)) return a + b; + return 0; +} + void* _cbor_alloc_multiple(size_t item_size, size_t item_count) { if (_cbor_safe_to_multiply(item_size, item_count)) { - return _CBOR_MALLOC(item_size * item_count); + return _cbor_malloc(item_size * item_count); } else { return NULL; } @@ -37,7 +50,7 @@ void* _cbor_alloc_multiple(size_t item_size, size_t item_count) { void* _cbor_realloc_multiple(void* pointer, size_t item_size, size_t item_count) { if (_cbor_safe_to_multiply(item_size, item_count)) { - return _CBOR_REALLOC(pointer, item_size * item_count); + return _cbor_realloc(pointer, item_size * item_count); } else { return NULL; } diff --git a/lib/libcbor/src/cbor/internal/memory_utils.h b/lib/libcbor/src/cbor/internal/memory_utils.h index c41ace67948..14843c8c56f 100644 --- a/lib/libcbor/src/cbor/internal/memory_utils.h +++ b/lib/libcbor/src/cbor/internal/memory_utils.h @@ -11,9 +11,20 @@ #include #include -/** Can a and b be multiplied without overflowing size_t? */ +#include "cbor/common.h" + +/** Can `a` and `b` be multiplied without overflowing size_t? */ +_CBOR_NODISCARD bool _cbor_safe_to_multiply(size_t a, size_t b); +/** Can `a` and `b` be added without overflowing size_t? */ +_CBOR_NODISCARD +bool _cbor_safe_to_add(size_t a, size_t b); + +/** Adds `a` and `b`, propagating zeros and returing 0 on overflow. */ +_CBOR_NODISCARD +size_t _cbor_safe_signaling_add(size_t a, size_t b); + /** Overflow-proof contiguous array allocation * * @param item_size diff --git a/lib/libcbor/src/cbor/internal/stack.c b/lib/libcbor/src/cbor/internal/stack.c index 79c9e5e5297..2db03cbbf08 100644 --- a/lib/libcbor/src/cbor/internal/stack.c +++ b/lib/libcbor/src/cbor/internal/stack.c @@ -7,14 +7,14 @@ #include "stack.h" -struct _cbor_stack _cbor_stack_init() { +struct _cbor_stack _cbor_stack_init(void) { return (struct _cbor_stack){.top = NULL, .size = 0}; } void _cbor_stack_pop(struct _cbor_stack *stack) { struct _cbor_stack_record *top = stack->top; stack->top = stack->top->lower; - _CBOR_FREE(top); + _cbor_free(top); stack->size--; } @@ -23,7 +23,7 @@ struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *stack, size_t subitems) { if (stack->size == CBOR_MAX_STACK_SIZE) return NULL; struct _cbor_stack_record *new_top = - _CBOR_MALLOC(sizeof(struct _cbor_stack_record)); + _cbor_malloc(sizeof(struct _cbor_stack_record)); if (new_top == NULL) return NULL; *new_top = (struct _cbor_stack_record){stack->top, item, subitems}; diff --git a/lib/libcbor/src/cbor/internal/stack.h b/lib/libcbor/src/cbor/internal/stack.h index 42ed04429c7..cf2206b40e5 100644 --- a/lib/libcbor/src/cbor/internal/stack.h +++ b/lib/libcbor/src/cbor/internal/stack.h @@ -16,8 +16,18 @@ extern "C" { /** Simple stack record for the parser */ struct _cbor_stack_record { + /** Pointer to the parent stack frame */ struct _cbor_stack_record *lower; + /** Item under construction */ cbor_item_t *item; + /** + * How many outstanding subitems are expected. + * + * For example, when we see a new definite array, `subitems` is initialized to + * the array length. With every item added, the counter is decreased. When it + * reaches zero, the stack is popped and the complete item is propagated + * upwards. + */ size_t subitems; }; @@ -27,10 +37,12 @@ struct _cbor_stack { size_t size; }; -struct _cbor_stack _cbor_stack_init(); +_CBOR_NODISCARD +struct _cbor_stack _cbor_stack_init(void); void _cbor_stack_pop(struct _cbor_stack *); +_CBOR_NODISCARD struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *, cbor_item_t *, size_t); diff --git a/lib/libcbor/src/cbor/internal/unicode.c b/lib/libcbor/src/cbor/internal/unicode.c index 98b49728989..1831c8e6205 100644 --- a/lib/libcbor/src/cbor/internal/unicode.c +++ b/lib/libcbor/src/cbor/internal/unicode.c @@ -6,6 +6,7 @@ */ #include "unicode.h" +#include #define UTF8_ACCEPT 0 #define UTF8_REJECT 1 @@ -65,12 +66,12 @@ uint32_t _cbor_unicode_decode(uint32_t* state, uint32_t* codep, uint32_t byte) { return *state; } -size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, - struct _cbor_unicode_status* status) { +uint64_t _cbor_unicode_codepoint_count(cbor_data source, uint64_t source_length, + struct _cbor_unicode_status* status) { *status = (struct _cbor_unicode_status){.location = 0, .status = _CBOR_UNICODE_OK}; uint32_t codepoint, state = UTF8_ACCEPT, res; - size_t pos = 0, count = 0; + uint64_t pos = 0, count = 0; for (; pos < source_length; pos++) { res = _cbor_unicode_decode(&state, &codepoint, source[pos]); @@ -90,5 +91,5 @@ size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, error: *status = (struct _cbor_unicode_status){.location = pos, .status = _CBOR_UNICODE_BADCP}; - return -1; + return 0; } diff --git a/lib/libcbor/src/cbor/internal/unicode.h b/lib/libcbor/src/cbor/internal/unicode.h index 5f645602930..af32cc7ff02 100644 --- a/lib/libcbor/src/cbor/internal/unicode.h +++ b/lib/libcbor/src/cbor/internal/unicode.h @@ -19,11 +19,12 @@ enum _cbor_unicode_status_error { _CBOR_UNICODE_OK, _CBOR_UNICODE_BADCP }; /** Signals unicode validation error and possibly its location */ struct _cbor_unicode_status { enum _cbor_unicode_status_error status; - size_t location; + uint64_t location; }; -size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, - struct _cbor_unicode_status* status); +_CBOR_NODISCARD +uint64_t _cbor_unicode_codepoint_count(cbor_data source, uint64_t source_length, + struct _cbor_unicode_status* status); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/ints.c b/lib/libcbor/src/cbor/ints.c index 880982e5a3e..b4d035a1897 100644 --- a/lib/libcbor/src/cbor/ints.c +++ b/lib/libcbor/src/cbor/ints.c @@ -8,36 +8,37 @@ #include "ints.h" cbor_int_width cbor_int_get_width(const cbor_item_t *item) { - assert(cbor_is_int(item)); + CBOR_ASSERT(cbor_is_int(item)); return item->metadata.int_metadata.width; } uint8_t cbor_get_uint8(const cbor_item_t *item) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_8); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_8); return *item->data; } uint16_t cbor_get_uint16(const cbor_item_t *item) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_16); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_16); return *(uint16_t *)item->data; } uint32_t cbor_get_uint32(const cbor_item_t *item) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_32); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_32); return *(uint32_t *)item->data; } uint64_t cbor_get_uint64(const cbor_item_t *item) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_64); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_64); return *(uint64_t *)item->data; } uint64_t cbor_get_int(const cbor_item_t *item) { - assert(cbor_is_int(item)); + CBOR_ASSERT(cbor_is_int(item)); + // cppcheck-suppress missingReturn switch (cbor_int_get_width(item)) { case CBOR_INT_8: return cbor_get_uint8(item); @@ -48,46 +49,44 @@ uint64_t cbor_get_int(const cbor_item_t *item) { case CBOR_INT_64: return cbor_get_uint64(item); } - // TODO: This should be handled in a default branch - return 0xDEADBEEF; /* Compiler complaints */ } void cbor_set_uint8(cbor_item_t *item, uint8_t value) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_8); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_8); *item->data = value; } void cbor_set_uint16(cbor_item_t *item, uint16_t value) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_16); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_16); *(uint16_t *)item->data = value; } void cbor_set_uint32(cbor_item_t *item, uint32_t value) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_32); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_32); *(uint32_t *)item->data = value; } void cbor_set_uint64(cbor_item_t *item, uint64_t value) { - assert(cbor_is_int(item)); - assert(cbor_int_get_width(item) == CBOR_INT_64); + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_64); *(uint64_t *)item->data = value; } void cbor_mark_uint(cbor_item_t *item) { - assert(cbor_is_int(item)); + CBOR_ASSERT(cbor_is_int(item)); item->type = CBOR_TYPE_UINT; } void cbor_mark_negint(cbor_item_t *item) { - assert(cbor_is_int(item)); + CBOR_ASSERT(cbor_is_int(item)); item->type = CBOR_TYPE_NEGINT; } -cbor_item_t *cbor_new_int8() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 1); +cbor_item_t *cbor_new_int8(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 1); _CBOR_NOTNULL(item); *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), .refcount = 1, @@ -96,8 +95,8 @@ cbor_item_t *cbor_new_int8() { return item; } -cbor_item_t *cbor_new_int16() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 2); +cbor_item_t *cbor_new_int16(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 2); _CBOR_NOTNULL(item); *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), .refcount = 1, @@ -106,8 +105,8 @@ cbor_item_t *cbor_new_int16() { return item; } -cbor_item_t *cbor_new_int32() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4); +cbor_item_t *cbor_new_int32(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); _CBOR_NOTNULL(item); *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), .refcount = 1, @@ -116,8 +115,8 @@ cbor_item_t *cbor_new_int32() { return item; } -cbor_item_t *cbor_new_int64() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8); +cbor_item_t *cbor_new_int64(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 8); _CBOR_NOTNULL(item); *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), .refcount = 1, diff --git a/lib/libcbor/src/cbor/ints.h b/lib/libcbor/src/cbor/ints.h index f965c298948..9c1d5723948 100644 --- a/lib/libcbor/src/cbor/ints.h +++ b/lib/libcbor/src/cbor/ints.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_INTS_H #define LIBCBOR_INTS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -25,35 +26,35 @@ extern "C" { * @param item[borrow] positive or negative integer * @return the value */ -uint8_t cbor_get_uint8(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint8_t cbor_get_uint8(const cbor_item_t *item); /** Extracts the integer value * * @param item[borrow] positive or negative integer * @return the value */ -uint16_t cbor_get_uint16(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint16_t cbor_get_uint16(const cbor_item_t *item); /** Extracts the integer value * * @param item[borrow] positive or negative integer * @return the value */ -uint32_t cbor_get_uint32(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint32_t cbor_get_uint32(const cbor_item_t *item); /** Extracts the integer value * * @param item[borrow] positive or negative integer * @return the value */ -uint64_t cbor_get_uint64(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_get_uint64(const cbor_item_t *item); /** Extracts the integer value * * @param item[borrow] positive or negative integer * @return the value, extended to `uint64_t` */ -uint64_t cbor_get_int(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_get_int(const cbor_item_t *item); /** Assigns the integer value * @@ -61,7 +62,7 @@ uint64_t cbor_get_int(const cbor_item_t *item); * @param value the value to assign. For negative integer, the logical value is * `-value - 1` */ -void cbor_set_uint8(cbor_item_t *item, uint8_t value); +CBOR_EXPORT void cbor_set_uint8(cbor_item_t *item, uint8_t value); /** Assigns the integer value * @@ -69,7 +70,7 @@ void cbor_set_uint8(cbor_item_t *item, uint8_t value); * @param value the value to assign. For negative integer, the logical value is * `-value - 1` */ -void cbor_set_uint16(cbor_item_t *item, uint16_t value); +CBOR_EXPORT void cbor_set_uint16(cbor_item_t *item, uint16_t value); /** Assigns the integer value * @@ -77,7 +78,7 @@ void cbor_set_uint16(cbor_item_t *item, uint16_t value); * @param value the value to assign. For negative integer, the logical value is * `-value - 1` */ -void cbor_set_uint32(cbor_item_t *item, uint32_t value); +CBOR_EXPORT void cbor_set_uint32(cbor_item_t *item, uint32_t value); /** Assigns the integer value * @@ -85,14 +86,15 @@ void cbor_set_uint32(cbor_item_t *item, uint32_t value); * @param value the value to assign. For negative integer, the logical value is * `-value - 1` */ -void cbor_set_uint64(cbor_item_t *item, uint64_t value); +CBOR_EXPORT void cbor_set_uint64(cbor_item_t *item, uint64_t value); /** Queries the integer width * * @param item[borrow] positive or negative integer item * @return the width */ -cbor_int_width cbor_int_get_width(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_int_width +cbor_int_get_width(const cbor_item_t *item); /** Marks the integer item as a positive integer * @@ -100,7 +102,7 @@ cbor_int_width cbor_int_get_width(const cbor_item_t *item); * * @param item[borrow] positive or negative integer item */ -void cbor_mark_uint(cbor_item_t *item); +CBOR_EXPORT void cbor_mark_uint(cbor_item_t *item); /** Marks the integer item as a negative integer * @@ -108,7 +110,7 @@ void cbor_mark_uint(cbor_item_t *item); * * @param item[borrow] positive or negative integer item */ -void cbor_mark_negint(cbor_item_t *item); +CBOR_EXPORT void cbor_mark_negint(cbor_item_t *item); /** Allocates new integer with 1B width * @@ -117,7 +119,7 @@ void cbor_mark_negint(cbor_item_t *item); * @return **new** positive integer or `NULL` on memory allocation failure. The * value is not initialized */ -cbor_item_t *cbor_new_int8(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int8(void); /** Allocates new integer with 2B width * @@ -126,7 +128,7 @@ cbor_item_t *cbor_new_int8(); * @return **new** positive integer or `NULL` on memory allocation failure. The * value is not initialized */ -cbor_item_t *cbor_new_int16(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int16(void); /** Allocates new integer with 4B width * @@ -135,7 +137,7 @@ cbor_item_t *cbor_new_int16(); * @return **new** positive integer or `NULL` on memory allocation failure. The * value is not initialized */ -cbor_item_t *cbor_new_int32(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int32(void); /** Allocates new integer with 8B width * @@ -144,63 +146,63 @@ cbor_item_t *cbor_new_int32(); * @return **new** positive integer or `NULL` on memory allocation failure. The * value is not initialized */ -cbor_item_t *cbor_new_int64(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int64(void); /** Constructs a new positive integer * * @param value the value to use * @return **new** positive integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_uint8(uint8_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint8(uint8_t value); /** Constructs a new positive integer * * @param value the value to use * @return **new** positive integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_uint16(uint16_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint16(uint16_t value); /** Constructs a new positive integer * * @param value the value to use * @return **new** positive integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_uint32(uint32_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint32(uint32_t value); /** Constructs a new positive integer * * @param value the value to use * @return **new** positive integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_uint64(uint64_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint64(uint64_t value); /** Constructs a new negative integer * * @param value the value to use * @return **new** negative integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_negint8(uint8_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint8(uint8_t value); /** Constructs a new negative integer * * @param value the value to use * @return **new** negative integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_negint16(uint16_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint16(uint16_t value); /** Constructs a new negative integer * * @param value the value to use * @return **new** negative integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_negint32(uint32_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint32(uint32_t value); /** Constructs a new negative integer * * @param value the value to use * @return **new** negative integer or `NULL` on memory allocation failure */ -cbor_item_t *cbor_build_negint64(uint64_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint64(uint64_t value); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/maps.c b/lib/libcbor/src/cbor/maps.c index 45140e2cfa2..8711e57acb7 100644 --- a/lib/libcbor/src/cbor/maps.c +++ b/lib/libcbor/src/cbor/maps.c @@ -9,17 +9,17 @@ #include "internal/memory_utils.h" size_t cbor_map_size(const cbor_item_t *item) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); return item->metadata.map_metadata.end_ptr; } size_t cbor_map_allocated(const cbor_item_t *item) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); return item->metadata.map_metadata.allocated; } cbor_item_t *cbor_new_definite_map(size_t size) { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -34,8 +34,8 @@ cbor_item_t *cbor_new_definite_map(size_t size) { return item; } -cbor_item_t *cbor_new_indefinite_map() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_indefinite_map(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -50,7 +50,7 @@ cbor_item_t *cbor_new_indefinite_map() { } bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); struct _cbor_map_metadata *metadata = (struct _cbor_map_metadata *)&item->metadata; if (cbor_map_is_definite(item)) { @@ -66,7 +66,6 @@ bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key) { if (metadata->end_ptr >= metadata->allocated) { /* Exponential realloc */ // Check for overflows first - // TODO: Explicitly test this if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { return false; } @@ -94,7 +93,7 @@ bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key) { } bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); cbor_incref(value); cbor_map_handle(item)[ /* Move one back since we are assuming _add_key (which increased the ptr) @@ -105,13 +104,13 @@ bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value) { } bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); if (!_cbor_map_add_key(item, pair.key)) return false; return _cbor_map_add_value(item, pair.value); } bool cbor_map_is_definite(const cbor_item_t *item) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE; } @@ -120,6 +119,6 @@ bool cbor_map_is_indefinite(const cbor_item_t *item) { } struct cbor_pair *cbor_map_handle(const cbor_item_t *item) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); return (struct cbor_pair *)item->data; } diff --git a/lib/libcbor/src/cbor/maps.h b/lib/libcbor/src/cbor/maps.h index 4e27eefe325..2c57412cafe 100644 --- a/lib/libcbor/src/cbor/maps.h +++ b/lib/libcbor/src/cbor/maps.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_MAPS_H #define LIBCBOR_MAPS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -25,28 +26,27 @@ extern "C" { * @param item[borrow] A map * @return The number of pairs */ -size_t cbor_map_size(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_map_size(const cbor_item_t *item); /** Get the size of the allocated storage * * @param item[borrow] A map * @return Allocated storage size (as the number of #cbor_pair items) */ -size_t cbor_map_allocated(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_map_allocated(const cbor_item_t *item); /** Create a new definite map * * @param size The number of slots to preallocate * @return **new** definite map. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_definite_map(size_t size); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_definite_map(size_t size); /** Create a new indefinite map * - * @param size The number of slots to preallocate - * @return **new** definite map. `NULL` on malloc failure. + * @return **new** indefinite map. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_indefinite_map(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_indefinite_map(void); /** Add a pair to the map * @@ -56,9 +56,10 @@ cbor_item_t *cbor_new_indefinite_map(); * @param item[borrow] A map * @param pair[incref] The key-value pair to add (incref is member-wise) * @return `true` on success, `false` if either reallocation failed or the - * preallcoated storage is full + * preallocated storage is full */ -bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_add(cbor_item_t *item, + struct cbor_pair pair); /** Add a key to the map * @@ -67,9 +68,10 @@ bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair); * @param item[borrow] A map * @param key[incref] The key * @return `true` on success, `false` if either reallocation failed or the - * preallcoated storage is full + * preallocated storage is full */ -bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key); +_CBOR_NODISCARD CBOR_EXPORT bool _cbor_map_add_key(cbor_item_t *item, + cbor_item_t *key); /** Add a value to the map * @@ -78,23 +80,25 @@ bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key); * @param item[borrow] A map * @param key[incref] The value * @return `true` on success, `false` if either reallocation failed or the - * preallcoated storage is full + * preallocated storage is full */ -bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value); +_CBOR_NODISCARD CBOR_EXPORT bool _cbor_map_add_value(cbor_item_t *item, + cbor_item_t *value); /** Is this map definite? * * @param item[borrow] A map * @return Is this map definite? */ -bool cbor_map_is_definite(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_is_definite(const cbor_item_t *item); /** Is this map indefinite? * * @param item[borrow] A map * @return Is this map indefinite? */ -bool cbor_map_is_indefinite(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_is_indefinite( + const cbor_item_t *item); /** Get the pairs storage * @@ -102,7 +106,8 @@ bool cbor_map_is_indefinite(const cbor_item_t *item); * @return Array of #cbor_map_size pairs. Manipulation is possible as long as * references remain valid. */ -struct cbor_pair *cbor_map_handle(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT struct cbor_pair *cbor_map_handle( + const cbor_item_t *item); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/serialization.c b/lib/libcbor/src/cbor/serialization.c index 41343eff994..40f4c531d57 100644 --- a/lib/libcbor/src/cbor/serialization.c +++ b/lib/libcbor/src/cbor/serialization.c @@ -19,6 +19,7 @@ size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { + // cppcheck-suppress missingReturn switch (cbor_typeof(item)) { case CBOR_TYPE_UINT: return cbor_serialize_uint(item, buffer, buffer_size); @@ -36,44 +37,144 @@ size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, return cbor_serialize_tag(item, buffer, buffer_size); case CBOR_TYPE_FLOAT_CTRL: return cbor_serialize_float_ctrl(item, buffer, buffer_size); - default: - return 0; } } -size_t cbor_serialize_alloc(const cbor_item_t *item, unsigned char **buffer, - size_t *buffer_size) { - size_t bfr_size = 32; - unsigned char *bfr = _CBOR_MALLOC(bfr_size), *tmp_bfr; - if (bfr == NULL) { - return 0; - } +/** Largest integer that can be encoded as embedded in the item leading byte. */ +const uint64_t kMaxEmbeddedInt = 23; - size_t written; +/** How many bytes will a tag for a nested item of a given `size` take when + * encoded.*/ +size_t _cbor_encoded_header_size(uint64_t size) { + if (size <= kMaxEmbeddedInt) + return 1; + else if (size <= UINT8_MAX) + return 2; + else if (size <= UINT16_MAX) + return 3; + else if (size <= UINT32_MAX) + return 5; + else + return 9; +} - /* This is waaay too optimistic - figure out something smarter (eventually) */ - while ((written = cbor_serialize(item, bfr, bfr_size)) == 0) { - if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, bfr_size)) { - _CBOR_FREE(bfr); - return 0; +size_t cbor_serialized_size(const cbor_item_t *item) { + // cppcheck-suppress missingReturn + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: + case CBOR_TYPE_NEGINT: + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + if (cbor_get_uint8(item) <= kMaxEmbeddedInt) return 1; + return 2; + case CBOR_INT_16: + return 3; + case CBOR_INT_32: + return 5; + case CBOR_INT_64: + return 9; + } + // Note: We do not _cbor_safe_signaling_add zero-length definite strings, + // they would cause zeroes to propagate. All other items are at least one + // byte. + case CBOR_TYPE_BYTESTRING: { + if (cbor_bytestring_is_definite(item)) { + size_t header_size = + _cbor_encoded_header_size(cbor_bytestring_length(item)); + if (cbor_bytestring_length(item) == 0) return header_size; + return _cbor_safe_signaling_add(header_size, + cbor_bytestring_length(item)); + } + size_t indef_bytestring_size = 2; // Leading byte + break + cbor_item_t **chunks = cbor_bytestring_chunks_handle(item); + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { + indef_bytestring_size = _cbor_safe_signaling_add( + indef_bytestring_size, cbor_serialized_size(chunks[i])); + } + return indef_bytestring_size; } - - tmp_bfr = _CBOR_REALLOC(bfr, bfr_size *= 2); - - if (tmp_bfr == NULL) { - _CBOR_FREE(bfr); - return 0; + case CBOR_TYPE_STRING: { + if (cbor_string_is_definite(item)) { + size_t header_size = + _cbor_encoded_header_size(cbor_string_length(item)); + if (cbor_string_length(item) == 0) return header_size; + return _cbor_safe_signaling_add(header_size, cbor_string_length(item)); + } + size_t indef_string_size = 2; // Leading byte + break + cbor_item_t **chunks = cbor_string_chunks_handle(item); + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { + indef_string_size = _cbor_safe_signaling_add( + indef_string_size, cbor_serialized_size(chunks[i])); + } + return indef_string_size; + } + case CBOR_TYPE_ARRAY: { + size_t array_size = cbor_array_is_definite(item) + ? _cbor_encoded_header_size(cbor_array_size(item)) + : 2; // Leading byte + break + cbor_item_t **items = cbor_array_handle(item); + for (size_t i = 0; i < cbor_array_size(item); i++) { + array_size = _cbor_safe_signaling_add(array_size, + cbor_serialized_size(items[i])); + } + return array_size; + } + case CBOR_TYPE_MAP: { + size_t map_size = cbor_map_is_definite(item) + ? _cbor_encoded_header_size(cbor_map_size(item)) + : 2; // Leading byte + break + struct cbor_pair *items = cbor_map_handle(item); + for (size_t i = 0; i < cbor_map_size(item); i++) { + map_size = _cbor_safe_signaling_add( + map_size, + _cbor_safe_signaling_add(cbor_serialized_size(items[i].key), + cbor_serialized_size(items[i].value))); + } + return map_size; } - bfr = tmp_bfr; + case CBOR_TYPE_TAG: { + return _cbor_safe_signaling_add( + _cbor_encoded_header_size(cbor_tag_value(item)), + cbor_serialized_size(cbor_move(cbor_tag_item(item)))); + } + case CBOR_TYPE_FLOAT_CTRL: + switch (cbor_float_get_width(item)) { + case CBOR_FLOAT_0: + return _cbor_encoded_header_size(cbor_ctrl_value(item)); + case CBOR_FLOAT_16: + return 3; + case CBOR_FLOAT_32: + return 5; + case CBOR_FLOAT_64: + return 9; + } + } +} + +size_t cbor_serialize_alloc(const cbor_item_t *item, unsigned char **buffer, + size_t *buffer_size) { + *buffer = NULL; + size_t serialized_size = cbor_serialized_size(item); + if (serialized_size == 0) { + if (buffer_size != NULL) *buffer_size = 0; + return 0; + } + *buffer = _cbor_malloc(serialized_size); + if (*buffer == NULL) { + if (buffer_size != NULL) *buffer_size = 0; + return 0; } - *buffer = bfr; - *buffer_size = bfr_size; + + size_t written = cbor_serialize(item, *buffer, serialized_size); + CBOR_ASSERT(written == serialized_size); + if (buffer_size != NULL) *buffer_size = serialized_size; return written; } size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_uint(item)); + CBOR_ASSERT(cbor_isa_uint(item)); + // cppcheck-suppress missingReturn switch (cbor_int_get_width(item)) { case CBOR_INT_8: return cbor_encode_uint8(cbor_get_uint8(item), buffer, buffer_size); @@ -83,14 +184,13 @@ size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, return cbor_encode_uint32(cbor_get_uint32(item), buffer, buffer_size); case CBOR_INT_64: return cbor_encode_uint64(cbor_get_uint64(item), buffer, buffer_size); - default: - return 0; } } size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_negint(item)); + CBOR_ASSERT(cbor_isa_negint(item)); + // cppcheck-suppress missingReturn switch (cbor_int_get_width(item)) { case CBOR_INT_8: return cbor_encode_negint8(cbor_get_uint8(item), buffer, buffer_size); @@ -100,173 +200,158 @@ size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, return cbor_encode_negint32(cbor_get_uint32(item), buffer, buffer_size); case CBOR_INT_64: return cbor_encode_negint64(cbor_get_uint64(item), buffer, buffer_size); - default: - return 0; } } size_t cbor_serialize_bytestring(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_isa_bytestring(item)); if (cbor_bytestring_is_definite(item)) { size_t length = cbor_bytestring_length(item); size_t written = cbor_encode_bytestring_start(length, buffer, buffer_size); - if (written && (buffer_size - written >= length)) { + if (written > 0 && (buffer_size - written >= length)) { memcpy(buffer + written, cbor_bytestring_handle(item), length); return written + length; - } else - return 0; + } + return 0; } else { - assert(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); size_t chunk_count = cbor_bytestring_chunk_count(item); size_t written = cbor_encode_indef_bytestring_start(buffer, buffer_size); - if (written == 0) return 0; cbor_item_t **chunks = cbor_bytestring_chunks_handle(item); for (size_t i = 0; i < chunk_count; i++) { size_t chunk_written = cbor_serialize_bytestring( chunks[i], buffer + written, buffer_size - written); - if (chunk_written == 0) - return 0; - else - written += chunk_written; + if (chunk_written == 0) return 0; + written += chunk_written; } - if (cbor_encode_break(buffer + written, buffer_size - written) > 0) - return written + 1; - else - return 0; + + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; } } size_t cbor_serialize_string(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_string(item)); + CBOR_ASSERT(cbor_isa_string(item)); if (cbor_string_is_definite(item)) { size_t length = cbor_string_length(item); size_t written = cbor_encode_string_start(length, buffer, buffer_size); if (written && (buffer_size - written >= length)) { memcpy(buffer + written, cbor_string_handle(item), length); return written + length; - } else - return 0; + } + return 0; } else { - assert(cbor_string_is_indefinite(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); size_t chunk_count = cbor_string_chunk_count(item); size_t written = cbor_encode_indef_string_start(buffer, buffer_size); - if (written == 0) return 0; cbor_item_t **chunks = cbor_string_chunks_handle(item); for (size_t i = 0; i < chunk_count; i++) { size_t chunk_written = cbor_serialize_string(chunks[i], buffer + written, buffer_size - written); - if (chunk_written == 0) - return 0; - else - written += chunk_written; + if (chunk_written == 0) return 0; + written += chunk_written; } - if (cbor_encode_break(buffer + written, buffer_size - written) > 0) - return written + 1; - else - return 0; + + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; } } size_t cbor_serialize_array(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_array(item)); + CBOR_ASSERT(cbor_isa_array(item)); size_t size = cbor_array_size(item), written = 0; cbor_item_t **handle = cbor_array_handle(item); if (cbor_array_is_definite(item)) { written = cbor_encode_array_start(size, buffer, buffer_size); } else { - assert(cbor_array_is_indefinite(item)); + CBOR_ASSERT(cbor_array_is_indefinite(item)); written = cbor_encode_indef_array_start(buffer, buffer_size); } if (written == 0) return 0; - size_t item_written; for (size_t i = 0; i < size; i++) { - item_written = + size_t item_written = cbor_serialize(*(handle++), buffer + written, buffer_size - written); - if (item_written == 0) - return 0; - else - written += item_written; + if (item_written == 0) return 0; + written += item_written; } if (cbor_array_is_definite(item)) { return written; } else { - assert(cbor_array_is_indefinite(item)); - item_written = cbor_encode_break(buffer + written, buffer_size - written); - if (item_written == 0) - return 0; - else - return written + 1; + CBOR_ASSERT(cbor_array_is_indefinite(item)); + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; } } size_t cbor_serialize_map(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_map(item)); + CBOR_ASSERT(cbor_isa_map(item)); size_t size = cbor_map_size(item), written = 0; struct cbor_pair *handle = cbor_map_handle(item); if (cbor_map_is_definite(item)) { written = cbor_encode_map_start(size, buffer, buffer_size); } else { - assert(cbor_map_is_indefinite(item)); + CBOR_ASSERT(cbor_map_is_indefinite(item)); written = cbor_encode_indef_map_start(buffer, buffer_size); } if (written == 0) return 0; - size_t item_written; for (size_t i = 0; i < size; i++) { - item_written = + size_t item_written = cbor_serialize(handle->key, buffer + written, buffer_size - written); - if (item_written == 0) + if (item_written == 0) { return 0; - else - written += item_written; + } + written += item_written; item_written = cbor_serialize((handle++)->value, buffer + written, buffer_size - written); - if (item_written == 0) - return 0; - else - written += item_written; + if (item_written == 0) return 0; + written += item_written; } if (cbor_map_is_definite(item)) { return written; } else { - assert(cbor_map_is_indefinite(item)); - item_written = cbor_encode_break(buffer + written, buffer_size - written); - if (item_written == 0) - return 0; - else - return written + 1; + CBOR_ASSERT(cbor_map_is_indefinite(item)); + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; } } size_t cbor_serialize_tag(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_tag(item)); + CBOR_ASSERT(cbor_isa_tag(item)); size_t written = cbor_encode_tag(cbor_tag_value(item), buffer, buffer_size); if (written == 0) return 0; - size_t item_written = cbor_serialize(cbor_tag_item(item), buffer + written, - buffer_size - written); - if (item_written == 0) - return 0; - else - return written + item_written; + size_t item_written = cbor_serialize(cbor_move(cbor_tag_item(item)), + buffer + written, buffer_size - written); + if (item_written == 0) return 0; + return written + item_written; } size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size) { - assert(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + // cppcheck-suppress missingReturn switch (cbor_float_get_width(item)) { case CBOR_FLOAT_0: /* CTRL - special treatment */ @@ -280,7 +365,4 @@ size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, return cbor_encode_double(cbor_float_get_float8(item), buffer, buffer_size); } - - /* Should never happen - make the compiler happy */ - return 0; } diff --git a/lib/libcbor/src/cbor/serialization.h b/lib/libcbor/src/cbor/serialization.h index ef68cf86aec..a4921f99fa3 100644 --- a/lib/libcbor/src/cbor/serialization.h +++ b/lib/libcbor/src/cbor/serialization.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_SERIALIZATION_H #define LIBCBOR_SERIALIZATION_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -27,23 +28,42 @@ extern "C" { * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize(const cbor_item_t *item, cbor_mutable_data buffer, - size_t buffer_size); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize(const cbor_item_t *item, + cbor_mutable_data buffer, + size_t buffer_size); + +/** Compute the length (in bytes) of the item when serialized using + * `cbor_serialize`. + * + * Time complexity is proportional to the number of nested items. + * + * @param item[borrow] A data item + * @return Length (>= 1) of the item when serialized. 0 if the length overflows + * `size_t`. + */ +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_serialized_size(const cbor_item_t *item); /** Serialize the given item, allocating buffers as needed + * + * Since libcbor v0.10, the return value is always the same as `buffer_size` (if + * provided, see https://github.com/PJK/libcbor/pull/251/). New clients should + * ignore the return value. * * \rst - * .. warning:: It is your responsibility to free the buffer using an - * appropriate ``free`` implementation. \endrst + * .. warning:: It is the caller's responsibility to free the buffer using an + * appropriate ``free`` implementation. + * \endrst * * @param item[borrow] A data item * @param buffer[out] Buffer containing the result - * @param buffer_size[out] Size of the \p buffer + * @param buffer_size[out] Size of the \p buffer, or ``NULL`` * @return Length of the result. 0 on failure, in which case \p buffer is * ``NULL``. */ -size_t cbor_serialize_alloc(const cbor_item_t *item, cbor_mutable_data *buffer, - size_t *buffer_size); +CBOR_EXPORT size_t cbor_serialize_alloc(const cbor_item_t *item, + cbor_mutable_data *buffer, + size_t *buffer_size); /** Serialize an uint * @@ -52,16 +72,20 @@ size_t cbor_serialize_alloc(const cbor_item_t *item, cbor_mutable_data *buffer, * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_uint(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_uint(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize a negint * - * @param item[borrow] A neging + * @param item[borrow] A negint * @param buffer Buffer to serialize to * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_negint(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_negint(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize a bytestring * @@ -70,8 +94,8 @@ size_t cbor_serialize_negint(const cbor_item_t *, cbor_mutable_data, size_t); * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_bytestring(const cbor_item_t *, cbor_mutable_data, - size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_serialize_bytestring(const cbor_item_t *, cbor_mutable_data, size_t); /** Serialize a string * @@ -80,7 +104,9 @@ size_t cbor_serialize_bytestring(const cbor_item_t *, cbor_mutable_data, * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_string(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_string(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize an array * @@ -89,7 +115,9 @@ size_t cbor_serialize_string(const cbor_item_t *, cbor_mutable_data, size_t); * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_array(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_array(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize a map * @@ -98,7 +126,9 @@ size_t cbor_serialize_array(const cbor_item_t *, cbor_mutable_data, size_t); * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_map(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_map(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize a tag * @@ -107,7 +137,9 @@ size_t cbor_serialize_map(const cbor_item_t *, cbor_mutable_data, size_t); * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_tag(const cbor_item_t *, cbor_mutable_data, size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_tag(const cbor_item_t *, + cbor_mutable_data, + size_t); /** Serialize a * @@ -116,8 +148,8 @@ size_t cbor_serialize_tag(const cbor_item_t *, cbor_mutable_data, size_t); * @param buffer_size Size of the \p buffer * @return Length of the result. 0 on failure. */ -size_t cbor_serialize_float_ctrl(const cbor_item_t *, cbor_mutable_data, - size_t); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_serialize_float_ctrl(const cbor_item_t *, cbor_mutable_data, size_t); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/streaming.c b/lib/libcbor/src/cbor/streaming.c index 9d85e15f8b8..922a71d8e6b 100644 --- a/lib/libcbor/src/cbor/streaming.c +++ b/lib/libcbor/src/cbor/streaming.c @@ -8,13 +8,12 @@ #include "streaming.h" #include "internal/loaders.h" -bool static _cbor_claim_bytes(size_t required, size_t provided, - struct cbor_decoder_result *result) { +static bool claim_bytes(size_t required, size_t provided, + struct cbor_decoder_result *result) { if (required > (provided - result->read)) { - /* We need to keep all the metadata if parsing is to be resumed */ + result->required = required + result->read; result->read = 0; result->status = CBOR_DECODER_NEDATA; - result->required = required; return false; } else { result->read += required; @@ -23,17 +22,33 @@ bool static _cbor_claim_bytes(size_t required, size_t provided, } } +// Use implicit capture as an exception to avoid the super long parameter list +#define CLAIM_BYTES_AND_INVOKE(callback_name, length, source_extra_offset) \ + do { \ + if (claim_bytes(length, source_size, &result)) { \ + callbacks->callback_name(context, source + 1 + source_extra_offset, \ + length); \ + } \ + } while (0) + +#define READ_CLAIM_INVOKE(callback_name, length_reader, length_bytes) \ + do { \ + if (claim_bytes(length_bytes, source_size, &result)) { \ + uint64_t length = length_reader(source + 1); \ + CLAIM_BYTES_AND_INVOKE(callback_name, length, length_bytes); \ + } \ + return result; \ + } while (0) + struct cbor_decoder_result cbor_stream_decode( cbor_data source, size_t source_size, const struct cbor_callbacks *callbacks, void *context) { - /* If we have no data, we cannot read even the MTB */ - if (source_size < 1) { - return (struct cbor_decoder_result){0, CBOR_DECODER_EBUFFER}; + // Attempt to claim the initial MTB byte + struct cbor_decoder_result result = {.status = CBOR_DECODER_FINISHED}; + if (!claim_bytes(1, source_size, &result)) { + return result; } - /* If we have a byte, assume it's the MTB */ - struct cbor_decoder_result result = {1, CBOR_DECODER_FINISHED}; - switch (*source) { case 0x00: /* Fallthrough */ case 0x01: /* Fallthrough */ @@ -67,7 +82,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x18: /* One byte unsigned integer */ { - if (_cbor_claim_bytes(1, source_size, &result)) { + if (claim_bytes(1, source_size, &result)) { callbacks->uint8(context, _cbor_load_uint8(source + 1)); } return result; @@ -75,7 +90,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x19: /* Two bytes unsigned integer */ { - if (_cbor_claim_bytes(2, source_size, &result)) { + if (claim_bytes(2, source_size, &result)) { callbacks->uint16(context, _cbor_load_uint16(source + 1)); } return result; @@ -83,7 +98,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x1A: /* Four bytes unsigned integer */ { - if (_cbor_claim_bytes(4, source_size, &result)) { + if (claim_bytes(4, source_size, &result)) { callbacks->uint32(context, _cbor_load_uint32(source + 1)); } return result; @@ -91,7 +106,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x1B: /* Eight bytes unsigned integer */ { - if (_cbor_claim_bytes(8, source_size, &result)) { + if (claim_bytes(8, source_size, &result)) { callbacks->uint64(context, _cbor_load_uint64(source + 1)); } return result; @@ -101,7 +116,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x1E: /* Fallthrough */ case 0x1F: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0x20: /* Fallthrough */ case 0x21: /* Fallthrough */ case 0x22: /* Fallthrough */ @@ -135,7 +150,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x38: /* One byte negative integer */ { - if (_cbor_claim_bytes(1, source_size, &result)) { + if (claim_bytes(1, source_size, &result)) { callbacks->negint8(context, _cbor_load_uint8(source + 1)); } return result; @@ -143,7 +158,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x39: /* Two bytes negative integer */ { - if (_cbor_claim_bytes(2, source_size, &result)) { + if (claim_bytes(2, source_size, &result)) { callbacks->negint16(context, _cbor_load_uint16(source + 1)); } return result; @@ -151,7 +166,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x3A: /* Four bytes negative integer */ { - if (_cbor_claim_bytes(4, source_size, &result)) { + if (claim_bytes(4, source_size, &result)) { callbacks->negint32(context, _cbor_load_uint32(source + 1)); } return result; @@ -159,7 +174,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x3B: /* Eight bytes negative integer */ { - if (_cbor_claim_bytes(8, source_size, &result)) { + if (claim_bytes(8, source_size, &result)) { callbacks->negint64(context, _cbor_load_uint64(source + 1)); } return result; @@ -169,7 +184,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x3E: /* Fallthrough */ case 0x3F: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0x40: /* Fallthrough */ case 0x41: /* Fallthrough */ case 0x42: /* Fallthrough */ @@ -196,63 +211,27 @@ struct cbor_decoder_result cbor_stream_decode( case 0x57: /* Embedded length byte string */ { - size_t length = - (size_t)_cbor_load_uint8(source) - 0x40; /* 0x40 offset */ - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->byte_string(context, source + 1, length); - } + uint64_t length = _cbor_load_uint8(source) - 0x40; /* 0x40 offset */ + CLAIM_BYTES_AND_INVOKE(byte_string, length, 0); return result; } case 0x58: /* One byte length byte string */ - // TODO template this? - { - if (_cbor_claim_bytes(1, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint8(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->byte_string(context, source + 1 + 1, length); - } - } - return result; - } + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint8, 1); case 0x59: /* Two bytes length byte string */ - { - if (_cbor_claim_bytes(2, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint16(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->byte_string(context, source + 1 + 2, length); - } - } - return result; - } + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint16, 2); case 0x5A: /* Four bytes length byte string */ - { - if (_cbor_claim_bytes(4, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint32(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->byte_string(context, source + 1 + 4, length); - } - } - return result; - } + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint32, 4); case 0x5B: /* Eight bytes length byte string */ - { - if (_cbor_claim_bytes(8, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint64(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->byte_string(context, source + 1 + 8, length); - } - } - return result; - } + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint64, 8); case 0x5C: /* Fallthrough */ case 0x5D: /* Fallthrough */ case 0x5E: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0x5F: /* Indefinite byte string */ { @@ -285,62 +264,27 @@ struct cbor_decoder_result cbor_stream_decode( case 0x77: /* Embedded one byte length string */ { - size_t length = - (size_t)_cbor_load_uint8(source) - 0x60; /* 0x60 offset */ - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->string(context, source + 1, length); - } + uint64_t length = _cbor_load_uint8(source) - 0x60; /* 0x60 offset */ + CLAIM_BYTES_AND_INVOKE(string, length, 0); return result; } case 0x78: /* One byte length string */ - { - if (_cbor_claim_bytes(1, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint8(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->string(context, source + 1 + 1, length); - } - } - return result; - } + READ_CLAIM_INVOKE(string, _cbor_load_uint8, 1); case 0x79: /* Two bytes length string */ - { - if (_cbor_claim_bytes(2, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint16(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->string(context, source + 1 + 2, length); - } - } - return result; - } + READ_CLAIM_INVOKE(string, _cbor_load_uint16, 2); case 0x7A: /* Four bytes length string */ - { - if (_cbor_claim_bytes(4, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint32(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->string(context, source + 1 + 4, length); - } - } - return result; - } + READ_CLAIM_INVOKE(string, _cbor_load_uint32, 4); case 0x7B: /* Eight bytes length string */ - { - if (_cbor_claim_bytes(8, source_size, &result)) { - size_t length = (size_t)_cbor_load_uint64(source + 1); - if (_cbor_claim_bytes(length, source_size, &result)) { - callbacks->string(context, source + 1 + 8, length); - } - } - return result; - } + READ_CLAIM_INVOKE(string, _cbor_load_uint64, 8); case 0x7C: /* Fallthrough */ case 0x7D: /* Fallthrough */ case 0x7E: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0x7F: /* Indefinite length string */ { @@ -374,41 +318,38 @@ struct cbor_decoder_result cbor_stream_decode( /* Embedded one byte length array */ { callbacks->array_start( - context, (size_t)_cbor_load_uint8(source) - 0x80); /* 0x40 offset */ + context, _cbor_load_uint8(source) - 0x80); /* 0x40 offset */ return result; } case 0x98: /* One byte length array */ { - if (_cbor_claim_bytes(1, source_size, &result)) { - callbacks->array_start(context, (size_t)_cbor_load_uint8(source + 1)); + if (claim_bytes(1, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint8(source + 1)); } return result; } case 0x99: /* Two bytes length array */ { - if (_cbor_claim_bytes(2, source_size, &result)) { - callbacks->array_start(context, - (size_t)_cbor_load_uint16(source + 1)); + if (claim_bytes(2, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint16(source + 1)); } return result; } case 0x9A: /* Four bytes length array */ { - if (_cbor_claim_bytes(4, source_size, &result)) { - callbacks->array_start(context, - (size_t)_cbor_load_uint32(source + 1)); + if (claim_bytes(4, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint32(source + 1)); } return result; } case 0x9B: /* Eight bytes length array */ { - if (_cbor_claim_bytes(8, source_size, &result)) { - callbacks->array_start(context, - (size_t)_cbor_load_uint64(source + 1)); + if (claim_bytes(8, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint64(source + 1)); } return result; } @@ -416,7 +357,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0x9D: /* Fallthrough */ case 0x9E: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0x9F: /* Indefinite length array */ { @@ -449,39 +390,39 @@ struct cbor_decoder_result cbor_stream_decode( case 0xB7: /* Embedded one byte length map */ { - callbacks->map_start( - context, (size_t)_cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */ + callbacks->map_start(context, + _cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */ return result; } case 0xB8: /* One byte length map */ { - if (_cbor_claim_bytes(1, source_size, &result)) { - callbacks->map_start(context, (size_t)_cbor_load_uint8(source + 1)); + if (claim_bytes(1, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint8(source + 1)); } return result; } case 0xB9: /* Two bytes length map */ { - if (_cbor_claim_bytes(2, source_size, &result)) { - callbacks->map_start(context, (size_t)_cbor_load_uint16(source + 1)); + if (claim_bytes(2, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint16(source + 1)); } return result; } case 0xBA: /* Four bytes length map */ { - if (_cbor_claim_bytes(4, source_size, &result)) { - callbacks->map_start(context, (size_t)_cbor_load_uint32(source + 1)); + if (claim_bytes(4, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint32(source + 1)); } return result; } case 0xBB: /* Eight bytes length map */ { - if (_cbor_claim_bytes(8, source_size, &result)) { - callbacks->map_start(context, (size_t)_cbor_load_uint64(source + 1)); + if (claim_bytes(8, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint64(source + 1)); } return result; } @@ -489,7 +430,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0xBD: /* Fallthrough */ case 0xBE: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xBF: /* Indefinite length map */ { @@ -509,8 +450,8 @@ struct cbor_decoder_result cbor_stream_decode( case 0xC5: /* Big float */ { - callbacks->tag(context, - _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */ + callbacks->tag(context, (uint64_t)(_cbor_load_uint8(source) - + 0xC0)); /* 0xC0 offset */ return result; } case 0xC6: /* Fallthrough */ @@ -529,40 +470,40 @@ struct cbor_decoder_result cbor_stream_decode( case 0xD3: /* Fallthrough */ case 0xD4: /* Unassigned tag value */ { - return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; + return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xD5: /* Expected b64url conversion tag - fallthrough */ case 0xD6: /* Expected b64 conversion tag - fallthrough */ case 0xD7: /* Expected b16 conversion tag */ { - callbacks->tag(context, - _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */ + callbacks->tag(context, (uint64_t)(_cbor_load_uint8(source) - + 0xC0)); /* 0xC0 offset */ return result; } case 0xD8: /* 1B tag */ { - if (_cbor_claim_bytes(1, source_size, &result)) { + if (claim_bytes(1, source_size, &result)) { callbacks->tag(context, _cbor_load_uint8(source + 1)); } return result; } case 0xD9: /* 2B tag */ { - if (_cbor_claim_bytes(2, source_size, &result)) { + if (claim_bytes(2, source_size, &result)) { callbacks->tag(context, _cbor_load_uint16(source + 1)); } return result; } case 0xDA: /* 4B tag */ { - if (_cbor_claim_bytes(4, source_size, &result)) { + if (claim_bytes(4, source_size, &result)) { callbacks->tag(context, _cbor_load_uint32(source + 1)); } return result; } case 0xDB: /* 8B tag */ { - if (_cbor_claim_bytes(8, source_size, &result)) { + if (claim_bytes(8, source_size, &result)) { callbacks->tag(context, _cbor_load_uint64(source + 1)); } return result; @@ -572,7 +513,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0xDE: /* Fallthrough */ case 0xDF: /* Reserved */ { - return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; + return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xE0: /* Fallthrough */ case 0xE1: /* Fallthrough */ @@ -595,7 +536,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0xF2: /* Fallthrough */ case 0xF3: /* Simple value - unassigned */ { - return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; + return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xF4: /* False */ @@ -623,11 +564,11 @@ struct cbor_decoder_result cbor_stream_decode( } case 0xF8: /* 1B simple value, unassigned */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xF9: /* 2B float */ { - if (_cbor_claim_bytes(2, source_size, &result)) { + if (claim_bytes(2, source_size, &result)) { callbacks->float2(context, _cbor_load_half(source + 1)); } return result; @@ -635,7 +576,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0xFA: /* 4B float */ { - if (_cbor_claim_bytes(4, source_size, &result)) { + if (claim_bytes(4, source_size, &result)) { callbacks->float4(context, _cbor_load_float(source + 1)); } return result; @@ -643,7 +584,7 @@ struct cbor_decoder_result cbor_stream_decode( case 0xFB: /* 8B float */ { - if (_cbor_claim_bytes(8, source_size, &result)) { + if (claim_bytes(8, source_size, &result)) { callbacks->float8(context, _cbor_load_double(source + 1)); } return result; @@ -652,16 +593,13 @@ struct cbor_decoder_result cbor_stream_decode( case 0xFD: /* Fallthrough */ case 0xFE: /* Reserved */ - { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; } + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } case 0xFF: /* Break */ - { - callbacks->indef_break(context); - return result; - } - default: /* Never happens - this shuts up the compiler */ - { + callbacks->indef_break(context); + // Never happens, the switch statement is exhaustive on the 1B range; make + // compiler happy + default: return result; - } } } diff --git a/lib/libcbor/src/cbor/streaming.h b/lib/libcbor/src/cbor/streaming.h index d9d54b8c8e3..cb908e17e9c 100644 --- a/lib/libcbor/src/cbor/streaming.h +++ b/lib/libcbor/src/cbor/streaming.h @@ -9,6 +9,7 @@ #define LIBCBOR_STREAMING_H #include "callbacks.h" +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -17,16 +18,16 @@ extern "C" { /** Stateless decoder * - * Will try parsing the \p buffer and will invoke the appropriate callback on + * Will try parsing the \p source and will invoke the appropriate callback on * success. Decodes one item at a time. No memory allocations occur. * - * @param buffer Input buffer - * @param buffer_size Length of the buffer + * @param source Input buffer + * @param source_size Length of the buffer * @param callbacks The callback bundle * @param context An arbitrary pointer to allow for maintaining context. */ -struct cbor_decoder_result cbor_stream_decode( - cbor_data buffer, size_t buffer_size, +_CBOR_NODISCARD CBOR_EXPORT struct cbor_decoder_result cbor_stream_decode( + cbor_data source, size_t source_size, const struct cbor_callbacks* callbacks, void* context); #ifdef __cplusplus diff --git a/lib/libcbor/src/cbor/strings.c b/lib/libcbor/src/cbor/strings.c index 209886b5f8c..de2d1024bb4 100644 --- a/lib/libcbor/src/cbor/strings.c +++ b/lib/libcbor/src/cbor/strings.c @@ -9,8 +9,8 @@ #include #include "internal/memory_utils.h" -cbor_item_t *cbor_new_definite_string() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_definite_string(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ .refcount = 1, @@ -19,15 +19,15 @@ cbor_item_t *cbor_new_definite_string() { return item; } -cbor_item_t *cbor_new_indefinite_string() { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); +cbor_item_t *cbor_new_indefinite_string(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ .refcount = 1, .type = CBOR_TYPE_STRING, .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}}, - .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))}; + .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))}; _CBOR_DEPENDENT_NOTNULL(item, item->data); *((struct cbor_indefinite_string_data *)item->data) = (struct cbor_indefinite_string_data){ @@ -42,7 +42,7 @@ cbor_item_t *cbor_build_string(const char *val) { cbor_item_t *item = cbor_new_definite_string(); _CBOR_NOTNULL(item); size_t len = strlen(val); - unsigned char *handle = _CBOR_MALLOC(len); + unsigned char *handle = _cbor_malloc(len); _CBOR_DEPENDENT_NOTNULL(item, handle); memcpy(handle, val, len); cbor_string_set_handle(item, handle, len); @@ -52,7 +52,7 @@ cbor_item_t *cbor_build_string(const char *val) { cbor_item_t *cbor_build_stringn(const char *val, size_t length) { cbor_item_t *item = cbor_new_definite_string(); _CBOR_NOTNULL(item); - unsigned char *handle = _CBOR_MALLOC(length); + unsigned char *handle = _cbor_malloc(length); _CBOR_DEPENDENT_NOTNULL(item, handle); memcpy(handle, val, length); cbor_string_set_handle(item, handle, length); @@ -62,31 +62,30 @@ cbor_item_t *cbor_build_stringn(const char *val, size_t length) { void cbor_string_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length) { - assert(cbor_isa_string(item)); - assert(cbor_string_is_definite(item)); + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_definite(item)); item->data = data; item->metadata.string_metadata.length = length; } cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) { - assert(cbor_isa_string(item)); - assert(cbor_string_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); return ((struct cbor_indefinite_string_data *)item->data)->chunks; } size_t cbor_string_chunk_count(const cbor_item_t *item) { - assert(cbor_isa_string(item)); - assert(cbor_string_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); return ((struct cbor_indefinite_string_data *)item->data)->chunk_count; } bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { - assert(cbor_isa_string(item)); - assert(cbor_string_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *)item->data; if (data->chunk_count == data->chunk_capacity) { - // TODO: Add a test for this if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { return false; } @@ -109,22 +108,22 @@ bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { } size_t cbor_string_length(const cbor_item_t *item) { - assert(cbor_isa_string(item)); + CBOR_ASSERT(cbor_isa_string(item)); return item->metadata.string_metadata.length; } unsigned char *cbor_string_handle(const cbor_item_t *item) { - assert(cbor_isa_string(item)); + CBOR_ASSERT(cbor_isa_string(item)); return item->data; } size_t cbor_string_codepoint_count(const cbor_item_t *item) { - assert(cbor_isa_string(item)); + CBOR_ASSERT(cbor_isa_string(item)); return item->metadata.string_metadata.codepoint_count; } bool cbor_string_is_definite(const cbor_item_t *item) { - assert(cbor_isa_string(item)); + CBOR_ASSERT(cbor_isa_string(item)); return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE; } diff --git a/lib/libcbor/src/cbor/strings.h b/lib/libcbor/src/cbor/strings.h index 342d0988fdd..b9899c4bba2 100644 --- a/lib/libcbor/src/cbor/strings.h +++ b/lib/libcbor/src/cbor/strings.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_STRINGS_H #define LIBCBOR_STRINGS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -20,14 +21,15 @@ extern "C" { * ============================================================================ */ -/** Returns the length of the underlying string +/** Returns the length of the underlying string in bytes * - * For definite strings only + * There can be fewer unicode character than bytes (see + * `cbor_string_codepoint_count`). For definite strings only. * * @param item[borrow] a definite string * @return length of the string. Zero if no chunk has been attached yet */ -size_t cbor_string_length(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_string_length(const cbor_item_t *item); /** The number of codepoints in this string * @@ -36,21 +38,24 @@ size_t cbor_string_length(const cbor_item_t *item); * @param item[borrow] A string * @return The number of codepoints in this string */ -size_t cbor_string_codepoint_count(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_string_codepoint_count(const cbor_item_t *item); /** Is the string definite? * * @param item[borrow] a string * @return Is the string definite? */ -bool cbor_string_is_definite(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_is_definite( + const cbor_item_t *item); /** Is the string indefinite? * * @param item[borrow] a string * @return Is the string indefinite? */ -bool cbor_string_is_indefinite(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_is_indefinite( + const cbor_item_t *item); /** Get the handle to the underlying string * @@ -61,24 +66,26 @@ bool cbor_string_is_indefinite(const cbor_item_t *item); * @return The address of the underlying string. `NULL` if no data have been * assigned yet. */ -cbor_mutable_data cbor_string_handle(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_mutable_data +cbor_string_handle(const cbor_item_t *item); /** Set the handle to the underlying string * * * \rst * .. warning:: Using a pointer to a stack allocated constant is a common - * mistake. Lifetime of the string will expire when it goes out of scope and the - * CBOR item will be left inconsistent. \endrst + * mistake. Lifetime of the string will expire when it goes out of scope and + * the CBOR item will be left inconsistent. + * \endrst * * @param item[borrow] A definite string * @param data The memory block. The caller gives up the ownership of the block. * libcbor will deallocate it when appropriate using its free function * @param length Length of the data block */ -void cbor_string_set_handle(cbor_item_t *item, - cbor_mutable_data CBOR_RESTRICT_POINTER data, - size_t length); +CBOR_EXPORT void cbor_string_set_handle( + cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length); /** Get the handle to the array of chunks * @@ -88,14 +95,16 @@ void cbor_string_set_handle(cbor_item_t *item, * @param item[borrow] A indefinite string * @return array of #cbor_string_chunk_count definite strings */ -cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t **cbor_string_chunks_handle( + const cbor_item_t *item); /** Get the number of chunks this string consist of * * @param item[borrow] A indefinite string * @return The chunk count. 0 for freshly created items. */ -size_t cbor_string_chunk_count(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_string_chunk_count(const cbor_item_t *item); /** Appends a chunk to the string * @@ -108,7 +117,8 @@ size_t cbor_string_chunk_count(const cbor_item_t *item); * @return true on success. false on realloc failure. In that case, the refcount * of `chunk` is not increased and the `item` is left intact. */ -bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk); +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_add_chunk(cbor_item_t *item, + cbor_item_t *chunk); /** Creates a new definite string * @@ -116,7 +126,7 @@ bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk); * * @return **new** definite string. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_definite_string(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_definite_string(void); /** Creates a new indefinite string * @@ -124,7 +134,7 @@ cbor_item_t *cbor_new_definite_string(); * * @return **new** indefinite string. `NULL` on malloc failure. */ -cbor_item_t *cbor_new_indefinite_string(); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_indefinite_string(void); /** Creates a new string and initializes it * @@ -133,7 +143,7 @@ cbor_item_t *cbor_new_indefinite_string(); * @param val A null-terminated UTF-8 string * @return A **new** string with content `handle`. `NULL` on malloc failure. */ -cbor_item_t *cbor_build_string(const char *val); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_string(const char *val); /** Creates a new string and initializes it * @@ -142,7 +152,8 @@ cbor_item_t *cbor_build_string(const char *val); * @param val A UTF-8 string, at least \p length long (excluding the null byte) * @return A **new** string with content `handle`. `NULL` on malloc failure. */ -cbor_item_t *cbor_build_stringn(const char *val, size_t length); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_stringn(const char *val, + size_t length); #ifdef __cplusplus } diff --git a/lib/libcbor/src/cbor/tags.c b/lib/libcbor/src/cbor/tags.c index 3853db4d4ae..3f3edb0b0e1 100644 --- a/lib/libcbor/src/cbor/tags.c +++ b/lib/libcbor/src/cbor/tags.c @@ -8,7 +8,7 @@ #include "tags.h" cbor_item_t *cbor_new_tag(uint64_t value) { - cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t)); + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ @@ -21,23 +21,26 @@ cbor_item_t *cbor_new_tag(uint64_t value) { } cbor_item_t *cbor_tag_item(const cbor_item_t *item) { - assert(cbor_isa_tag(item)); - return item->metadata.tag_metadata.tagged_item; + CBOR_ASSERT(cbor_isa_tag(item)); + return cbor_incref(item->metadata.tag_metadata.tagged_item); } uint64_t cbor_tag_value(const cbor_item_t *item) { - assert(cbor_isa_tag(item)); + CBOR_ASSERT(cbor_isa_tag(item)); return item->metadata.tag_metadata.value; } void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item) { - assert(cbor_isa_tag(item)); + CBOR_ASSERT(cbor_isa_tag(item)); cbor_incref(tagged_item); item->metadata.tag_metadata.tagged_item = tagged_item; } cbor_item_t *cbor_build_tag(uint64_t value, cbor_item_t *item) { cbor_item_t *res = cbor_new_tag(value); + if (res == NULL) { + return NULL; + } cbor_tag_set_item(res, item); return res; } diff --git a/lib/libcbor/src/cbor/tags.h b/lib/libcbor/src/cbor/tags.h index 6e76c8263d6..1fac44a54ee 100644 --- a/lib/libcbor/src/cbor/tags.h +++ b/lib/libcbor/src/cbor/tags.h @@ -8,6 +8,7 @@ #ifndef LIBCBOR_TAGS_H #define LIBCBOR_TAGS_H +#include "cbor/cbor_export.h" #include "cbor/common.h" #ifdef __cplusplus @@ -26,28 +27,28 @@ extern "C" { * @return **new** tag. Item reference is `NULL`. Returns `NULL` upon * memory allocation failure */ -cbor_item_t *cbor_new_tag(uint64_t value); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_tag(uint64_t value); /** Get the tagged item * * @param item[borrow] A tag * @return **incref** the tagged item */ -cbor_item_t *cbor_tag_item(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_tag_item(const cbor_item_t *item); /** Get tag value * * @param item[borrow] A tag * @return The tag value. Please consult the tag repository */ -uint64_t cbor_tag_value(const cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_tag_value(const cbor_item_t *item); /** Set the tagged item * * @param item[borrow] A tag * @param tagged_item[incref] The item to tag */ -void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item); +CBOR_EXPORT void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item); /** Build a new tag * @@ -55,7 +56,8 @@ void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item); * @param value Tag value * @return **new** tag item */ -cbor_item_t *cbor_build_tag(uint64_t value, cbor_item_t *item); +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_tag(uint64_t value, + cbor_item_t *item); #ifdef __cplusplus }