aboutsummaryrefslogtreecommitdiff
path: root/contrib/libcbor/test
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libcbor/test')
-rw-r--r--contrib/libcbor/test/CMakeLists.txt31
-rw-r--r--contrib/libcbor/test/array_encoders_test.c52
-rw-r--r--contrib/libcbor/test/array_test.c222
-rw-r--r--contrib/libcbor/test/assertions.c65
-rw-r--r--contrib/libcbor/test/assertions.h44
-rw-r--r--contrib/libcbor/test/bad_inputs_test.c116
-rw-r--r--contrib/libcbor/test/bytestring_encoders_test.c37
-rw-r--r--contrib/libcbor/test/bytestring_test.c381
-rw-r--r--contrib/libcbor/test/callbacks_test.c419
-rw-r--r--contrib/libcbor/test/cbor_serialize_test.c703
-rw-r--r--contrib/libcbor/test/cbor_stream_decode_test.c743
-rw-r--r--contrib/libcbor/test/copy_test.c475
-rw-r--r--contrib/libcbor/test/cpp_linkage_test.cpp11
-rw-r--r--contrib/libcbor/test/data/callbacks.cborbin0 -> 79 bytes
-rw-r--r--contrib/libcbor/test/data/callbacks.diag1
-rw-r--r--contrib/libcbor/test/data/pretty.cbor3
-rw-r--r--contrib/libcbor/test/data/pretty.diag1
-rw-r--r--contrib/libcbor/test/float_ctrl_encoders_test.c213
-rw-r--r--contrib/libcbor/test/float_ctrl_test.c139
-rw-r--r--contrib/libcbor/test/fuzz_test.c78
-rw-r--r--contrib/libcbor/test/map_encoders_test.c35
-rw-r--r--contrib/libcbor/test/map_test.c270
-rw-r--r--contrib/libcbor/test/memory_utils_test.c59
-rw-r--r--contrib/libcbor/test/negint_encoders_test.c72
-rw-r--r--contrib/libcbor/test/negint_test.c114
-rw-r--r--contrib/libcbor/test/pretty_printer_test.c205
-rw-r--r--contrib/libcbor/test/stack_over_limit_test.c28
-rw-r--r--contrib/libcbor/test/stream_expectations.c328
-rw-r--r--contrib/libcbor/test/stream_expectations.h152
-rw-r--r--contrib/libcbor/test/string_encoders_test.c36
-rw-r--r--contrib/libcbor/test/string_test.c361
-rw-r--r--contrib/libcbor/test/tag_encoders_test.c30
-rw-r--r--contrib/libcbor/test/tag_test.c165
-rw-r--r--contrib/libcbor/test/test_allocator.c89
-rw-r--r--contrib/libcbor/test/test_allocator.h35
-rw-r--r--contrib/libcbor/test/uint_encoders_test.c70
-rw-r--r--contrib/libcbor/test/uint_test.c159
-rw-r--r--contrib/libcbor/test/unicode_test.c42
38 files changed, 5984 insertions, 0 deletions
diff --git a/contrib/libcbor/test/CMakeLists.txt b/contrib/libcbor/test/CMakeLists.txt
new file mode 100644
index 000000000000..9721fd03a166
--- /dev/null
+++ b/contrib/libcbor/test/CMakeLists.txt
@@ -0,0 +1,31 @@
+file(GLOB TESTS "*_test.c")
+
+find_package(CMocka REQUIRED)
+
+message(STATUS "CMocka vars: ${CMOCKA_LIBRARIES} ${CMOCKA_INCLUDE_DIR}")
+
+find_library(MATH_LIBRARY m)
+
+CHECK_INCLUDE_FILE("execinfo.h" HAS_EXECINFO)
+
+foreach (TEST ${TESTS})
+ string(REGEX REPLACE ".*/([^/]+).c" "\\1" NAME ${TEST})
+ message("Adding test ${NAME}")
+ add_executable(${NAME} "${NAME}.c" assertions.c stream_expectations.c test_allocator.c)
+ target_link_libraries(${NAME} ${CMOCKA_LIBRARIES})
+ target_link_libraries(${NAME} cbor)
+ if(MATH_LIBRARY)
+ target_link_libraries(${NAME} ${MATH_LIBRARY})
+ endif()
+ target_include_directories(${NAME} PUBLIC ${CMOCKA_INCLUDE_DIR})
+ # See https://stackoverflow.com/a/10824578/499521
+ ADD_TEST(ctest_build_test_${NAME}
+ "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${NAME})
+ ADD_TEST(ctest_run_${NAME} ${NAME})
+ SET_TESTS_PROPERTIES(ctest_run_${NAME}
+ PROPERTIES DEPENDS ctest_build_test_${NAME})
+ add_dependencies(coverage ${NAME})
+endforeach (TEST)
+
+add_executable(cpp_linkage_test cpp_linkage_test.cpp)
+target_link_libraries(cpp_linkage_test cbor) \ No newline at end of file
diff --git a/contrib/libcbor/test/array_encoders_test.c b/contrib/libcbor/test/array_encoders_test.c
new file mode 100644
index 000000000000..54a28bd94c6b
--- /dev/null
+++ b/contrib/libcbor/test/array_encoders_test.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_array_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_array_start(1, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x81}), 1);
+}
+
+static void test_array_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_array_start(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x9A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_indef_array_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_indef_array_start(buffer, 512));
+ assert_size_equal(0, cbor_encode_indef_array_start(buffer, 0));
+ assert_memory_equal(buffer, ((unsigned char[]){0x9F}), 1);
+}
+
+static void test_indef_array_encoding(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *array = cbor_new_indefinite_array();
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+ assert_true(cbor_array_push(array, one));
+ assert_true(cbor_array_push(array, two));
+
+ assert_size_equal(4, cbor_serialize_array(array, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x9F, 0x01, 0x02, 0xFF}), 4);
+
+ cbor_decref(&array);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_embedded_array_start),
+ cmocka_unit_test(test_array_start),
+ cmocka_unit_test(test_indef_array_start),
+ cmocka_unit_test(test_indef_array_encoding)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/array_test.c b/contrib/libcbor/test/array_test.c
new file mode 100644
index 000000000000..1a241c051f2c
--- /dev/null
+++ b/contrib/libcbor/test/array_test.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *arr;
+struct cbor_load_result res;
+
+unsigned char data1[] = {0x80, 0xFF};
+
+static void test_empty_array(void **_CBOR_UNUSED(_state)) {
+ arr = cbor_load(data1, 2, &res);
+ assert_non_null(arr);
+ assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
+ assert_true(cbor_isa_array(arr));
+ assert_true(cbor_array_size(arr) == 0);
+ assert_true(res.read == 1);
+ cbor_decref(&arr);
+ assert_null(arr);
+}
+
+unsigned char data2[] = {0x81, 0x01, 0xFF};
+
+static void test_simple_array(void **_CBOR_UNUSED(_state)) {
+ arr = cbor_load(data2, 3, &res);
+ assert_non_null(arr);
+ assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
+ assert_true(cbor_isa_array(arr));
+ assert_size_equal(cbor_array_size(arr), 1);
+ assert_true(res.read == 2);
+ assert_size_equal(cbor_array_allocated(arr), 1);
+ /* Check the values */
+ assert_uint8(cbor_array_handle(arr)[0], 1);
+ cbor_item_t *intermediate = cbor_array_get(arr, 0);
+ assert_uint8(intermediate, 1);
+
+ cbor_item_t *new_val = cbor_build_uint8(10);
+ assert_false(cbor_array_set(arr, 1, new_val));
+ assert_false(cbor_array_set(arr, 3, new_val));
+ cbor_decref(&new_val);
+
+ cbor_decref(&arr);
+ cbor_decref(&intermediate);
+ assert_null(arr);
+ assert_null(intermediate);
+}
+
+unsigned char data3[] = {0x82, 0x01, 0x81, 0x01, 0xFF};
+
+static void test_nested_arrays(void **_CBOR_UNUSED(_state)) {
+ arr = cbor_load(data3, 5, &res);
+ assert_non_null(arr);
+ assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
+ assert_true(cbor_isa_array(arr));
+ assert_true(cbor_array_size(arr) == 2);
+ assert_true(res.read == 4);
+ /* Check the values */
+ assert_uint8(cbor_array_handle(arr)[0], 1);
+
+ cbor_item_t *nested = cbor_array_handle(arr)[1];
+ assert_true(cbor_isa_array(nested));
+ assert_true(cbor_array_size(nested) == 1);
+ assert_uint8(cbor_array_handle(nested)[0], 1);
+
+ cbor_decref(&arr);
+ assert_null(arr);
+}
+
+unsigned char test_indef_arrays_data[] = {0x9f, 0x01, 0x02, 0xFF};
+
+static void test_indef_arrays(void **_CBOR_UNUSED(_state)) {
+ arr = cbor_load(test_indef_arrays_data, 4, &res);
+ assert_non_null(arr);
+ assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
+ assert_true(cbor_isa_array(arr));
+ assert_true(cbor_array_size(arr) == 2);
+ assert_true(res.read == 4);
+ /* Check the values */
+ assert_uint8(cbor_array_handle(arr)[0], 1);
+ assert_uint8(cbor_array_handle(arr)[1], 2);
+
+ assert_true(cbor_array_set(arr, 1, cbor_move(cbor_build_uint8(10))));
+
+ cbor_decref(&arr);
+ assert_null(arr);
+}
+
+unsigned char test_nested_indef_arrays_data[] = {0x9f, 0x01, 0x9f, 0x02,
+ 0xFF, 0x03, 0xFF};
+
+static void test_nested_indef_arrays(void **_CBOR_UNUSED(_state)) {
+ arr = cbor_load(test_nested_indef_arrays_data, 7, &res);
+ assert_non_null(arr);
+ assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
+ assert_true(cbor_isa_array(arr));
+ assert_size_equal(cbor_array_size(arr), 3);
+ assert_true(res.read == 7);
+ /* Check the values */
+ assert_uint8(cbor_array_handle(arr)[0], 1);
+
+ cbor_item_t *nested = cbor_array_handle(arr)[1];
+ assert_true(cbor_isa_array(nested));
+ assert_true(cbor_array_size(nested) == 1);
+ assert_uint8(cbor_array_handle(nested)[0], 2);
+
+ cbor_decref(&arr);
+ assert_null(arr);
+}
+
+static void test_array_replace(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *array = cbor_new_definite_array(2);
+ assert_size_equal(cbor_array_size(array), 0);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *three = cbor_build_uint8(3);
+ assert_size_equal(cbor_refcount(one), 1);
+ assert_size_equal(cbor_refcount(three), 1);
+
+ // No item to replace
+ assert_false(cbor_array_replace(array, 0, three));
+ assert_size_equal(cbor_refcount(three), 1);
+
+ // Add items [1, 2]
+ assert_true(cbor_array_push(array, one));
+ assert_true(cbor_array_push(array, cbor_move(cbor_build_uint8(2))));
+ assert_size_equal(cbor_refcount(one), 2);
+ assert_size_equal(cbor_array_size(array), 2);
+
+ // Array has only two items
+ assert_false(cbor_array_replace(array, 2, three));
+ assert_size_equal(cbor_refcount(three), 1);
+
+ // Change [1, 2] to [3, 2]
+ assert_true(cbor_array_replace(array, 0, three));
+ assert_size_equal(cbor_refcount(one), 1);
+ assert_size_equal(cbor_refcount(three), 2);
+ assert_uint8(cbor_move(cbor_array_get(array, 0)), 3);
+ assert_uint8(cbor_move(cbor_array_get(array, 1)), 2);
+
+ cbor_decref(&one);
+ cbor_decref(&three);
+ cbor_decref(&array);
+}
+
+static void test_array_push_overflow(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *array = cbor_new_indefinite_array();
+ cbor_item_t *one = cbor_build_uint8(1);
+ struct _cbor_array_metadata *metadata =
+ (struct _cbor_array_metadata *)&array->metadata;
+ // Pretend we already have a huge block allocated
+ metadata->allocated = SIZE_MAX;
+ metadata->end_ptr = SIZE_MAX;
+
+ assert_false(cbor_array_push(array, one));
+ assert_size_equal(cbor_refcount(one), 1);
+
+ cbor_decref(&one);
+ metadata->allocated = 0;
+ metadata->end_ptr = 0;
+ cbor_decref(&array);
+}
+
+static void test_array_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_array(42)); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_array(42)); }, 2, MALLOC,
+ MALLOC_FAIL);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_array()); });
+}
+
+static void test_array_push(void **_CBOR_UNUSED(_state)) {
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *array = cbor_new_indefinite_array();
+ cbor_item_t *string = cbor_build_string("Hello!");
+
+ assert_false(cbor_array_push(array, string));
+ assert_size_equal(cbor_array_allocated(array), 0);
+ assert_null(array->data);
+ assert_size_equal(array->metadata.array_metadata.end_ptr, 0);
+
+ cbor_decref(&string);
+ cbor_decref(&array);
+ },
+ 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+static unsigned char simple_indef_array[] = {0x9F, 0x01, 0x02, 0xFF};
+static void test_indef_array_decode(void **_CBOR_UNUSED(_state)) {
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *array;
+ struct cbor_load_result res;
+ array = cbor_load(simple_indef_array, 4, &res);
+
+ assert_null(array);
+ assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
+ },
+ 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_empty_array),
+ cmocka_unit_test(test_simple_array),
+ cmocka_unit_test(test_nested_arrays),
+ cmocka_unit_test(test_indef_arrays),
+ cmocka_unit_test(test_nested_indef_arrays),
+ cmocka_unit_test(test_array_replace),
+ cmocka_unit_test(test_array_push_overflow),
+ cmocka_unit_test(test_array_creation),
+ cmocka_unit_test(test_array_push),
+ cmocka_unit_test(test_indef_array_decode),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/assertions.c b/contrib/libcbor/test/assertions.c
new file mode 100644
index 000000000000..197e829d489d
--- /dev/null
+++ b/contrib/libcbor/test/assertions.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "stream_expectations.h"
+
+void assert_uint8(cbor_item_t* item, uint8_t num) {
+ assert_true(cbor_isa_uint(item));
+ assert_true(cbor_int_get_width(item) == CBOR_INT_8);
+ assert_true(cbor_get_uint8(item) == num);
+}
+
+void assert_uint16(cbor_item_t* item, uint16_t num) {
+ assert_true(cbor_isa_uint(item));
+ assert_true(cbor_int_get_width(item) == CBOR_INT_16);
+ assert_true(cbor_get_uint16(item) == num);
+}
+
+void assert_uint32(cbor_item_t* item, uint32_t num) {
+ assert_true(cbor_isa_uint(item));
+ assert_true(cbor_int_get_width(item) == CBOR_INT_32);
+ assert_true(cbor_get_uint32(item) == num);
+}
+
+void assert_uint64(cbor_item_t* item, uint64_t num) {
+ assert_true(cbor_isa_uint(item));
+ assert_true(cbor_int_get_width(item) == CBOR_INT_64);
+ assert_true(cbor_get_uint64(item) == num);
+}
+
+void assert_decoder_result(size_t expected_bytes_read,
+ enum cbor_decoder_status expected_status,
+ struct cbor_decoder_result actual_result) {
+ assert_true(actual_result.read == expected_bytes_read);
+ assert_true(actual_result.status == expected_status);
+ assert_true(actual_result.required == 0);
+}
+
+void assert_decoder_result_nedata(size_t expected_bytes_required,
+ struct cbor_decoder_result actual_result) {
+ assert_true(actual_result.read == 0);
+ assert_true(actual_result.status == CBOR_DECODER_NEDATA);
+ assert_true(actual_result.required == expected_bytes_required);
+}
+
+void assert_minimum_input_size(size_t expected, cbor_data data) {
+ for (size_t available = 1; available < expected; available++) {
+ assert_decoder_result_nedata(expected, decode(data, 1));
+ }
+}
+
+void _assert_size_equal(size_t actual, size_t expected, const char* src_file,
+ int src_line) {
+ if (actual == expected) return;
+ // Not using `fail_msg` since it mishandles variadic macro arguments, which
+ // causes compiler warnings/
+ // TODO file bug
+ printf("(%s:%d) assert_size_equal: Expected %zu to equal %zu\n", src_file,
+ src_line, actual, expected);
+ fail();
+}
diff --git a/contrib/libcbor/test/assertions.h b/contrib/libcbor/test/assertions.h
new file mode 100644
index 000000000000..13e8d6f12137
--- /dev/null
+++ b/contrib/libcbor/test/assertions.h
@@ -0,0 +1,44 @@
+// Headers needed by cmocka -- must be imported first
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cmocka.h>
+
+#include "cbor.h"
+
+#ifndef ASSERTIONS_H_
+#define ASSERTIONS_H_
+
+void assert_uint8(cbor_item_t* item, uint8_t num);
+void assert_uint16(cbor_item_t* item, uint16_t num);
+void assert_uint32(cbor_item_t* item, uint32_t num);
+void assert_uint64(cbor_item_t* item, uint64_t num);
+
+// TODO: Fix "Yoda" parameter ordering of asserts
+/** Verify the `actual_result.status` and `actual_result.status`. */
+void assert_decoder_result(size_t expected_bytes_read,
+ enum cbor_decoder_status expected_status,
+ struct cbor_decoder_result actual_result);
+
+/**
+ * Assert that the result is set to CBOR_DECODER_NEDATA with the given
+ * `cbor_decoder_result.required` value.
+ */
+void assert_decoder_result_nedata(size_t expected_bytes_required,
+ struct cbor_decoder_result actual_result);
+
+/**
+ * Check that the streaming decoder returns a correct CBOR_DECODER_NEDATA
+ * result for all inputs from data[0..1] through data[0..(expected-1)].
+ */
+void assert_minimum_input_size(size_t expected, cbor_data data);
+
+/** Check the equality of two `size_t`s. */
+void _assert_size_equal(size_t actual, size_t expected, const char* src_file,
+ int src_line);
+#define assert_size_equal(actual, expected) \
+ _assert_size_equal(actual, expected, __FILE__, __LINE__)
+
+#endif
diff --git a/contrib/libcbor/test/bad_inputs_test.c b/contrib/libcbor/test/bad_inputs_test.c
new file mode 100644
index 000000000000..de7bdab95231
--- /dev/null
+++ b/contrib/libcbor/test/bad_inputs_test.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+/* These tests verify behavior on interesting randomly generated inputs from the
+ * fuzzer */
+
+cbor_item_t *item;
+struct cbor_load_result res;
+
+/* Map start + array with embedded length */
+unsigned char data1[] = {0xA9, 0x85};
+static void test_1(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data1, 2, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_NOTENOUGHDATA);
+ assert_size_equal(res.error.position, 2);
+}
+
+unsigned char data2[] = {0x9D};
+static void test_2(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data2, 1, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_MALFORMATED);
+ assert_size_equal(res.error.position, 0);
+}
+
+unsigned char data3[] = {0xD6};
+static void test_3(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data3, 1, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_NOTENOUGHDATA);
+ assert_size_equal(res.error.position, 1);
+}
+
+#ifdef SANE_MALLOC
+unsigned char data4[] = {0xBA, 0xC1, 0xE8, 0x3E, 0xE7, 0x20, 0xA8};
+static void test_4(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data4, 7, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_MEMERROR);
+ assert_size_equal(res.error.position, 5);
+}
+
+unsigned char data5[] = {0x9A, 0xDA, 0x3A, 0xB2, 0x7F, 0x29};
+static void test_5(void **_CBOR_UNUSED(_state)) {
+ assert_true(res.error.code == CBOR_ERR_MEMERROR);
+ item = cbor_load(data5, 6, &res);
+ assert_null(item);
+ assert_size_equal(res.error.position, 5);
+ /* Indef string expectation mismatch */
+}
+#endif
+
+unsigned char data6[] = {0x7F, 0x21, 0x4C, 0x02, 0x40};
+static void test_6(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data6, 5, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
+ assert_size_equal(res.error.position, 2);
+}
+
+#ifdef EIGHT_BYTE_SIZE_T
+/* Extremely high size value (overflows size_t in representation size). Only
+ * works with 64b sizes */
+unsigned char data7[] = {0xA2, 0x9B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static void test_7(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data7, 16, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_MEMERROR);
+ assert_size_equal(res.error.position, 10);
+}
+#endif
+
+unsigned char data8[] = {0xA3, 0x64, 0x68, 0x61, 0x6C, 0x66, 0xFF, 0x00,
+ 0x00, 0x66, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65,
+ 0xFA, 0x7F, 0x7F, 0xFF, 0xFF, 0x6D, 0x73, 0x69,
+ 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x76, 0x61, 0x6C,
+ 0x75, 0x65, 0x73, 0x83, 0xF5, 0xF4, 0xF6};
+static void test_8(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data8, 39, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
+ assert_size_equal(res.error.position, 7);
+}
+
+unsigned char data9[] = {0xBF, 0x05, 0xFF, 0x00, 0x00, 0x00, 0x10, 0x04};
+static void test_9(void **_CBOR_UNUSED(_state)) {
+ item = cbor_load(data9, 8, &res);
+ assert_null(item);
+ assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
+ assert_size_equal(res.error.position, 3);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_1), cmocka_unit_test(test_2),
+ cmocka_unit_test(test_3),
+#ifdef SANE_MALLOC
+ cmocka_unit_test(test_4), cmocka_unit_test(test_5),
+#endif
+ cmocka_unit_test(test_6),
+#ifdef EIGHT_BYTE_SIZE_T
+ cmocka_unit_test(test_7),
+#endif
+ cmocka_unit_test(test_8), cmocka_unit_test(test_9),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/bytestring_encoders_test.c b/contrib/libcbor/test/bytestring_encoders_test.c
new file mode 100644
index 000000000000..8e2fbe694055
--- /dev/null
+++ b/contrib/libcbor/test/bytestring_encoders_test.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_bytestring_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_bytestring_start(1, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x41}), 1);
+}
+
+static void test_bytestring_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_bytestring_start(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x5A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_indef_bytestring_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_indef_bytestring_start(buffer, 0));
+ assert_size_equal(1, cbor_encode_indef_bytestring_start(buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x5F}), 1);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_embedded_bytestring_start),
+ cmocka_unit_test(test_bytestring_start),
+ cmocka_unit_test(test_indef_bytestring_start)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/bytestring_test.c b/contrib/libcbor/test/bytestring_test.c
new file mode 100644
index 000000000000..08968a13e98e
--- /dev/null
+++ b/contrib/libcbor/test/bytestring_test.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *bs;
+struct cbor_load_result res;
+
+unsigned char data1[] = {0x40, 0xFF};
+unsigned char data2[] = {0x41, 0xA1};
+unsigned char data3[] = {0x58, 0x01, 0xA1, 0xFF};
+unsigned char data4[] = {
+ 0x58, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21,
+ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
+ 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D,
+ 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
+ 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81,
+ 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D,
+ 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5,
+ 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1,
+ 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
+ 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
+ 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5,
+ 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1,
+ 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
+ 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
+unsigned char data5[] = {
+ 0x59, 0x00, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
+ 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
+ 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80,
+ 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4,
+ 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0,
+ 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC,
+ 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+ 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
+ 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0,
+ 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC,
+ 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
+unsigned char data6[] = {
+ 0x5A, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42,
+ 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E,
+ 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
+ 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E,
+ 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A,
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2,
+ 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE,
+ 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
+ 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6,
+ 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2,
+ 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE,
+ 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
+ 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
+ 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
+unsigned char data7[] = {
+ 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x01, 0x02,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
+ 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E,
+ 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
+ 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+ 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
+ 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E,
+ 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
+ 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
+ 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2,
+ 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
+ 0xFF};
+unsigned char data8[] = {
+ 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xFF, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+ 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,
+ 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61,
+ 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D,
+ 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85,
+ 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91,
+ 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
+ 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
+ 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5,
+ 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1,
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+ 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5,
+ 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1,
+ 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
+ 0xFE, 0xFF};
+
+static void test_empty_bs(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data1, 2, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_size_equal(cbor_bytestring_length(bs), 0);
+ assert_true(res.read == 1);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_embedded_bs(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data2, 2, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 1);
+ assert_true(res.read == 2);
+ assert_true(*cbor_bytestring_handle(bs) == 0xA1);
+ assert_memory_equal(cbor_bytestring_handle(bs), data2 + 1, 1);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_notenough_data(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data3, 2, &res);
+ assert_null(bs);
+ assert_true(res.error.code == CBOR_ERR_NOTENOUGHDATA);
+}
+
+static void test_short_bs1(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data3, 4, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 1);
+ assert_true(res.read == 3);
+ assert_true(*cbor_bytestring_handle(bs) == 0xA1);
+ assert_memory_equal(cbor_bytestring_handle(bs), data3 + 2, 1);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_short_bs2(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data4, 259, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 255);
+ assert_true(res.read == 257);
+ assert_memory_equal(cbor_bytestring_handle(bs), data4 + 2, 0xFF);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_half_bs(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data5, 259, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 255);
+ assert_true(res.read == 258);
+ assert_memory_equal(cbor_bytestring_handle(bs), data5 + 3, 0xFF);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_int_bs(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data6, 261, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 255);
+ assert_true(res.read == 260);
+ assert_memory_equal(cbor_bytestring_handle(bs), data6 + 5, 0xFF);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+static void test_long_bs(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data7, 265, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 255);
+ assert_true(res.read == 264);
+ assert_memory_equal(cbor_bytestring_handle(bs), data7 + 9, 0xFF);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+unsigned char data9[] = {0x5F, 0xFF};
+
+static void test_zero_indef(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data9, 2, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_is_indefinite(bs));
+ assert_true(cbor_bytestring_chunk_count(bs) == 0);
+ assert_true(res.read == 2);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+unsigned char data10[] = {0x5F, 0x58, 0x01, 0xA1, 0xFF, 0xFF};
+
+/* start | bstring | break| extra */
+
+static void test_short_indef(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data10, 6, &res);
+ assert_non_null(bs);
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 0);
+ assert_true(cbor_bytestring_is_indefinite(bs));
+ assert_true(cbor_bytestring_chunk_count(bs) == 1);
+ assert_true(res.read == 5);
+ assert_true(cbor_isa_bytestring(cbor_bytestring_chunks_handle(bs)[0]));
+ assert_true(cbor_bytestring_length(cbor_bytestring_chunks_handle(bs)[0]) ==
+ 1);
+ assert_true(*cbor_bytestring_handle(cbor_bytestring_chunks_handle(bs)[0]) ==
+ 0xA1);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+unsigned char data11[] = {0x5F, 0x58, 0x01, 0xA1, 0x58, 0x01, 0xA2, 0xFF, 0xFF};
+
+/* start | bstring | bstring | break|
+ * extra */
+
+static void test_two_indef(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data11, 9, &res);
+ assert_non_null(bs);
+ assert_size_equal(1, cbor_refcount(bs));
+ assert_true(cbor_typeof(bs) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bs));
+ assert_true(cbor_bytestring_length(bs) == 0);
+ assert_true(cbor_bytestring_is_indefinite(bs));
+ assert_true(cbor_bytestring_chunk_count(bs) == 2);
+ assert_true(res.read == 8);
+ assert_true(cbor_isa_bytestring(cbor_bytestring_chunks_handle(bs)[0]));
+ assert_true(cbor_bytestring_length(cbor_bytestring_chunks_handle(bs)[0]) ==
+ 1);
+ assert_true(*cbor_bytestring_handle(cbor_bytestring_chunks_handle(bs)[0]) ==
+ 0xA1);
+ assert_true(cbor_isa_bytestring(cbor_bytestring_chunks_handle(bs)[1]));
+ assert_true(cbor_bytestring_length(cbor_bytestring_chunks_handle(bs)[1]) ==
+ 1);
+ assert_true(*cbor_bytestring_handle(cbor_bytestring_chunks_handle(bs)[1]) ==
+ 0xA2);
+ cbor_decref(&bs);
+ assert_null(bs);
+}
+
+unsigned char data12[] = {0x5F, 0x58, 0x01};
+
+/* start | bstring - too short */
+
+static void test_missing_indef(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_load(data12, 3, &res);
+ assert_true(res.error.code == CBOR_ERR_NOTENOUGHDATA);
+ assert_null(bs);
+}
+
+static void test_inline_creation(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_build_bytestring((cbor_data) "Hello!", 6);
+ assert_memory_equal(cbor_bytestring_handle(bs), "Hello!", 6);
+ cbor_decref(&bs);
+}
+
+static void test_add_chunk_reallocation_overflow(void **_CBOR_UNUSED(_state)) {
+ bs = cbor_new_indefinite_bytestring();
+ cbor_item_t *chunk = cbor_build_bytestring((cbor_data) "Hello!", 6);
+ struct cbor_indefinite_string_data *metadata =
+ (struct cbor_indefinite_string_data *)bs->data;
+ // Pretend we already have many chunks allocated
+ metadata->chunk_count = SIZE_MAX;
+ metadata->chunk_capacity = SIZE_MAX;
+
+ assert_false(cbor_bytestring_add_chunk(bs, chunk));
+ assert_size_equal(cbor_refcount(chunk), 1);
+
+ metadata->chunk_count = 0;
+ metadata->chunk_capacity = 0;
+ cbor_decref(&chunk);
+ cbor_decref(&bs);
+}
+
+static void test_bytestring_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_bytestring()); });
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_bytestring()); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_new_indefinite_bytestring()); }, 2,
+ MALLOC, MALLOC_FAIL);
+
+ unsigned char bytes[] = {0, 0, 0xFF, 0xAB};
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_bytestring(bytes, 4)); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_build_bytestring(bytes, 4)); }, 2, MALLOC,
+ MALLOC_FAIL);
+}
+
+static void test_bytestring_add_chunk(void **_CBOR_UNUSED(_state)) {
+ unsigned char bytes[] = {0, 0, 0xFF, 0xAB};
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *bytestring = cbor_new_indefinite_bytestring();
+ cbor_item_t *chunk = cbor_build_bytestring(bytes, 4);
+
+ assert_false(cbor_bytestring_add_chunk(bytestring, chunk));
+
+ assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
+ assert_size_equal(
+ ((struct cbor_indefinite_string_data *)bytestring->data)
+ ->chunk_capacity,
+ 0);
+
+ cbor_decref(&chunk);
+ cbor_decref(&bytestring);
+ },
+ 5, MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_empty_bs),
+ cmocka_unit_test(test_embedded_bs),
+ cmocka_unit_test(test_notenough_data),
+ cmocka_unit_test(test_short_bs1),
+ cmocka_unit_test(test_short_bs2),
+ cmocka_unit_test(test_half_bs),
+ cmocka_unit_test(test_int_bs),
+ cmocka_unit_test(test_long_bs),
+ cmocka_unit_test(test_zero_indef),
+ cmocka_unit_test(test_short_indef),
+ cmocka_unit_test(test_two_indef),
+ cmocka_unit_test(test_missing_indef),
+ cmocka_unit_test(test_inline_creation),
+ cmocka_unit_test(test_add_chunk_reallocation_overflow),
+ cmocka_unit_test(test_bytestring_creation),
+ cmocka_unit_test(test_bytestring_add_chunk),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/callbacks_test.c b/contrib/libcbor/test/callbacks_test.c
new file mode 100644
index 000000000000..65c5d37f4399
--- /dev/null
+++ b/contrib/libcbor/test/callbacks_test.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+#include "assertions.h"
+#include "cbor.h"
+#include "cbor/internal/builder_callbacks.h"
+#include "cbor/internal/stack.h"
+#include "test_allocator.h"
+
+unsigned char data[] = {
+ 0x93, 0x01, 0x19, 0x01, 0x01, 0x1A, 0x00, 0x01, 0x05, 0xB8, 0x1B, 0x00,
+ 0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8, 0xB8, 0x20, 0x39, 0x01, 0x00, 0x3A,
+ 0x00, 0x01, 0x05, 0xB7, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8,
+ 0xB7, 0x5F, 0x41, 0x01, 0x41, 0x02, 0xFF, 0x7F, 0x61, 0x61, 0x61, 0x62,
+ 0xFF, 0x9F, 0xFF, 0xA1, 0x61, 0x61, 0x61, 0x62, 0xC0, 0xBF, 0xFF, 0xF9,
+ 0x3C, 0x00, 0xFA, 0x47, 0xC3, 0x50, 0x00, 0xFB, 0x7E, 0x37, 0xE4, 0x3C,
+ 0x88, 0x00, 0x75, 0x9C, 0xF6, 0xF7, 0xF5};
+
+/* Exercise the default callbacks */
+static void test_default_callbacks(void** _CBOR_UNUSED(_state)) {
+ size_t read = 0;
+ while (read < 79) {
+ struct cbor_decoder_result result =
+ cbor_stream_decode(data + read, 79 - read, &cbor_empty_callbacks, NULL);
+ read += result.read;
+ }
+}
+
+unsigned char bytestring_data[] = {0x01, 0x02, 0x03};
+static void test_builder_byte_string_callback_append(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(
+ _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ cbor_builder_byte_string_callback(&context, bytestring_data, 3);
+
+ assert_false(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ cbor_item_t* bytestring = stack.top->item;
+ assert_size_equal(cbor_refcount(bytestring), 1);
+ assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bytestring));
+ assert_size_equal(cbor_bytestring_length(bytestring), 0);
+ assert_true(cbor_bytestring_is_indefinite(bytestring));
+ assert_size_equal(cbor_bytestring_chunk_count(bytestring), 1);
+
+ cbor_item_t* chunk = cbor_bytestring_chunks_handle(bytestring)[0];
+ assert_size_equal(cbor_refcount(chunk), 1);
+ assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(chunk));
+ assert_true(cbor_bytestring_is_definite(chunk));
+ assert_size_equal(cbor_bytestring_length(chunk), 3);
+ assert_memory_equal(cbor_bytestring_handle(chunk), bytestring_data, 3);
+ // Data is copied
+ assert_ptr_not_equal(cbor_bytestring_handle(chunk), bytestring_data);
+
+ cbor_decref(&bytestring);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_byte_string_callback_append_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(
+ _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ WITH_FAILING_MALLOC(
+ { cbor_builder_byte_string_callback(&context, bytestring_data, 3); });
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* bytestring = stack.top->item;
+ assert_size_equal(cbor_refcount(bytestring), 1);
+ assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bytestring));
+ assert_size_equal(cbor_bytestring_length(bytestring), 0);
+ assert_true(cbor_bytestring_is_indefinite(bytestring));
+ assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
+
+ cbor_decref(&bytestring);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_byte_string_callback_append_item_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(
+ _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ // Allocate new data block, but fail to allocate a new item with it
+ WITH_MOCK_MALLOC(
+ { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 2,
+ MALLOC, MALLOC_FAIL);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* bytestring = stack.top->item;
+ assert_size_equal(cbor_refcount(bytestring), 1);
+ assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bytestring));
+ assert_size_equal(cbor_bytestring_length(bytestring), 0);
+ assert_true(cbor_bytestring_is_indefinite(bytestring));
+ assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
+
+ cbor_decref(&bytestring);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_byte_string_callback_append_parent_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(
+ _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ // Allocate new item, but fail to push it into the parent on the stack
+ WITH_MOCK_MALLOC(
+ { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 3,
+ MALLOC, MALLOC, REALLOC_FAIL);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* bytestring = stack.top->item;
+ assert_size_equal(cbor_refcount(bytestring), 1);
+ assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
+ assert_true(cbor_isa_bytestring(bytestring));
+ assert_size_equal(cbor_bytestring_length(bytestring), 0);
+ assert_true(cbor_bytestring_is_indefinite(bytestring));
+ assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
+
+ cbor_decref(&bytestring);
+ _cbor_stack_pop(&stack);
+}
+
+unsigned char string_data[] = {0x61, 0x62, 0x63};
+static void test_builder_string_callback_append(void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ cbor_builder_string_callback(&context, string_data, 3);
+
+ assert_false(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ cbor_item_t* string = stack.top->item;
+ assert_size_equal(cbor_refcount(string), 1);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 0);
+ assert_true(cbor_string_is_indefinite(string));
+ assert_size_equal(cbor_string_chunk_count(string), 1);
+
+ cbor_item_t* chunk = cbor_string_chunks_handle(string)[0];
+ assert_size_equal(cbor_refcount(chunk), 1);
+ assert_true(cbor_isa_string(chunk));
+ assert_true(cbor_string_is_definite(chunk));
+ assert_size_equal(cbor_string_length(chunk), 3);
+ assert_memory_equal(cbor_string_handle(chunk), "abc", 3);
+ // Data is copied
+ assert_ptr_not_equal(cbor_string_handle(chunk), string_data);
+
+ cbor_decref(&string);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_string_callback_append_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ WITH_FAILING_MALLOC(
+ { cbor_builder_string_callback(&context, string_data, 3); });
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* string = stack.top->item;
+ assert_size_equal(cbor_refcount(string), 1);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 0);
+ assert_true(cbor_string_is_indefinite(string));
+ assert_size_equal(cbor_string_chunk_count(string), 0);
+
+ cbor_decref(&string);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_string_callback_append_item_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ // Allocate new data block, but fail to allocate a new item with it
+ WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); },
+ 2, MALLOC, MALLOC_FAIL);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* string = stack.top->item;
+ assert_size_equal(cbor_refcount(string), 1);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 0);
+ assert_true(cbor_string_is_indefinite(string));
+ assert_size_equal(cbor_string_chunk_count(string), 0);
+
+ cbor_decref(&string);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_builder_string_callback_append_parent_alloc_failure(
+ void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ // Allocate new item, but fail to push it into the parent on the stack
+ WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); },
+ 3, MALLOC, MALLOC, REALLOC_FAIL);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* string = stack.top->item;
+ assert_size_equal(cbor_refcount(string), 1);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 0);
+ assert_true(cbor_string_is_indefinite(string));
+ assert_size_equal(cbor_string_chunk_count(string), 0);
+
+ cbor_decref(&string);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_append_array_failure(void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_definite_array(0), 0));
+ stack.top->subitems = 1;
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+ cbor_item_t* item = cbor_build_uint8(42);
+
+ _cbor_builder_append(item, &context);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* array = stack.top->item;
+ assert_size_equal(cbor_refcount(array), 1);
+ assert_true(cbor_isa_array(array));
+ assert_size_equal(cbor_array_size(array), 0);
+
+ // item free'd by _cbor_builder_append
+ cbor_decref(&array);
+ _cbor_stack_pop(&stack);
+}
+
+static void test_append_map_failure(void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(
+ _cbor_stack_push(&stack, cbor_new_indefinite_map(), /*subitems=*/0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+ cbor_item_t* item = cbor_build_uint8(42);
+
+ WITH_MOCK_MALLOC({ _cbor_builder_append(item, &context); }, 1, REALLOC_FAIL);
+
+ assert_true(context.creation_failed);
+ assert_false(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+
+ // The stack remains unchanged
+ cbor_item_t* map = stack.top->item;
+ assert_size_equal(cbor_refcount(map), 1);
+ assert_true(cbor_isa_map(map));
+ assert_size_equal(cbor_map_size(map), 0);
+
+ // item free'd by _cbor_builder_append
+ cbor_decref(&map);
+ _cbor_stack_pop(&stack);
+}
+
+// Size 1 array start, but we get an indef break
+unsigned char invalid_indef_break_data[] = {0x81, 0xFF};
+static void test_invalid_indef_break(void** _CBOR_UNUSED(_state)) {
+ struct cbor_load_result res;
+ cbor_item_t* item = cbor_load(invalid_indef_break_data, 2, &res);
+
+ assert_null(item);
+ assert_size_equal(res.read, 2);
+ assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
+}
+
+static void test_invalid_state_indef_break(void** _CBOR_UNUSED(_state)) {
+ struct _cbor_stack stack = _cbor_stack_init();
+ assert_non_null(_cbor_stack_push(&stack, cbor_new_int8(), /*subitems=*/0));
+ struct _cbor_decoder_context context = {
+ .creation_failed = false,
+ .syntax_error = false,
+ .root = NULL,
+ .stack = &stack,
+ };
+
+ cbor_builder_indef_break_callback(&context);
+
+ assert_false(context.creation_failed);
+ assert_true(context.syntax_error);
+ assert_size_equal(context.stack->size, 1);
+ // The stack remains unchanged
+ cbor_item_t* small_int = stack.top->item;
+ assert_size_equal(cbor_refcount(small_int), 1);
+ assert_true(cbor_isa_uint(small_int));
+
+ cbor_decref(&small_int);
+ _cbor_stack_pop(&stack);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_default_callbacks),
+ cmocka_unit_test(test_builder_byte_string_callback_append),
+ cmocka_unit_test(test_builder_byte_string_callback_append_alloc_failure),
+ cmocka_unit_test(
+ test_builder_byte_string_callback_append_item_alloc_failure),
+ cmocka_unit_test(
+ test_builder_byte_string_callback_append_parent_alloc_failure),
+ cmocka_unit_test(test_builder_string_callback_append),
+ cmocka_unit_test(test_builder_string_callback_append_alloc_failure),
+ cmocka_unit_test(test_builder_string_callback_append_item_alloc_failure),
+ cmocka_unit_test(
+ test_builder_string_callback_append_parent_alloc_failure),
+ cmocka_unit_test(test_append_array_failure),
+ cmocka_unit_test(test_append_map_failure),
+ cmocka_unit_test(test_invalid_indef_break),
+ cmocka_unit_test(test_invalid_state_indef_break),
+ };
+
+ cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/cbor_serialize_test.c b/contrib/libcbor/test/cbor_serialize_test.c
new file mode 100644
index 000000000000..a2907b149345
--- /dev/null
+++ b/contrib/libcbor/test/cbor_serialize_test.c
@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+// cbor_serialize_alloc
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <cmocka.h>
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+unsigned char buffer[512];
+
+static void test_serialize_uint8_embed(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, 0);
+ assert_size_equal(1, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, (unsigned char[]){0x00}, 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+}
+
+static void test_serialize_uint8(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, 42);
+ assert_size_equal(2, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x18, 0x2a}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+}
+
+static void test_serialize_uint16(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int16();
+ cbor_set_uint16(item, 1000);
+ assert_size_equal(3, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x19, 0x03, 0xE8}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+}
+
+static void test_serialize_uint32(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int32();
+ cbor_set_uint32(item, 1000000);
+ assert_size_equal(5, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x1A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+ assert_size_equal(cbor_serialized_size(item), 5);
+ cbor_decref(&item);
+}
+
+static void test_serialize_uint64(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int64();
+ cbor_set_uint64(item, 1000000000000);
+ assert_size_equal(9, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x1B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x10, 0x00}),
+ 9);
+ assert_size_equal(cbor_serialized_size(item), 9);
+ cbor_decref(&item);
+}
+
+static void test_serialize_negint8_embed(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, 0);
+ cbor_mark_negint(item);
+ assert_size_equal(1, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, (unsigned char[]){0x20}, 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+}
+
+static void test_serialize_negint8(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int8();
+ cbor_set_uint8(item, 42);
+ cbor_mark_negint(item);
+ assert_size_equal(2, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x38, 0x2a}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+}
+
+static void test_serialize_negint16(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int16();
+ cbor_set_uint16(item, 1000);
+ cbor_mark_negint(item);
+ assert_size_equal(3, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x39, 0x03, 0xE8}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+}
+
+static void test_serialize_negint32(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int32();
+ cbor_set_uint32(item, 1000000);
+ cbor_mark_negint(item);
+ assert_size_equal(5, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x3A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+ assert_size_equal(cbor_serialized_size(item), 5);
+ cbor_decref(&item);
+}
+
+static void test_serialize_negint64(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_int64();
+ cbor_set_uint64(item, 1000000000000);
+ cbor_mark_negint(item);
+ assert_size_equal(9, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x3B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x10, 0x00}),
+ 9);
+ assert_size_equal(cbor_serialized_size(item), 9);
+ cbor_decref(&item);
+}
+
+static void test_serialize_definite_bytestring(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_bytestring();
+ unsigned char *data = malloc(256);
+ cbor_bytestring_set_handle(item, data, 256);
+ memset(data, 0, 256); /* Prevent undefined behavior in comparison */
+ assert_size_equal(256 + 3, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x59, 0x01, 0x00}), 3);
+ assert_memory_equal(buffer + 3, data, 256);
+ assert_size_equal(cbor_serialized_size(item), 259);
+ cbor_decref(&item);
+}
+
+static void test_serialize_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_bytestring();
+
+ cbor_item_t *chunk = cbor_new_definite_bytestring();
+ unsigned char *data = malloc(256);
+ memset(data, 0, 256); /* Prevent undefined behavior in comparison */
+ cbor_bytestring_set_handle(chunk, data, 256);
+
+ assert_true(cbor_bytestring_add_chunk(item, cbor_move(chunk)));
+ assert_size_equal(cbor_bytestring_chunk_count(item), 1);
+
+ assert_size_equal(1 + 3 + 256 + 1, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x5F, 0x59, 0x01, 0x00}), 4);
+ assert_memory_equal(buffer + 4, data, 256);
+ assert_memory_equal(buffer + 4 + 256, ((unsigned char[]){0xFF}), 1);
+ assert_size_equal(cbor_serialized_size(item), 261);
+ cbor_decref(&item);
+}
+
+static void test_serialize_bytestring_size_overflow(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_bytestring();
+
+ // Fake having a huge chunk of data
+ unsigned char *data = malloc(1);
+ cbor_bytestring_set_handle(item, data, SIZE_MAX);
+
+ // Would require 1 + 8 + SIZE_MAX bytes, which overflows size_t
+ assert_size_equal(cbor_serialize(item, buffer, 512), 0);
+ assert_size_equal(cbor_serialized_size(item), 0);
+ cbor_decref(&item);
+}
+
+static void test_serialize_bytestring_no_space(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_bytestring();
+ unsigned char *data = malloc(12);
+ cbor_bytestring_set_handle(item, data, 12);
+
+ assert_size_equal(cbor_serialize(item, buffer, 1), 0);
+
+ cbor_decref(&item);
+}
+
+static void test_serialize_indefinite_bytestring_no_space(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_bytestring();
+ cbor_item_t *chunk = cbor_new_definite_bytestring();
+ unsigned char *data = malloc(256);
+ cbor_bytestring_set_handle(chunk, data, 256);
+ assert_true(cbor_bytestring_add_chunk(item, cbor_move(chunk)));
+
+ // Not enough space for the leading byte
+ assert_size_equal(cbor_serialize(item, buffer, 0), 0);
+
+ // Not enough space for the chunk
+ assert_size_equal(cbor_serialize(item, buffer, 30), 0);
+
+ // Not enough space for the indef break
+ assert_size_equal(
+ cbor_serialize(item, buffer, 1 + cbor_serialized_size(chunk)), 0);
+
+ cbor_decref(&item);
+}
+
+static void test_serialize_definite_string(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_string();
+ unsigned char *data = malloc(12);
+ strncpy((char *)data, "Hello world!", 12);
+ cbor_string_set_handle(item, data, 12);
+ assert_size_equal(1 + 12, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
+ 0x72, 0x6C, 0x64, 0x21}),
+ 13);
+ assert_size_equal(cbor_serialized_size(item), 13);
+ cbor_decref(&item);
+}
+
+static void test_serialize_definite_string_4b_header(
+ void **_CBOR_UNUSED(_state)) {
+#if SIZE_MAX > UINT16_MAX
+ cbor_item_t *item = cbor_new_definite_string();
+ const size_t size = (size_t)UINT16_MAX + 1;
+ unsigned char *data = malloc(size);
+ memset(data, 0, size);
+ cbor_string_set_handle(item, data, size);
+ assert_size_equal(cbor_serialized_size(item), 1 + 4 + size);
+ cbor_decref(&item);
+#endif
+}
+
+static void test_serialize_definite_string_8b_header(
+ void **_CBOR_UNUSED(_state)) {
+#if SIZE_MAX > UINT32_MAX
+ cbor_item_t *item = cbor_new_definite_string();
+ const size_t size = (size_t)UINT32_MAX + 1;
+ unsigned char *data = malloc(1);
+ data[0] = '\0';
+ cbor_string_set_handle(item, data, 1);
+ // Pretend that we have a big item to avoid the huge malloc
+ item->metadata.string_metadata.length = size;
+ assert_size_equal(cbor_serialized_size(item), 1 + 8 + size);
+ cbor_decref(&item);
+#endif
+}
+
+static void test_serialize_indefinite_string(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_string();
+ cbor_item_t *chunk = cbor_new_definite_string();
+
+ unsigned char *data = malloc(12);
+ strncpy((char *)data, "Hello world!", 12);
+ cbor_string_set_handle(chunk, data, 12);
+
+ assert_true(cbor_string_add_chunk(item, cbor_move(chunk)));
+ assert_size_equal(cbor_string_chunk_count(item), 1);
+
+ assert_size_equal(15, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x7F, 0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77,
+ 0x6F, 0x72, 0x6C, 0x64, 0x21, 0xFF}),
+ 15);
+ assert_size_equal(cbor_serialized_size(item), 15);
+ cbor_decref(&item);
+}
+
+static void test_serialize_string_no_space(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_string();
+ unsigned char *data = malloc(12);
+ memset(data, 0, 12);
+ cbor_string_set_handle(item, data, 12);
+
+ assert_size_equal(cbor_serialize(item, buffer, 1), 0);
+
+ cbor_decref(&item);
+}
+
+static void test_serialize_indefinite_string_no_space(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_string();
+ cbor_item_t *chunk = cbor_new_definite_string();
+ unsigned char *data = malloc(256);
+ memset(data, 0, 256);
+ cbor_string_set_handle(chunk, data, 256);
+ assert_true(cbor_string_add_chunk(item, cbor_move(chunk)));
+
+ // Not enough space for the leading byte
+ assert_size_equal(cbor_serialize(item, buffer, 0), 0);
+
+ // Not enough space for the chunk
+ assert_size_equal(cbor_serialize(item, buffer, 30), 0);
+
+ // Not enough space for the indef break
+ assert_size_equal(
+ cbor_serialize(item, buffer, 1 + cbor_serialized_size(chunk)), 0);
+
+ cbor_decref(&item);
+}
+
+static void test_serialize_definite_array(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_array(2);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_true(cbor_array_push(item, one));
+ assert_true(cbor_array_set(item, 1, two));
+ assert_true(cbor_array_replace(item, 0, one));
+
+ assert_size_equal(3, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x82, 0x01, 0x02}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_serialize_array_no_space(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_array();
+ cbor_item_t *one = cbor_build_uint8(1);
+ assert_true(cbor_array_push(item, one));
+ assert_size_equal(cbor_serialized_size(item), 3);
+
+ // Not enough space for the leading byte
+ assert_size_equal(0, cbor_serialize(item, buffer, 0));
+
+ // Not enough space for the item
+ assert_size_equal(0, cbor_serialize(item, buffer, 1));
+
+ // Not enough space for the indef break
+ assert_size_equal(0, cbor_serialize(item, buffer, 2));
+
+ cbor_decref(&item);
+ cbor_decref(&one);
+}
+
+static void test_serialize_indefinite_array(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_array();
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_true(cbor_array_push(item, one));
+ assert_true(cbor_array_push(item, two));
+
+ assert_size_equal(4, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x9F, 0x01, 0x02, 0xFF}), 4);
+ assert_size_equal(cbor_serialized_size(item), 4);
+ cbor_decref(&item);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_serialize_definite_map(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_map(2);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
+ assert_true(cbor_map_add(item, (struct cbor_pair){.key = two, .value = one}));
+
+ assert_size_equal(5, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xA2, 0x01, 0x02, 0x02, 0x01}),
+ 5);
+ assert_size_equal(cbor_serialized_size(item), 5);
+ cbor_decref(&item);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_serialize_indefinite_map(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_map();
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
+ assert_true(cbor_map_add(item, (struct cbor_pair){.key = two, .value = one}));
+
+ assert_size_equal(6, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer, ((unsigned char[]){0xBF, 0x01, 0x02, 0x02, 0x01, 0xFF}), 6);
+ assert_size_equal(cbor_serialized_size(item), 6);
+ cbor_decref(&item);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_serialize_map_no_space(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_map();
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+ assert_true(cbor_map_add(item, (struct cbor_pair){.key = one, .value = two}));
+ assert_size_equal(cbor_serialized_size(item), 4);
+
+ // Not enough space for the leading byte
+ assert_size_equal(cbor_serialize(item, buffer, 0), 0);
+
+ // Not enough space for the key
+ assert_size_equal(cbor_serialize(item, buffer, 1), 0);
+
+ // Not enough space for the value
+ assert_size_equal(cbor_serialize(item, buffer, 2), 0);
+
+ // Not enough space for the indef break
+ assert_size_equal(cbor_serialize(item, buffer, 3), 0);
+
+ cbor_decref(&item);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_serialize_tags(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_tag(21);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_tag_set_item(item, one);
+
+ assert_size_equal(2, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xD5, 0x01}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+ cbor_decref(&one);
+}
+
+static void test_serialize_tags_no_space(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_tag(21);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_tag_set_item(item, one);
+ assert_size_equal(cbor_serialized_size(item), 2);
+
+ // Not enough space for the leading byte
+ assert_size_equal(cbor_serialize(item, buffer, 0), 0);
+
+ // Not enough space for the item
+ assert_size_equal(cbor_serialize(item, buffer, 1), 0);
+
+ cbor_decref(&item);
+ cbor_decref(&one);
+}
+
+static void test_serialize_half(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_float2();
+ cbor_set_float2(item, NAN);
+
+ assert_size_equal(3, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+}
+
+static void test_serialize_single(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_float4();
+ cbor_set_float4(item, 100000.0f);
+
+ assert_size_equal(5, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x47, 0xC3, 0x50, 0x00}),
+ 5);
+ assert_size_equal(cbor_serialized_size(item), 5);
+ cbor_decref(&item);
+}
+
+static void test_serialize_double(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_float8();
+ cbor_set_float8(item, -4.1);
+
+ assert_size_equal(9, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0xC0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}),
+ 9);
+ assert_size_equal(cbor_serialized_size(item), 9);
+ cbor_decref(&item);
+}
+
+static void test_serialize_ctrl(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_undef();
+
+ assert_size_equal(1, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF7}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+}
+
+static void test_serialize_long_ctrl(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_ctrl();
+ cbor_set_ctrl(item, 254);
+
+ assert_size_equal(2, cbor_serialize(item, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF8, 0xFE}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+}
+
+static void test_auto_serialize(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_array(4);
+ for (size_t i = 0; i < 4; i++) {
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint64(0))));
+ }
+
+ unsigned char *output;
+ size_t output_size;
+ assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 37);
+ assert_size_equal(output_size, 37);
+ assert_size_equal(cbor_serialized_size(item), 37);
+ assert_memory_equal(output, ((unsigned char[]){0x84, 0x1B}), 2);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_no_size(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_uint8(1);
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
+ assert_memory_equal(output, ((unsigned char[]){0x01}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_too_large(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_string();
+ cbor_item_t *chunk = cbor_new_definite_string();
+ assert_true(cbor_string_add_chunk(item, chunk));
+
+ // Pretend the chunk is huge
+ chunk->metadata.string_metadata.length = SIZE_MAX;
+ assert_true(SIZE_MAX + 2 == 1);
+ assert_size_equal(cbor_serialized_size(item), 0);
+ unsigned char *output;
+ size_t output_size;
+ assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 0);
+ assert_size_equal(output_size, 0);
+ assert_null(output);
+
+ chunk->metadata.string_metadata.length = 0;
+ cbor_decref(&chunk);
+ cbor_decref(&item);
+}
+
+static void test_auto_serialize_alloc_fail(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_uint8(42);
+
+ WITH_FAILING_MALLOC({
+ unsigned char *output;
+ size_t output_size;
+ assert_size_equal(cbor_serialize_alloc(item, &output, &output_size), 0);
+ assert_size_equal(output_size, 0);
+ assert_null(output);
+ });
+
+ cbor_decref(&item);
+}
+
+static void test_auto_serialize_zero_len_bytestring(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_bytestring((cbor_data) "", 0);
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
+ assert_memory_equal(output, ((unsigned char[]){0x40}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_string(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_string("");
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
+ assert_memory_equal(output, ((unsigned char[]){0x60}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_bytestring_chunk(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_bytestring();
+
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "", 0))));
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 3);
+ assert_memory_equal(output, ((unsigned char[]){0x5f, 0x40, 0xff}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_string_chunk(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_string();
+
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string(""))));
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 3);
+ assert_memory_equal(output, ((unsigned char[]){0x7f, 0x60, 0xff}), 3);
+ assert_size_equal(cbor_serialized_size(item), 3);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_array(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_array(0);
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
+ assert_memory_equal(output, ((unsigned char[]){0x80}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_indef_array(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_array();
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 2);
+ assert_memory_equal(output, ((unsigned char[]){0x9f, 0xff}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_map(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_map(0);
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 1);
+ assert_memory_equal(output, ((unsigned char[]){0xa0}), 1);
+ assert_size_equal(cbor_serialized_size(item), 1);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+static void test_auto_serialize_zero_len_indef_map(
+ void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_map();
+
+ unsigned char *output;
+ assert_size_equal(cbor_serialize_alloc(item, &output, NULL), 2);
+ assert_memory_equal(output, ((unsigned char[]){0xbf, 0xff}), 2);
+ assert_size_equal(cbor_serialized_size(item), 2);
+ cbor_decref(&item);
+ _cbor_free(output);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_serialize_uint8_embed),
+ cmocka_unit_test(test_serialize_uint8),
+ cmocka_unit_test(test_serialize_uint16),
+ cmocka_unit_test(test_serialize_uint32),
+ cmocka_unit_test(test_serialize_uint64),
+ cmocka_unit_test(test_serialize_negint8_embed),
+ cmocka_unit_test(test_serialize_negint8),
+ cmocka_unit_test(test_serialize_negint16),
+ cmocka_unit_test(test_serialize_negint32),
+ cmocka_unit_test(test_serialize_negint64),
+ cmocka_unit_test(test_serialize_definite_bytestring),
+ cmocka_unit_test(test_serialize_indefinite_bytestring),
+ cmocka_unit_test(test_serialize_bytestring_size_overflow),
+ cmocka_unit_test(test_serialize_bytestring_no_space),
+ cmocka_unit_test(test_serialize_indefinite_bytestring_no_space),
+ cmocka_unit_test(test_serialize_definite_string),
+ cmocka_unit_test(test_serialize_definite_string_4b_header),
+ cmocka_unit_test(test_serialize_definite_string_8b_header),
+ cmocka_unit_test(test_serialize_indefinite_string),
+ cmocka_unit_test(test_serialize_string_no_space),
+ cmocka_unit_test(test_serialize_indefinite_string_no_space),
+ cmocka_unit_test(test_serialize_definite_array),
+ cmocka_unit_test(test_serialize_indefinite_array),
+ cmocka_unit_test(test_serialize_array_no_space),
+ cmocka_unit_test(test_serialize_definite_map),
+ cmocka_unit_test(test_serialize_indefinite_map),
+ cmocka_unit_test(test_serialize_map_no_space),
+ cmocka_unit_test(test_serialize_tags),
+ cmocka_unit_test(test_serialize_tags_no_space),
+ cmocka_unit_test(test_serialize_half),
+ cmocka_unit_test(test_serialize_single),
+ cmocka_unit_test(test_serialize_double),
+ cmocka_unit_test(test_serialize_ctrl),
+ cmocka_unit_test(test_serialize_long_ctrl),
+ cmocka_unit_test(test_auto_serialize),
+ cmocka_unit_test(test_auto_serialize_no_size),
+ cmocka_unit_test(test_auto_serialize_too_large),
+ cmocka_unit_test(test_auto_serialize_alloc_fail),
+ cmocka_unit_test(test_auto_serialize_zero_len_bytestring),
+ cmocka_unit_test(test_auto_serialize_zero_len_string),
+ cmocka_unit_test(test_auto_serialize_zero_len_bytestring_chunk),
+ cmocka_unit_test(test_auto_serialize_zero_len_string_chunk),
+ cmocka_unit_test(test_auto_serialize_zero_len_array),
+ cmocka_unit_test(test_auto_serialize_zero_len_indef_array),
+ cmocka_unit_test(test_auto_serialize_zero_len_map),
+ cmocka_unit_test(test_auto_serialize_zero_len_indef_map),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/cbor_stream_decode_test.c b/contrib/libcbor/test/cbor_stream_decode_test.c
new file mode 100644
index 000000000000..5288016c2fc6
--- /dev/null
+++ b/contrib/libcbor/test/cbor_stream_decode_test.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "stream_expectations.h"
+
+static void test_no_data(void **_CBOR_UNUSED(_state)) {
+ assert_decoder_result_nedata(1, decode(NULL, 0));
+}
+
+unsigned char embedded_uint8_data[] = {0x00, 0x01, 0x05, 0x17};
+static void test_uint8_embedded_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_uint8_data, 1));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_uint8_data + 1, 1));
+
+ assert_uint8_eq(5);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_uint8_data + 2, 1));
+
+ assert_uint8_eq(23);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_uint8_data + 3, 1));
+}
+
+unsigned char uint8_data[] = {0x18, 0x83, 0x18, 0xFF};
+static void test_uint8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_uint8_eq(0x83);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(uint8_data, 2));
+
+ assert_uint8_eq(0xFF);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(uint8_data + 2, 2));
+
+ assert_minimum_input_size(2, uint8_data);
+}
+
+unsigned char uint16_data[] = {0x19, 0x01, 0xf4};
+static void test_uint16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_uint16_eq(500);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(uint16_data, 3));
+
+ assert_minimum_input_size(3, uint16_data);
+}
+
+unsigned char uint32_data[] = {0x1a, 0xa5, 0xf7, 0x02, 0xb3};
+static void test_uint32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_uint32_eq((uint32_t)2784428723UL);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(uint32_data, 5));
+
+ assert_minimum_input_size(5, uint32_data);
+}
+
+unsigned char uint64_data[] = {0x1b, 0xa5, 0xf7, 0x02, 0xb3,
+ 0xa5, 0xf7, 0x02, 0xb3};
+static void test_uint64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_uint64_eq(11959030306112471731ULL);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(uint64_data, 9));
+
+ assert_minimum_input_size(9, uint64_data);
+}
+
+unsigned char embedded_negint8_data[] = {0x20, 0x21, 0x25, 0x37};
+static void test_negint8_embedded_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_negint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_negint8_data, 1));
+
+ assert_negint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_negint8_data + 1, 1));
+
+ assert_negint8_eq(5);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_negint8_data + 2, 1));
+
+ assert_negint8_eq(23);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(embedded_negint8_data + 3, 1));
+}
+
+unsigned char negint8_data[] = {0x38, 0x83, 0x38, 0xFF};
+static void test_negint8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_negint8_eq(0x83);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(negint8_data, 2));
+
+ assert_negint8_eq(0xFF);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(negint8_data + 2, 2));
+
+ assert_minimum_input_size(2, negint8_data);
+}
+
+unsigned char negint16_data[] = {0x39, 0x01, 0xf4};
+static void test_negint16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_negint16_eq(500);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(negint16_data, 3));
+
+ assert_minimum_input_size(3, negint16_data);
+}
+
+unsigned char negint32_data[] = {0x3a, 0xa5, 0xf7, 0x02, 0xb3};
+static void test_negint32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_negint32_eq((uint32_t)2784428723UL);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(negint32_data, 5));
+
+ assert_minimum_input_size(5, negint32_data);
+}
+
+unsigned char negint64_data[] = {0x3b, 0xa5, 0xf7, 0x02, 0xb3,
+ 0xa5, 0xf7, 0x02, 0xb3};
+static void test_negint64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_negint64_eq(11959030306112471731ULL);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(negint64_data, 9));
+
+ assert_minimum_input_size(9, negint64_data);
+}
+
+unsigned char bstring_embedded_int8_data[] = {0x41, 0xFF};
+static void test_bstring_embedded_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_embedded_int8_data + 1, 1);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(bstring_embedded_int8_data, 2));
+
+ assert_minimum_input_size(2, bstring_embedded_int8_data);
+}
+
+// The callback returns a *pointer* to the the start of the data segment (after
+// the second byte of input); the data is never read, so we never run into
+// memory issues despite not allocating and initializing all the data.
+unsigned char bstring_int8_data[] = {0x58, 0x02 /*, [2 bytes] */};
+static void test_bstring_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_int8_data + 2, 2);
+ assert_decoder_result(4, CBOR_DECODER_FINISHED, decode(bstring_int8_data, 4));
+
+ assert_minimum_input_size(2, bstring_int8_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 2 + 2,
+ decode(bstring_int8_data, 2));
+}
+
+unsigned char bstring_int8_empty_data[] = {0x58, 0x00};
+static void test_bstring_int8_empty_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_int8_empty_data + 2, 0);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(bstring_int8_empty_data, 2));
+
+ assert_minimum_input_size(2, bstring_int8_empty_data);
+}
+
+unsigned char bstring_int16_data[] = {0x59, 0x01, 0x5C /*, [348 bytes] */};
+static void test_bstring_int16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_int16_data + 3, 348);
+ assert_decoder_result(3 + 348, CBOR_DECODER_FINISHED,
+ decode(bstring_int16_data, 3 + 348));
+
+ assert_minimum_input_size(3, bstring_int16_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 3 + 348,
+ decode(bstring_int16_data, 3));
+}
+
+unsigned char bstring_int32_data[] = {0x5A, 0x00, 0x10, 0x10,
+ 0x10 /*, [1052688 bytes] */};
+static void test_bstring_int32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_int32_data + 5, 1052688);
+ assert_decoder_result(5 + 1052688, CBOR_DECODER_FINISHED,
+ decode(bstring_int32_data, 5 + 1052688));
+
+ assert_minimum_input_size(5, bstring_int32_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 5 + 1052688,
+ decode(bstring_int32_data, 5));
+}
+
+#ifdef EIGHT_BYTE_SIZE_T
+unsigned char bstring_int64_data[] = {
+ 0x5B, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00 /*, [4294967296 bytes] */};
+static void test_bstring_int64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_mem_eq(bstring_int64_data + 9, 4294967296);
+ assert_decoder_result(9 + 4294967296, CBOR_DECODER_FINISHED,
+ decode(bstring_int64_data, 9 + 4294967296));
+
+ assert_minimum_input_size(9, bstring_int64_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 9 + 4294967296,
+ decode(bstring_int64_data, 9));
+}
+#endif
+
+unsigned char bstring_indef_1_data[] = {0x5F, 0x40 /* Empty byte string */,
+ 0xFF};
+static void test_bstring_indef_decoding_1(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_1_data, 3));
+
+ assert_bstring_mem_eq(bstring_indef_1_data + 2, 0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_1_data + 1, 2));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_1_data + 2, 1));
+}
+
+unsigned char bstring_indef_2_data[] = {0x5F, 0xFF};
+static void test_bstring_indef_decoding_2(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_2_data, 2));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_2_data + 1, 1));
+}
+
+unsigned char bstring_indef_3_data[] = {0x5F,
+ // Empty byte string
+ 0x40,
+ // 1B, 1 character byte string
+ 0x58, 0x01, 0x00,
+ // Break
+ 0xFF};
+static void test_bstring_indef_decoding_3(void **_CBOR_UNUSED(_state)) {
+ assert_bstring_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_3_data, 6));
+
+ assert_bstring_mem_eq(bstring_indef_3_data + 2, 0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_3_data + 1, 5));
+
+ assert_bstring_mem_eq(bstring_indef_3_data + 4, 1);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_3_data + 2, 4));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(bstring_indef_3_data + 5, 1));
+}
+
+unsigned char string_embedded_int8_data[] = {0x61, 0xFF};
+static void test_string_embedded_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_embedded_int8_data + 1, 1);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(string_embedded_int8_data, 2));
+
+ assert_minimum_input_size(2, string_embedded_int8_data);
+}
+
+// The callback returns a *pointer* to the the start of the data segment (after
+// the second byte of input); the data is never read, so we never run into
+// memory issues despite not allocating and initializing all the data.
+unsigned char string_int8_data[] = {0x78, 0x02 /*, [2 bytes] */};
+static void test_string_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_int8_data + 2, 2);
+ assert_decoder_result(4, CBOR_DECODER_FINISHED, decode(string_int8_data, 4));
+
+ assert_minimum_input_size(2, string_int8_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 2 + 2,
+ decode(string_int8_data, 2));
+}
+
+unsigned char string_int8_empty_data[] = {0x78, 0x00};
+static void test_string_int8_empty_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_int8_empty_data + 2, 0);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(string_int8_empty_data, 2));
+
+ assert_minimum_input_size(2, string_int8_empty_data);
+}
+
+unsigned char string_int16_data[] = {0x79, 0x01, 0x5C /*, [348 bytes] */};
+static void test_string_int16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_int16_data + 3, 348);
+ assert_decoder_result(3 + 348, CBOR_DECODER_FINISHED,
+ decode(string_int16_data, 3 + 348));
+
+ assert_minimum_input_size(3, string_int16_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 3 + 348,
+ decode(string_int16_data, 3));
+}
+
+unsigned char string_int32_data[] = {0x7A, 0x00, 0x10, 0x10,
+ 0x10 /*, [1052688 bytes] */};
+static void test_string_int32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_int32_data + 5, 1052688);
+ assert_decoder_result(5 + 1052688, CBOR_DECODER_FINISHED,
+ decode(string_int32_data, 5 + 1052688));
+
+ assert_minimum_input_size(5, string_int32_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 5 + 1052688,
+ decode(string_int32_data, 5));
+}
+
+#ifdef EIGHT_BYTE_SIZE_T
+unsigned char string_int64_data[] = {
+ 0x7B, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00 /*, [4294967296 bytes] */};
+static void test_string_int64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_string_mem_eq(string_int64_data + 9, 4294967296);
+ assert_decoder_result(9 + 4294967296, CBOR_DECODER_FINISHED,
+ decode(string_int64_data, 9 + 4294967296));
+
+ assert_minimum_input_size(9, string_int64_data);
+ assert_decoder_result_nedata(/* expected_bytes_required= */ 9 + 4294967296,
+ decode(string_int64_data, 9));
+}
+#endif
+
+unsigned char string_indef_1_data[] = {0x7F, 0x60 /* Empty string */, 0xFF};
+static void test_string_indef_decoding_1(void **_CBOR_UNUSED(_state)) {
+ assert_string_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_1_data, 3));
+
+ assert_string_mem_eq(string_indef_1_data + 2, 0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_1_data + 1, 2));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_1_data + 2, 1));
+}
+
+unsigned char string_indef_2_data[] = {0x7F, 0xFF};
+static void test_string_indef_decoding_2(void **_CBOR_UNUSED(_state)) {
+ assert_string_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_2_data, 2));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_2_data + 1, 1));
+}
+
+unsigned char string_indef_3_data[] = {0x7F,
+ // Empty string
+ 0x60,
+ // 1B, 1 character byte string
+ 0x78, 0x01, 0x00,
+ // Break
+ 0xFF};
+static void test_string_indef_decoding_3(void **_CBOR_UNUSED(_state)) {
+ assert_string_indef_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_3_data, 6));
+
+ assert_string_mem_eq(string_indef_3_data + 2, 0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_3_data + 1, 5));
+
+ assert_string_mem_eq(string_indef_3_data + 4, 1);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED,
+ decode(string_indef_3_data + 2, 4));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(string_indef_3_data + 5, 1));
+}
+
+unsigned char array_embedded_int8_data[] = {0x80};
+static void test_array_embedded_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_embedded_int8_data, 1));
+}
+
+unsigned char array_int8_data[] = {0x98, 0x02, 0x00, 0x01};
+static void test_array_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(2);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(array_int8_data, 4));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int8_data + 2, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int8_data + 3, 1));
+
+ assert_minimum_input_size(2, array_int8_data);
+}
+
+unsigned char array_int16_data[] = {0x99, 0x00, 0x02, 0x00, 0x01};
+static void test_array_int16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(2);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(array_int16_data, 5));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int16_data + 3, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int16_data + 4, 1));
+
+ assert_minimum_input_size(3, array_int16_data);
+}
+
+unsigned char array_int32_data[] = {0x9A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01};
+static void test_array_int32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(2);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(array_int32_data, 7));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int32_data + 5, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int32_data + 6, 1));
+
+ assert_minimum_input_size(5, array_int32_data);
+}
+
+unsigned char array_int64_data[] = {0x9B, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x01};
+static void test_array_int64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(2);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(array_int64_data, 11));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int64_data + 9, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_int64_data + 10, 1));
+
+ assert_minimum_input_size(9, array_int64_data);
+}
+
+unsigned char array_of_arrays_data[] = {0x82, 0x80, 0x80};
+static void test_array_of_arrays_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_array_start(2);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_of_arrays_data, 3));
+
+ assert_array_start(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_of_arrays_data + 1, 2));
+
+ assert_array_start(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(array_of_arrays_data + 2, 1));
+}
+
+unsigned char indef_array_data_1[] = {0x9F, 0x00, 0x18, 0xFF, 0x9F, 0xFF, 0xFF};
+static void test_indef_array_decoding_1(void **_CBOR_UNUSED(_state)) {
+ assert_indef_array_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1, 7));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1 + 1, 6));
+
+ assert_uint8_eq(255);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1 + 2, 4));
+
+ assert_indef_array_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1 + 4, 3));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1 + 5, 2));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_array_data_1 + 6, 1));
+}
+
+unsigned char map_embedded_int8_data[] = {0xa1, 0x01, 0x00};
+static void test_map_embedded_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_map_start(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_embedded_int8_data, 3));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_embedded_int8_data + 1, 2));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_embedded_int8_data + 2, 1));
+}
+
+unsigned char map_int8_data[] = {0xB8, 0x01, 0x00, 0x01};
+static void test_map_int8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_map_start(1);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(map_int8_data, 4));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(map_int8_data + 2, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(map_int8_data + 3, 1));
+
+ assert_minimum_input_size(2, map_int8_data);
+}
+
+unsigned char map_int16_data[] = {0xB9, 0x00, 0x01, 0x00, 0x01};
+static void test_map_int16_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_map_start(1);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(map_int16_data, 5));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int16_data + 3, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int16_data + 4, 1));
+
+ assert_minimum_input_size(3, map_int16_data);
+}
+
+unsigned char map_int32_data[] = {0xBA, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01};
+static void test_map_int32_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_map_start(1);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(map_int32_data, 7));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int32_data + 5, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int32_data + 6, 1));
+
+ assert_minimum_input_size(5, map_int32_data);
+}
+
+unsigned char map_int64_data[] = {0xBB, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x01};
+static void test_map_int64_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_map_start(1);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(map_int64_data, 11));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int64_data + 9, 2));
+
+ assert_uint8_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(map_int64_data + 10, 1));
+
+ assert_minimum_input_size(9, map_int64_data);
+}
+
+unsigned char indef_map_data_1[] = {0xBF, 0x00, 0x18, 0xFF, 0xFF};
+static void test_indef_map_decoding_1(void **_CBOR_UNUSED(_state)) {
+ assert_indef_map_start();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(indef_map_data_1, 5));
+
+ assert_uint8_eq(0);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_map_data_1 + 1, 4));
+
+ assert_uint8_eq(255);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED,
+ decode(indef_map_data_1 + 2, 3));
+
+ assert_indef_break();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED,
+ decode(indef_map_data_1 + 4, 1));
+}
+
+unsigned char embedded_tag_data[] = {0xC1};
+static void test_embedded_tag_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_tag_eq(1);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(embedded_tag_data, 1));
+}
+
+unsigned char int8_tag_data[] = {0xD8, 0xFE};
+static void test_int8_tag_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_tag_eq(254);
+ assert_decoder_result(2, CBOR_DECODER_FINISHED, decode(int8_tag_data, 2));
+
+ assert_minimum_input_size(2, int8_tag_data);
+}
+
+unsigned char int16_tag_data[] = {0xD9, 0xFE, 0xFD};
+static void test_int16_tag_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_tag_eq(65277);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(int16_tag_data, 3));
+
+ assert_minimum_input_size(3, int16_tag_data);
+}
+
+unsigned char int32_tag_data[] = {0xDA, 0xFE, 0xFD, 0xFC, 0xFB};
+static void test_int32_tag_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_tag_eq(4278058235ULL);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(int32_tag_data, 5));
+
+ assert_minimum_input_size(5, int32_tag_data);
+}
+
+unsigned char int64_tag_data[] = {0xDB, 0xFE, 0xFD, 0xFC, 0xFB,
+ 0xFA, 0xF9, 0xF8, 0xF7};
+static void test_int64_tag_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_tag_eq(18374120213919168759ULL);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(int64_tag_data, 9));
+
+ assert_minimum_input_size(9, int64_tag_data);
+}
+
+unsigned char reserved_byte_data[] = {0xDC};
+static void test_reserved_byte_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_decoder_result(0, CBOR_DECODER_ERROR, decode(reserved_byte_data, 1));
+}
+
+unsigned char float2_data[] = {0xF9, 0x7B, 0xFF};
+static void test_float2_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_half(65504.0f);
+ assert_decoder_result(3, CBOR_DECODER_FINISHED, decode(float2_data, 3));
+
+ assert_minimum_input_size(3, float2_data);
+}
+
+unsigned char float4_data[] = {0xFA, 0x47, 0xC3, 0x50, 0x00};
+static void test_float4_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_float(100000.0f);
+ assert_decoder_result(5, CBOR_DECODER_FINISHED, decode(float4_data, 5));
+
+ assert_minimum_input_size(5, float4_data);
+}
+
+unsigned char float8_data[] = {0xFB, 0xC0, 0x10, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66};
+static void test_float8_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_double(-4.1);
+ assert_decoder_result(9, CBOR_DECODER_FINISHED, decode(float8_data, 9));
+
+ assert_minimum_input_size(0, float8_data);
+}
+
+unsigned char false_data[] = {0xF4};
+static void test_false_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bool(false);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(false_data, 1));
+}
+
+unsigned char true_data[] = {0xF5};
+static void test_true_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_bool(true);
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(true_data, 1));
+}
+
+unsigned char null_data[] = {0xF6};
+static void test_null_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_nil();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(null_data, 1));
+}
+
+unsigned char undef_data[] = {0xF7};
+static void test_undef_decoding(void **_CBOR_UNUSED(_state)) {
+ assert_undef();
+ assert_decoder_result(1, CBOR_DECODER_FINISHED, decode(undef_data, 1));
+}
+
+#define stream_test(f) cmocka_unit_test_teardown(f, clean_up_stream_assertions)
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ stream_test(test_no_data),
+
+ stream_test(test_uint8_embedded_decoding),
+ stream_test(test_uint8_decoding),
+ stream_test(test_uint16_decoding),
+ stream_test(test_uint32_decoding),
+ stream_test(test_uint64_decoding),
+
+ stream_test(test_negint8_embedded_decoding),
+ stream_test(test_negint8_decoding),
+ stream_test(test_negint16_decoding),
+ stream_test(test_negint32_decoding),
+ stream_test(test_negint64_decoding),
+
+ stream_test(test_bstring_embedded_int8_decoding),
+ stream_test(test_bstring_int8_decoding),
+ stream_test(test_bstring_int8_empty_decoding),
+ stream_test(test_bstring_int16_decoding),
+ stream_test(test_bstring_int32_decoding),
+#ifdef EIGHT_BYTE_SIZE_T
+ stream_test(test_bstring_int64_decoding),
+#endif
+ stream_test(test_bstring_indef_decoding_1),
+ stream_test(test_bstring_indef_decoding_2),
+ stream_test(test_bstring_indef_decoding_3),
+
+ stream_test(test_string_embedded_int8_decoding),
+ stream_test(test_string_int8_decoding),
+ stream_test(test_string_int8_empty_decoding),
+ stream_test(test_string_int16_decoding),
+ stream_test(test_string_int32_decoding),
+#ifdef EIGHT_BYTE_SIZE_T
+ stream_test(test_string_int64_decoding),
+#endif
+ stream_test(test_string_indef_decoding_1),
+ stream_test(test_string_indef_decoding_2),
+ stream_test(test_string_indef_decoding_3),
+
+ stream_test(test_array_embedded_int8_decoding),
+ stream_test(test_array_int8_decoding),
+ stream_test(test_array_int16_decoding),
+ stream_test(test_array_int32_decoding),
+ stream_test(test_array_int64_decoding),
+ stream_test(test_array_of_arrays_decoding),
+ stream_test(test_indef_array_decoding_1),
+
+ stream_test(test_map_embedded_int8_decoding),
+ stream_test(test_map_int8_decoding),
+ stream_test(test_map_int16_decoding),
+ stream_test(test_map_int32_decoding),
+ stream_test(test_map_int64_decoding),
+ stream_test(test_indef_map_decoding_1),
+
+ stream_test(test_embedded_tag_decoding),
+ stream_test(test_int8_tag_decoding),
+ stream_test(test_int16_tag_decoding),
+ stream_test(test_int32_tag_decoding),
+ stream_test(test_int64_tag_decoding),
+ stream_test(test_reserved_byte_decoding),
+
+ stream_test(test_float2_decoding),
+ stream_test(test_float4_decoding),
+ stream_test(test_float8_decoding),
+
+ stream_test(test_false_decoding),
+ stream_test(test_true_decoding),
+ stream_test(test_null_decoding),
+ stream_test(test_undef_decoding)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/copy_test.c b/contrib/libcbor/test/copy_test.c
new file mode 100644
index 000000000000..92e210a6a600
--- /dev/null
+++ b/contrib/libcbor/test/copy_test.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *item, *copy, *tmp;
+
+static void test_uints(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_uint8(10);
+ assert_uint8(copy = cbor_copy(item), 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_uint16(10);
+ assert_uint16(copy = cbor_copy(item), 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_uint32(10);
+ assert_uint32(copy = cbor_copy(item), 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_uint64(10);
+ assert_uint64(copy = cbor_copy(item), 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_negints(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_negint8(10);
+ assert_true(cbor_get_uint8(copy = cbor_copy(item)) == 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_negint16(10);
+ assert_true(cbor_get_uint16(copy = cbor_copy(item)) == 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_negint32(10);
+ assert_true(cbor_get_uint32(copy = cbor_copy(item)) == 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_negint64(10);
+ assert_true(cbor_get_uint64(copy = cbor_copy(item)) == 10);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_def_bytestring(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_bytestring((cbor_data) "abc", 3);
+ assert_memory_equal(cbor_bytestring_handle(copy = cbor_copy(item)),
+ cbor_bytestring_handle(item), 3);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_indef_bytestring(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
+ copy = cbor_copy(item);
+
+ assert_size_equal(cbor_bytestring_chunk_count(item),
+ cbor_bytestring_chunk_count(copy));
+
+ assert_memory_equal(
+ cbor_bytestring_handle(cbor_bytestring_chunks_handle(copy)[0]), "abc", 3);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_def_string(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_string("abc");
+ assert_memory_equal(cbor_string_handle(copy = cbor_copy(item)),
+ cbor_string_handle(item), 3);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_indef_string(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_string();
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
+ copy = cbor_copy(item);
+
+ assert_size_equal(cbor_string_chunk_count(item),
+ cbor_string_chunk_count(copy));
+
+ assert_memory_equal(cbor_string_handle(cbor_string_chunks_handle(copy)[0]),
+ "abc", 3);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_def_array(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_definite_array(1);
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+
+ assert_uint8(tmp = cbor_array_get(copy = cbor_copy(item), 0), 42);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+ cbor_decref(&tmp);
+}
+
+static void test_indef_array(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+
+ assert_uint8(tmp = cbor_array_get(copy = cbor_copy(item), 0), 42);
+ cbor_decref(&item);
+ cbor_decref(&copy);
+ cbor_decref(&tmp);
+}
+
+static void test_def_map(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_definite_map(1);
+ assert_true(cbor_map_add(item, (struct cbor_pair){
+ .key = cbor_move(cbor_build_uint8(42)),
+ .value = cbor_move(cbor_build_uint8(43)),
+ }));
+
+ assert_uint8(cbor_map_handle(copy = cbor_copy(item))[0].key, 42);
+
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_indef_map(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(cbor_map_add(item, (struct cbor_pair){
+ .key = cbor_move(cbor_build_uint8(42)),
+ .value = cbor_move(cbor_build_uint8(43)),
+ }));
+
+ assert_uint8(cbor_map_handle(copy = cbor_copy(item))[0].key, 42);
+
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_tag(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_tag(10, cbor_move(cbor_build_uint8(42)));
+
+ assert_uint8(cbor_move(cbor_tag_item(copy = cbor_copy(item))), 42);
+
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_ctrls(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_null();
+ assert_true(cbor_is_null(copy = cbor_copy(item)));
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_floats(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_float2(3.14f);
+ assert_true(cbor_float_get_float2(copy = cbor_copy(item)) ==
+ cbor_float_get_float2(item));
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_float4(3.14f);
+ assert_true(cbor_float_get_float4(copy = cbor_copy(item)) ==
+ cbor_float_get_float4(item));
+ cbor_decref(&item);
+ cbor_decref(&copy);
+
+ item = cbor_build_float8(3.14);
+ assert_true(cbor_float_get_float8(copy = cbor_copy(item)) ==
+ cbor_float_get_float8(item));
+ cbor_decref(&item);
+ cbor_decref(&copy);
+}
+
+static void test_alloc_failure_simple(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_uint8(10);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_bytestring_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_bytestring_chunk_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2, MALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_bytestring_chunk_append_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
+ // New indef string, cbor_indefinite_string_data, chunk item,
+ // chunk data, extend cbor_indefinite_string_data.chunks
+ MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_bytestring_second_chunk_alloc_failure(
+ void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "abc", 3))));
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring((cbor_data) "def", 3))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 6,
+ // New indef string, cbor_indefinite_string_data, chunk item,
+ // chunk data, extend cbor_indefinite_string_data.chunks,
+ // second chunk item
+ MALLOC, MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_string_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_string();
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_string_chunk_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_string();
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2, MALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_string_chunk_append_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_string();
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
+ // New indef string, cbor_indefinite_string_data, chunk item,
+ // chunk data, extend cbor_indefinite_string_data.chunks
+ MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_string_second_chunk_alloc_failure(
+ void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_string();
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("abc"))));
+ assert_true(cbor_string_add_chunk(item, cbor_move(cbor_build_string("def"))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 6,
+ // New indef string, cbor_indefinite_string_data, chunk item,
+ // chunk data, extend cbor_indefinite_string_data.chunks,
+ // second chunk item
+ MALLOC, MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_array_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_array_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
+ // New array, item copy
+ MALLOC, MALLOC_FAIL);
+
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_array_push_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 3,
+ // New array, item copy, array reallocation
+ MALLOC, MALLOC, REALLOC_FAIL);
+
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_array_second_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(42))));
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(43))));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 4,
+ // New array, item copy, array reallocation, second item copy
+ MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
+
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_map_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(
+ cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
+ cbor_move(cbor_build_bool(true))}));
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_map_key_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(
+ cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
+ cbor_move(cbor_build_bool(true))}));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
+ // New map, key copy
+ MALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_map_value_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(
+ cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
+ cbor_move(cbor_build_bool(true))}));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 3,
+ // New map, key copy, value copy
+ MALLOC, MALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_map_add_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(
+ cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
+ cbor_move(cbor_build_bool(true))}));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 4,
+ // New map, key copy, value copy, add
+ MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_map_second_key_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_new_indefinite_map();
+ assert_true(
+ cbor_map_add(item, (struct cbor_pair){cbor_move(cbor_build_uint8(42)),
+ cbor_move(cbor_build_bool(true))}));
+ assert_true(cbor_map_add(
+ item, (struct cbor_pair){cbor_move(cbor_build_uint8(43)),
+ cbor_move(cbor_build_bool(false))}));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 5,
+ // New map, key copy, value copy, add, second key copy
+ MALLOC, MALLOC, MALLOC, REALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_tag_item_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_copy(item)); });
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+static void test_tag_alloc_failure(void **_CBOR_UNUSED(_state)) {
+ item = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
+
+ WITH_MOCK_MALLOC({ assert_null(cbor_copy(item)); }, 2,
+ // Item copy, tag
+ MALLOC, MALLOC_FAIL);
+ assert_size_equal(cbor_refcount(item), 1);
+
+ cbor_decref(&item);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_uints),
+ cmocka_unit_test(test_negints),
+ cmocka_unit_test(test_def_bytestring),
+ cmocka_unit_test(test_indef_bytestring),
+ cmocka_unit_test(test_def_string),
+ cmocka_unit_test(test_indef_string),
+ cmocka_unit_test(test_def_array),
+ cmocka_unit_test(test_indef_array),
+ cmocka_unit_test(test_def_map),
+ cmocka_unit_test(test_indef_map),
+ cmocka_unit_test(test_tag),
+ cmocka_unit_test(test_ctrls),
+ cmocka_unit_test(test_floats),
+ cmocka_unit_test(test_alloc_failure_simple),
+ cmocka_unit_test(test_bytestring_alloc_failure),
+ cmocka_unit_test(test_bytestring_chunk_alloc_failure),
+ cmocka_unit_test(test_bytestring_chunk_append_failure),
+ cmocka_unit_test(test_bytestring_second_chunk_alloc_failure),
+ cmocka_unit_test(test_string_alloc_failure),
+ cmocka_unit_test(test_string_chunk_alloc_failure),
+ cmocka_unit_test(test_string_chunk_append_failure),
+ cmocka_unit_test(test_string_second_chunk_alloc_failure),
+ cmocka_unit_test(test_array_alloc_failure),
+ cmocka_unit_test(test_array_item_alloc_failure),
+ cmocka_unit_test(test_array_push_failure),
+ cmocka_unit_test(test_array_second_item_alloc_failure),
+ cmocka_unit_test(test_map_alloc_failure),
+ cmocka_unit_test(test_map_key_alloc_failure),
+ cmocka_unit_test(test_map_value_alloc_failure),
+ cmocka_unit_test(test_map_add_failure),
+ cmocka_unit_test(test_map_second_key_failure),
+ cmocka_unit_test(test_tag_item_alloc_failure),
+ cmocka_unit_test(test_tag_alloc_failure),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/cpp_linkage_test.cpp b/contrib/libcbor/test/cpp_linkage_test.cpp
new file mode 100644
index 000000000000..a37351f0bc83
--- /dev/null
+++ b/contrib/libcbor/test/cpp_linkage_test.cpp
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <iostream>
+#include "cbor.h"
+
+int main() { std::cout << "Hello from libcbor " << CBOR_VERSION << std::endl; }
diff --git a/contrib/libcbor/test/data/callbacks.cbor b/contrib/libcbor/test/data/callbacks.cbor
new file mode 100644
index 000000000000..6903268bc8d7
--- /dev/null
+++ b/contrib/libcbor/test/data/callbacks.cbor
Binary files differ
diff --git a/contrib/libcbor/test/data/callbacks.diag b/contrib/libcbor/test/data/callbacks.diag
new file mode 100644
index 000000000000..0dd611fa968b
--- /dev/null
+++ b/contrib/libcbor/test/data/callbacks.diag
@@ -0,0 +1 @@
+[1, 257, 67000, 6700067000, -1, -257, -67000, -6700067000, (_ h'01', h'02'), (_ "a", "b"), [_], {"a":"b"}, 0({_}), 1.0, 100000.0, 1.0e+300 , null, undefined, true]
diff --git a/contrib/libcbor/test/data/pretty.cbor b/contrib/libcbor/test/data/pretty.cbor
new file mode 100644
index 000000000000..e580dcd648ff
--- /dev/null
+++ b/contrib/libcbor/test/data/pretty.cbor
@@ -0,0 +1,3 @@
+*** can't parse 101
+0x5B, 0x31, 0x2C, 0x20, 0x2D, 0x31, 0x2C, 0x20, 0x28, 0x5F, 0x20, 0x68, 0x27, 0x30, 0x31, 0x27, 0x2C, 0x20, 0x68, 0x27, 0x30, 0x32, 0x27, 0x29, 0x2C, 0x20, 0x28, 0x5F, 0x20, 0x22, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x22, 0x2C, 0x20, 0x22, 0x62, 0x22, 0x29, 0x2C, 0x20, 0x5B, 0x5F, 0x5D, 0x2C, 0x20, 0x7B, 0x22, 0x61, 0x62, 0x63, 0x22, 0x3A, 0x22, 0x62, 0x61, 0x22, 0x7D, 0x2C, 0x20, 0x30, 0x28, 0x7B, 0x5F, 0x7D, 0x29, 0x2C, 0x20, 0x33, 0x2E, 0x31, 0x34, 0x2C, 0x20, 0x6E, 0x75, 0x6C, 0x6C, 0x2C, 0x20, 0x75, 0x6E, 0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x2C, 0x20, 0x74, 0x72, 0x75, 0x65, 0x5D, 0x0A
+*** Expected [ \t\n\r] at line 2, column 1 (byte 5) after
diff --git a/contrib/libcbor/test/data/pretty.diag b/contrib/libcbor/test/data/pretty.diag
new file mode 100644
index 000000000000..8be1b0cc2a42
--- /dev/null
+++ b/contrib/libcbor/test/data/pretty.diag
@@ -0,0 +1 @@
+[1, -1, (_ h'01', h'02'), (_ "abcdef", "b"), [_], {"abc":"ba"}, 0({_}), 3.14, null, undefined, true]
diff --git a/contrib/libcbor/test/float_ctrl_encoders_test.c b/contrib/libcbor/test/float_ctrl_encoders_test.c
new file mode 100644
index 000000000000..8940106d91d3
--- /dev/null
+++ b/contrib/libcbor/test/float_ctrl_encoders_test.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <math.h>
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_bools(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_bool(false, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF4}), 1);
+ assert_size_equal(1, cbor_encode_bool(true, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF5}), 1);
+}
+
+static void test_null(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_null(buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF6}), 1);
+}
+
+static void test_undef(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_undef(buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF7}), 1);
+}
+
+static void test_break(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_break(buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFF}), 1);
+}
+
+/* Check that encode(decode(buffer)) = buffer for a valid half-float in the
+ * buffer.*/
+static void assert_half_float_codec_identity(void) {
+ unsigned char secondary_buffer[3];
+ struct cbor_load_result res;
+ // Load and check data in buffer
+ cbor_item_t *half_float = cbor_load(buffer, 3, &res);
+ assert_size_equal(res.error.code, CBOR_ERR_NONE);
+ assert_true(cbor_isa_float_ctrl(half_float));
+ assert_true(cbor_is_float(half_float));
+ assert_size_equal(cbor_float_get_width(half_float), CBOR_FLOAT_16);
+ // Encode again and check equality
+ assert_size_equal(3, cbor_encode_half(cbor_float_get_float2(half_float),
+ secondary_buffer, 3));
+ assert_memory_equal(buffer, secondary_buffer, 3);
+ cbor_decref(&half_float);
+}
+
+static void test_half(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(3, cbor_encode_half(1.5f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x3E, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(-0.0f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x80, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(0.0f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(65504.0f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7B, 0xFF}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(0.00006103515625f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x04, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(-4.0f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0xC4, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ /* Smallest representable value */
+ assert_size_equal(3, cbor_encode_half(5.960464477539063e-8f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x01}), 3);
+ assert_half_float_codec_identity();
+
+ /* Smaller than the smallest, approximate magnitude representation */
+ assert_size_equal(3, cbor_encode_half(5.960464477539062e-8f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x01}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(4.172325134277344e-7f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x07}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(6.097555160522461e-5f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x03, 0xff}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(6.100535392761231e-5f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x04, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ /* Smaller than the smallest and even the magnitude cannot be represented,
+ round off to zero */
+ assert_size_equal(3, cbor_encode_half(1e-25f, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(1.1920928955078125e-7, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x00, 0x02}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(-1.1920928955078124e-7, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x80, 0x02}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(INFINITY, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7C, 0x00}), 3);
+ assert_half_float_codec_identity();
+}
+
+static void test_half_special(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(3, cbor_encode_half(NAN, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ // We discard all 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
+ assert_size_equal(3, cbor_encode_half(nanf("2"), buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7E, 0x00}), 3);
+ assert_half_float_codec_identity();
+}
+
+static void test_half_infinity(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(3, cbor_encode_half(INFINITY, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0x7C, 0x00}), 3);
+ assert_half_float_codec_identity();
+
+ assert_size_equal(3, cbor_encode_half(-INFINITY, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xF9, 0xFC, 0x00}), 3);
+ assert_half_float_codec_identity();
+}
+
+static void test_float(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_single(3.4028234663852886e+38, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0x7F, 0xFF, 0xFF}),
+ 5);
+
+ assert_size_equal(5, cbor_encode_single(NAN, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0xC0, 0x00, 0x00}),
+ 5);
+
+#ifndef _WIN32
+ // TODO: https://github.com/PJK/libcbor/issues/271
+ assert_size_equal(5, cbor_encode_single(nanf("3"), buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0xC0, 0x00, 0x03}),
+ 5);
+#endif
+
+ assert_size_equal(5, cbor_encode_single(strtof("Inf", NULL), buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0x7F, 0x80, 0x00, 0x00}),
+ 5);
+
+ assert_size_equal(5, cbor_encode_single(strtof("-Inf", NULL), buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xFA, 0xFF, 0x80, 0x00, 0x00}),
+ 5);
+}
+
+static void test_double(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(9, cbor_encode_double(1.0e+300, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0x7E, 0x37, 0xE4, 0x3C, 0x88, 0x00, 0x75, 0x9C}),
+ 9);
+
+ assert_size_equal(9, cbor_encode_double(nan(""), buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
+ 9);
+
+#ifndef _WIN32
+ // TODO: https://github.com/PJK/libcbor/issues/271
+ assert_size_equal(9, cbor_encode_double(nan("3"), buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}),
+ 9);
+#endif
+
+ assert_size_equal(9, cbor_encode_double(strtod("Inf", NULL), buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
+ 9);
+
+ assert_size_equal(9, cbor_encode_double(strtod("-Inf", NULL), buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0xFB, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
+ 9);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_bools), cmocka_unit_test(test_null),
+ cmocka_unit_test(test_undef), cmocka_unit_test(test_break),
+ cmocka_unit_test(test_half), cmocka_unit_test(test_float),
+ cmocka_unit_test(test_double), cmocka_unit_test(test_half_special),
+ cmocka_unit_test(test_half_infinity),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/float_ctrl_test.c b/contrib/libcbor/test/float_ctrl_test.c
new file mode 100644
index 000000000000..c939486877e7
--- /dev/null
+++ b/contrib/libcbor/test/float_ctrl_test.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <tgmath.h>
+
+#include <cmocka.h>
+
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *float_ctrl;
+struct cbor_load_result res;
+
+static const float eps = 0.00001f;
+
+unsigned char float2_data[] = {0xF9, 0x7B, 0xFF};
+
+static void test_float2(void **_CBOR_UNUSED(_state)) {
+ float_ctrl = cbor_load(float2_data, 3, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_float(float_ctrl));
+ assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_16);
+ assert_true(cbor_float_get_float2(float_ctrl) == 65504.0F);
+ assert_float_equal(cbor_float_get_float(float_ctrl), 65504.0F, eps);
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+}
+
+unsigned char float4_data[] = {0xFA, 0x47, 0xC3, 0x50, 0x00};
+
+static void test_float4(void **_CBOR_UNUSED(_state)) {
+ float_ctrl = cbor_load(float4_data, 5, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_float(float_ctrl));
+ assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_32);
+ assert_true(cbor_float_get_float4(float_ctrl) == 100000.0F);
+ assert_float_equal(cbor_float_get_float(float_ctrl), 100000.0F, eps);
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+}
+
+unsigned char float8_data[] = {0xFB, 0x7E, 0x37, 0xE4, 0x3C,
+ 0x88, 0x00, 0x75, 0x9C};
+
+static void test_float8(void **_CBOR_UNUSED(_state)) {
+ float_ctrl = cbor_load(float8_data, 9, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_float(float_ctrl));
+ assert_true(cbor_float_get_width(float_ctrl) == CBOR_FLOAT_64);
+ // XXX: the cast prevents promotion to 80-bit floats on 32-bit x86
+ assert_true(cbor_float_get_float8(float_ctrl) == (double)1.0e+300);
+ // Not using `assert_double_equal` since CI has an old version of cmocka
+ assert_true(fabs(cbor_float_get_float(float_ctrl) - (double)1.0e+300) < eps);
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+}
+
+unsigned char null_data[] = {0xF6};
+
+static void test_null(void **_CBOR_UNUSED(_state)) {
+ float_ctrl = cbor_load(null_data, 1, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_null(float_ctrl));
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+}
+
+unsigned char undef_data[] = {0xF7};
+
+static void test_undef(void **_CBOR_UNUSED(_state)) {
+ float_ctrl = cbor_load(undef_data, 1, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_undef(float_ctrl));
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+}
+
+unsigned char bool_data[] = {0xF4, 0xF5};
+
+static void test_bool(void **_CBOR_UNUSED(_state)) {
+ _CBOR_TEST_DISABLE_ASSERT({
+ float_ctrl = cbor_load(bool_data, 1, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_bool(float_ctrl));
+ assert_false(cbor_get_bool(float_ctrl));
+ cbor_set_bool(float_ctrl, true);
+ assert_true(cbor_get_bool(float_ctrl));
+ assert_true(isnan(cbor_float_get_float(float_ctrl)));
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+
+ float_ctrl = cbor_load(bool_data + 1, 1, &res);
+ assert_true(cbor_isa_float_ctrl(float_ctrl));
+ assert_true(cbor_is_bool(float_ctrl));
+ assert_true(cbor_get_bool(float_ctrl));
+ cbor_set_bool(float_ctrl, false);
+ assert_false(cbor_get_bool(float_ctrl));
+ assert_true(isnan(cbor_float_get_float(float_ctrl)));
+ cbor_decref(&float_ctrl);
+ assert_null(float_ctrl);
+ });
+}
+
+static void test_float_ctrl_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_ctrl()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_float2()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_float4()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_float8()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_null()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_undef()); });
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_bool(false)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_float2(3.14)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_float4(3.14)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_float8(3.14)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_ctrl(0xAF)); });
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_float2),
+ cmocka_unit_test(test_float4),
+ cmocka_unit_test(test_float8),
+ cmocka_unit_test(test_null),
+ cmocka_unit_test(test_undef),
+ cmocka_unit_test(test_bool),
+ cmocka_unit_test(test_float_ctrl_creation),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/fuzz_test.c b/contrib/libcbor/test/fuzz_test.c
new file mode 100644
index 000000000000..a02ed7ea9287
--- /dev/null
+++ b/contrib/libcbor/test/fuzz_test.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <time.h>
+#include "assertions.h"
+#include "cbor.h"
+
+#ifdef HUGE_FUZZ
+#define ROUNDS 65536ULL
+#define MAXLEN 131072ULL
+#else
+#define ROUNDS 256ULL
+#define MAXLEN 2048ULL
+#endif
+
+#ifdef PRINT_FUZZ
+static void printmem(const unsigned char *ptr, size_t length) {
+ for (size_t i = 0; i < length; i++) printf("%02X", ptr[i]);
+ printf("\n");
+}
+#endif
+
+unsigned seed;
+
+void *mock_malloc(size_t size) {
+ if (size > (1 << 19))
+ return NULL;
+ else
+ return malloc(size);
+}
+
+static void run_round(void) {
+ cbor_item_t *item;
+ struct cbor_load_result res;
+
+ size_t length = rand() % MAXLEN + 1;
+ unsigned char *data = malloc(length);
+ for (size_t i = 0; i < length; i++) {
+ data[i] = rand() % 0xFF;
+ }
+
+#ifdef PRINT_FUZZ
+ printmem(data, length);
+#endif
+
+ item = cbor_load(data, length, &res);
+
+ if (res.error.code == CBOR_ERR_NONE) cbor_decref(&item);
+ /* Otherwise there should be nothing left behind by the decoder */
+
+ free(data);
+}
+
+static void fuzz(void **_CBOR_UNUSED(_state)) {
+ cbor_set_allocs(mock_malloc, realloc, free);
+ printf("Fuzzing %llu rounds of up to %llu bytes with seed %u\n", ROUNDS,
+ MAXLEN, seed);
+ srand(seed);
+
+ for (size_t i = 0; i < ROUNDS; i++) run_round();
+
+ printf("Successfully fuzzed through %llu kB of data\n",
+ (ROUNDS * MAXLEN) / 1024);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc > 1)
+ seed = (unsigned)strtoul(argv[1], NULL, 10);
+ else
+ seed = (unsigned)time(NULL);
+
+ const struct CMUnitTest tests[] = {cmocka_unit_test(fuzz)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/map_encoders_test.c b/contrib/libcbor/test/map_encoders_test.c
new file mode 100644
index 000000000000..bbb5fdc1ad91
--- /dev/null
+++ b/contrib/libcbor/test/map_encoders_test.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_map_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_map_start(1, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xA1}), 1);
+}
+
+static void test_map_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_map_start(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xBA, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_indef_map_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_indef_map_start(buffer, 512));
+ assert_size_equal(0, cbor_encode_indef_map_start(buffer, 0));
+ assert_memory_equal(buffer, ((unsigned char[]){0xBF}), 1);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {cmocka_unit_test(test_embedded_map_start),
+ cmocka_unit_test(test_map_start),
+ cmocka_unit_test(test_indef_map_start)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/map_test.c b/contrib/libcbor/test/map_test.c
new file mode 100644
index 000000000000..11bd7a8d7242
--- /dev/null
+++ b/contrib/libcbor/test/map_test.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <cmocka.h>
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *map;
+struct cbor_load_result res;
+
+unsigned char empty_map[] = {0xA0};
+
+static void test_empty_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(empty_map, 1, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_size(map) == 0);
+ assert_true(res.read == 1);
+ assert_size_equal(cbor_map_allocated(map), 0);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+unsigned char simple_map[] = {0xA2, 0x01, 0x02, 0x03, 0x04};
+
+/* {1: 2, 3: 4} */
+static void test_simple_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(simple_map, 5, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_definite(map));
+ assert_true(cbor_map_size(map) == 2);
+ assert_true(res.read == 5);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_uint8(handle[0].key, 1);
+ assert_uint8(handle[0].value, 2);
+ assert_uint8(handle[1].key, 3);
+ assert_uint8(handle[1].value, 4);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+unsigned char simple_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
+
+/* {_ 1: 2, 3: 4} */
+static void test_indef_simple_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(simple_indef_map, 6, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_indefinite(map));
+ assert_true(cbor_map_size(map) == 2);
+ assert_true(res.read == 6);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_uint8(handle[0].key, 1);
+ assert_uint8(handle[0].value, 2);
+ assert_uint8(handle[1].key, 3);
+ assert_uint8(handle[1].value, 4);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+//{
+// "glossary": {
+// "title": "example glossary"
+// }
+//}
+unsigned char def_nested_map[] = {
+ 0xA1, 0x68, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79, 0xA1, 0x65,
+ 0x74, 0x69, 0x74, 0x6C, 0x65, 0x70, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C,
+ 0x65, 0x20, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79};
+
+static void test_def_nested_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(def_nested_map, 34, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_definite(map));
+ assert_true(cbor_map_size(map) == 1);
+ assert_true(res.read == 34);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
+ assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_MAP);
+ struct cbor_pair *inner_handle = cbor_map_handle(handle[0].value);
+ assert_true(cbor_typeof(inner_handle[0].key) == CBOR_TYPE_STRING);
+ assert_true(cbor_typeof(inner_handle[0].value) == CBOR_TYPE_STRING);
+ assert_memory_equal(cbor_string_handle(inner_handle[0].value),
+ "example glossary", strlen("example glossary"));
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+unsigned char streamed_key_map[] = {0xA1, 0x7F, 0x61, 0x61,
+ 0x61, 0x62, 0xFF, 0xA0};
+
+/* '{ (_"a" "b"): {}}' */
+static void test_streamed_key_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(streamed_key_map, 8, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_definite(map));
+ assert_true(cbor_map_size(map) == 1);
+ assert_true(res.read == 8);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
+ assert_true(cbor_string_is_indefinite(handle[0].key));
+ assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
+ assert_true(cbor_isa_map(handle[0].value));
+ assert_size_equal(cbor_map_size(handle[0].value), 0);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+unsigned char streamed_kv_map[] = {0xA1, 0x7F, 0x61, 0x61, 0x61, 0x62, 0xFF,
+ 0x7F, 0x61, 0x63, 0x61, 0x64, 0xFF};
+
+/* '{ (_"a" "b"): (_"c", "d")}' */
+static void test_streamed_kv_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(streamed_kv_map, 13, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_definite(map));
+ assert_size_equal(cbor_map_size(map), 1);
+ assert_size_equal(res.read, 13);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
+ assert_true(cbor_string_is_indefinite(handle[0].key));
+ assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
+ assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
+ assert_true(cbor_string_is_indefinite(handle[0].value));
+ assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
+ assert_memory_equal(
+ cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
+ 1);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+unsigned char streamed_streamed_kv_map[] = {0xBF, 0x7F, 0x61, 0x61, 0x61,
+ 0x62, 0xFF, 0x7F, 0x61, 0x63,
+ 0x61, 0x64, 0xFF, 0xFF};
+
+/* '{_ (_"a" "b"): (_"c", "d")}' */
+static void test_streamed_streamed_kv_map(void **_CBOR_UNUSED(_state)) {
+ map = cbor_load(streamed_streamed_kv_map, 14, &res);
+ assert_non_null(map);
+ assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
+ assert_true(cbor_isa_map(map));
+ assert_true(cbor_map_is_indefinite(map));
+ assert_size_equal(cbor_map_size(map), 1);
+ assert_size_equal(res.read, 14);
+ struct cbor_pair *handle = cbor_map_handle(map);
+ assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
+ assert_true(cbor_string_is_indefinite(handle[0].key));
+ assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
+ assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
+ assert_true(cbor_string_is_indefinite(handle[0].value));
+ assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
+ assert_memory_equal(
+ cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
+ 1);
+ cbor_decref(&map);
+ assert_null(map);
+}
+
+static void test_map_add_full(void **_CBOR_UNUSED(_state)) {
+ map = cbor_new_definite_map(0);
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
+
+ cbor_decref(&map);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_map_add_too_big_to_realloc(void **_CBOR_UNUSED(_state)) {
+ map = cbor_new_indefinite_map();
+ struct _cbor_map_metadata *metadata =
+ (struct _cbor_map_metadata *)&map->metadata;
+ // Pretend we already have a huge memory block
+ metadata->allocated = SIZE_MAX;
+ metadata->end_ptr = SIZE_MAX;
+ cbor_item_t *one = cbor_build_uint8(1);
+ cbor_item_t *two = cbor_build_uint8(2);
+
+ assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
+
+ metadata->allocated = 0;
+ metadata->end_ptr = 0;
+ cbor_decref(&map);
+ cbor_decref(&one);
+ cbor_decref(&two);
+}
+
+static void test_map_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_map(42)); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_map(42)); }, 2, MALLOC,
+ MALLOC_FAIL);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_map()); });
+}
+
+static void test_map_add(void **_CBOR_UNUSED(_state)) {
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *map = cbor_new_indefinite_map();
+ cbor_item_t *key = cbor_build_uint8(0);
+ cbor_item_t *value = cbor_build_bool(true);
+
+ assert_false(
+ cbor_map_add(map, (struct cbor_pair){.key = key, .value = value}));
+ assert_size_equal(cbor_map_allocated(map), 0);
+ assert_null(map->data);
+
+ cbor_decref(&map);
+ cbor_decref(&key);
+ cbor_decref(&value);
+ },
+ 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+static unsigned char test_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
+static void test_indef_map_decode(void **_CBOR_UNUSED(_state)) {
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *map;
+ struct cbor_load_result res;
+ map = cbor_load(test_indef_map, 6, &res);
+
+ assert_null(map);
+ assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
+ },
+ 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_empty_map),
+ cmocka_unit_test(test_simple_map),
+ cmocka_unit_test(test_indef_simple_map),
+ cmocka_unit_test(test_def_nested_map),
+ cmocka_unit_test(test_streamed_key_map),
+ cmocka_unit_test(test_streamed_kv_map),
+ cmocka_unit_test(test_streamed_streamed_kv_map),
+ cmocka_unit_test(test_map_add_full),
+ cmocka_unit_test(test_map_add_too_big_to_realloc),
+ cmocka_unit_test(test_map_creation),
+ cmocka_unit_test(test_map_add),
+ cmocka_unit_test(test_indef_map_decode),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/memory_utils_test.c b/contrib/libcbor/test/memory_utils_test.c
new file mode 100644
index 000000000000..6cf07c7da934
--- /dev/null
+++ b/contrib/libcbor/test/memory_utils_test.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "cbor/internal/memory_utils.h"
+#include <string.h>
+#include "assertions.h"
+
+static void test_safe_multiply(void **_CBOR_UNUSED(_state)) {
+ assert_true(_cbor_safe_to_multiply(1, 1));
+ assert_true(_cbor_safe_to_multiply(SIZE_MAX, 0));
+ assert_true(_cbor_safe_to_multiply(SIZE_MAX, 1));
+ assert_false(_cbor_safe_to_multiply(SIZE_MAX, 2));
+ assert_false(_cbor_safe_to_multiply(SIZE_MAX, SIZE_MAX));
+}
+
+static void test_safe_add(void **_CBOR_UNUSED(_state)) {
+ assert_true(_cbor_safe_to_add(1, 1));
+ assert_true(_cbor_safe_to_add(SIZE_MAX - 1, 1));
+ assert_true(_cbor_safe_to_add(SIZE_MAX, 0));
+ assert_false(_cbor_safe_to_add(SIZE_MAX, 1));
+ assert_false(_cbor_safe_to_add(SIZE_MAX, 2));
+ assert_false(_cbor_safe_to_add(SIZE_MAX, SIZE_MAX));
+ assert_false(_cbor_safe_to_add(SIZE_MAX - 1, SIZE_MAX));
+ assert_false(_cbor_safe_to_add(SIZE_MAX - 1, SIZE_MAX - 1));
+}
+
+static void test_safe_signalling_add(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(_cbor_safe_signaling_add(1, 2), 3);
+ assert_size_equal(_cbor_safe_signaling_add(0, 1), 0);
+ assert_size_equal(_cbor_safe_signaling_add(0, SIZE_MAX), 0);
+ assert_size_equal(_cbor_safe_signaling_add(1, SIZE_MAX), 0);
+ assert_size_equal(_cbor_safe_signaling_add(1, SIZE_MAX - 1), SIZE_MAX);
+}
+
+static void test_realloc_multiple(void **_CBOR_UNUSED(_state)) {
+ unsigned char *data = malloc(1);
+ data[0] = 0x2a;
+
+ data = _cbor_realloc_multiple(data, /*item_size=*/1, /*item_count=*/10);
+ assert_size_equal(data[0], 0x2a);
+ data[9] = 0x2b; // Sanitizer will stop us if not ok
+ free(data);
+
+ assert_null(_cbor_realloc_multiple(NULL, SIZE_MAX, 2));
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_safe_multiply),
+ cmocka_unit_test(test_safe_add),
+ cmocka_unit_test(test_safe_signalling_add),
+ cmocka_unit_test(test_realloc_multiple),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/negint_encoders_test.c b/contrib/libcbor/test/negint_encoders_test.c
new file mode 100644
index 000000000000..e9230fbe42ae
--- /dev/null
+++ b/contrib/libcbor/test/negint_encoders_test.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_negint8(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_negint8(14, buffer, 512));
+ assert_memory_equal(buffer, (unsigned char[]){0x2E}, 1);
+}
+
+static void test_negint8(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_negint8(180, buffer, 1));
+ assert_size_equal(2, cbor_encode_negint8(255, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x38, 0xFF}), 2);
+}
+
+static void test_negint16(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_negint16(1000, buffer, 2));
+ assert_size_equal(3, cbor_encode_negint16(1000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x39, 0x03, 0xE8}), 3);
+}
+
+static void test_negint32(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_negint32(1000000, buffer, 4));
+ assert_size_equal(5, cbor_encode_negint32(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x3A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_negint64(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0,
+ cbor_encode_negint64(18446744073709551615ULL, buffer, 8));
+ assert_size_equal(9,
+ cbor_encode_negint64(18446744073709551615ULL, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}),
+ 9);
+}
+
+static void test_unspecified(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(9,
+ cbor_encode_negint(18446744073709551615ULL, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}),
+ 9);
+ assert_size_equal(5, cbor_encode_negint(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x3A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+ assert_size_equal(3, cbor_encode_negint(1000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x39, 0x03, 0xE8}), 3);
+ assert_size_equal(2, cbor_encode_negint(255, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x38, 0xFF}), 2);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {cmocka_unit_test(test_embedded_negint8),
+ cmocka_unit_test(test_negint8),
+ cmocka_unit_test(test_negint16),
+ cmocka_unit_test(test_negint32),
+ cmocka_unit_test(test_negint64),
+ cmocka_unit_test(test_unspecified)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/negint_test.c b/contrib/libcbor/test/negint_test.c
new file mode 100644
index 000000000000..66e7445b7f23
--- /dev/null
+++ b/contrib/libcbor/test/negint_test.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *number;
+struct cbor_load_result res;
+
+unsigned char data1[] = {0x22, 0xFF};
+unsigned char data2[] = {0x38, 0xFF, 0xFF};
+unsigned char data3[] = {0x39, 0x01, 0xf4, 0xFF};
+unsigned char data4[] = {0x3a, 0xa5, 0xf7, 0x02, 0xb3, 0xFF};
+unsigned char data5[] = {0x3b, 0xa5, 0xf7, 0x02, 0xb3,
+ 0xa5, 0xf7, 0x02, 0xb3, 0xFF};
+
+static void test_very_short_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data1, 2, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_NEGINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_8);
+ assert_false(cbor_isa_uint(number));
+ assert_true(cbor_isa_negint(number));
+ assert_true(cbor_get_uint8(number) == 2);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 1);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_short_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data2, 3, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_NEGINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_8);
+ assert_false(cbor_isa_uint(number));
+ assert_true(cbor_isa_negint(number));
+ assert_true(cbor_get_uint8(number) == 255);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 2);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_half_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data3, 5, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_NEGINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_16);
+ assert_false(cbor_isa_uint(number));
+ assert_true(cbor_isa_negint(number));
+ assert_true(cbor_get_uint16(number) == 500);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 3);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data4, 6, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_NEGINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_32);
+ assert_false(cbor_isa_uint(number));
+ assert_true(cbor_isa_negint(number));
+ assert_true(cbor_get_uint32(number) == 2784428723);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 5);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_long_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data5, 10, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_NEGINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_64);
+ assert_false(cbor_isa_uint(number));
+ assert_true(cbor_isa_negint(number));
+ assert_true(cbor_get_uint64(number) == 11959030306112471731ULL);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 9);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_int_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int8()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int16()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int32()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int64()); });
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_negint8(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_negint16(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_negint32(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_negint64(0xFF)); });
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_very_short_int),
+ cmocka_unit_test(test_short_int),
+ cmocka_unit_test(test_half_int),
+ cmocka_unit_test(test_int),
+ cmocka_unit_test(test_long_int),
+ cmocka_unit_test(test_int_creation),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/pretty_printer_test.c b/contrib/libcbor/test/pretty_printer_test.c
new file mode 100644
index 000000000000..6ea40c0e7ce2
--- /dev/null
+++ b/contrib/libcbor/test/pretty_printer_test.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "assertions.h"
+#include "cbor.h"
+
+void assert_describe_result(cbor_item_t *item, char *expected_result) {
+#if CBOR_PRETTY_PRINTER
+ // We know the expected size based on `expected_result`, but read everything
+ // in order to get the full actual output in a useful error message.
+ const size_t buffer_size = 512;
+ FILE *outfile = tmpfile();
+ cbor_describe(item, outfile);
+ rewind(outfile);
+ // Treat string as null-terminated since cmocka doesn't have asserts
+ // for explicit length strings.
+ char *output = malloc(buffer_size);
+ assert_non_null(output);
+ size_t output_size = fread(output, sizeof(char), buffer_size, outfile);
+ output[output_size] = '\0';
+ assert_string_equal(output, expected_result);
+ assert_true(feof(outfile));
+ free(output);
+ fclose(outfile);
+#endif
+}
+
+static void test_uint(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_uint8(42);
+ assert_describe_result(item, "[CBOR_TYPE_UINT] Width: 1B, Value: 42\n");
+ cbor_decref(&item);
+}
+
+static void test_negint(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_negint16(40);
+ assert_describe_result(item,
+ "[CBOR_TYPE_NEGINT] Width: 2B, Value: -40 - 1\n");
+ cbor_decref(&item);
+}
+
+static void test_definite_bytestring(void **_CBOR_UNUSED(_state)) {
+ unsigned char data[] = {0x01, 0x02, 0x03};
+ cbor_item_t *item = cbor_build_bytestring(data, 3);
+ assert_describe_result(item,
+ "[CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
+ " 010203\n");
+ cbor_decref(&item);
+}
+
+static void test_indefinite_bytestring(void **_CBOR_UNUSED(_state)) {
+ unsigned char data[] = {0x01, 0x02, 0x03};
+ cbor_item_t *item = cbor_new_indefinite_bytestring();
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring(data, 3))));
+ assert_true(cbor_bytestring_add_chunk(
+ item, cbor_move(cbor_build_bytestring(data, 2))));
+ assert_describe_result(
+ item,
+ "[CBOR_TYPE_BYTESTRING] Indefinite, Chunks: 2, Chunk data:\n"
+ " [CBOR_TYPE_BYTESTRING] Definite, Length: 3B, Data:\n"
+ " 010203\n"
+ " [CBOR_TYPE_BYTESTRING] Definite, Length: 2B, Data:\n"
+ " 0102\n");
+ cbor_decref(&item);
+}
+
+static void test_definite_string(void **_CBOR_UNUSED(_state)) {
+ char *string = "Hello!";
+ cbor_item_t *item = cbor_build_string(string);
+ assert_describe_result(
+ item,
+ "[CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
+ " Hello!\n");
+ cbor_decref(&item);
+}
+
+static void test_indefinite_string(void **_CBOR_UNUSED(_state)) {
+ char *string = "Hello!";
+ cbor_item_t *item = cbor_new_indefinite_string();
+ assert_true(
+ cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
+ assert_true(
+ cbor_string_add_chunk(item, cbor_move(cbor_build_string(string))));
+ assert_describe_result(
+ item,
+ "[CBOR_TYPE_STRING] Indefinite, Chunks: 2, Chunk data:\n"
+ " [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
+ " Hello!\n"
+ " [CBOR_TYPE_STRING] Definite, Length: 6B, Codepoints: 6, Data:\n"
+ " Hello!\n");
+ cbor_decref(&item);
+}
+
+static void test_multibyte_string(void **_CBOR_UNUSED(_state)) {
+ // "Štěstíčko" in UTF-8
+ char *string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
+ cbor_item_t *item = cbor_build_string(string);
+ assert_describe_result(
+ item,
+ "[CBOR_TYPE_STRING] Definite, Length: 13B, Codepoints: 9, Data:\n"
+ " \xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko\n");
+ cbor_decref(&item);
+}
+
+static void test_definite_array(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_array(2);
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
+ assert_describe_result(item,
+ "[CBOR_TYPE_ARRAY] Definite, Size: 2, Contents:\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
+ cbor_decref(&item);
+}
+
+static void test_indefinite_array(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(1))));
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_uint8(2))));
+ assert_describe_result(item,
+ "[CBOR_TYPE_ARRAY] Indefinite, Size: 2, Contents:\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
+ cbor_decref(&item);
+}
+
+static void test_definite_map(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_definite_map(1);
+ assert_true(cbor_map_add(
+ item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
+ .value = cbor_move(cbor_build_uint8(2))}));
+ assert_describe_result(item,
+ "[CBOR_TYPE_MAP] Definite, Size: 1, Contents:\n"
+ " Map entry 0\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
+ cbor_decref(&item);
+}
+
+static void test_indefinite_map(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_map();
+ assert_true(cbor_map_add(
+ item, (struct cbor_pair){.key = cbor_move(cbor_build_uint8(1)),
+ .value = cbor_move(cbor_build_uint8(2))}));
+ assert_describe_result(item,
+ "[CBOR_TYPE_MAP] Indefinite, Size: 1, Contents:\n"
+ " Map entry 0\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 2\n");
+ cbor_decref(&item);
+}
+
+static void test_tag(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_build_tag(42, cbor_move(cbor_build_uint8(1)));
+ assert_describe_result(item,
+ "[CBOR_TYPE_TAG] Value: 42\n"
+ " [CBOR_TYPE_UINT] Width: 1B, Value: 1\n");
+ cbor_decref(&item);
+}
+
+static void test_floats(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *item = cbor_new_indefinite_array();
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_bool(true))));
+ assert_true(
+ cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_UNDEF))));
+ assert_true(
+ cbor_array_push(item, cbor_move(cbor_build_ctrl(CBOR_CTRL_NULL))));
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_ctrl(24))));
+ assert_true(cbor_array_push(item, cbor_move(cbor_build_float4(3.14f))));
+ assert_describe_result(
+ item,
+ "[CBOR_TYPE_ARRAY] Indefinite, Size: 5, Contents:\n"
+ " [CBOR_TYPE_FLOAT_CTRL] Bool: true\n"
+ " [CBOR_TYPE_FLOAT_CTRL] Undefined\n"
+ " [CBOR_TYPE_FLOAT_CTRL] Null\n"
+ " [CBOR_TYPE_FLOAT_CTRL] Simple value: 24\n"
+ " [CBOR_TYPE_FLOAT_CTRL] Width: 4B, Value: 3.140000\n");
+ cbor_decref(&item);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_uint),
+ cmocka_unit_test(test_negint),
+ cmocka_unit_test(test_definite_bytestring),
+ cmocka_unit_test(test_indefinite_bytestring),
+ cmocka_unit_test(test_definite_string),
+ cmocka_unit_test(test_indefinite_string),
+ cmocka_unit_test(test_multibyte_string),
+ cmocka_unit_test(test_definite_array),
+ cmocka_unit_test(test_indefinite_array),
+ cmocka_unit_test(test_definite_map),
+ cmocka_unit_test(test_indefinite_map),
+ cmocka_unit_test(test_tag),
+ cmocka_unit_test(test_floats),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/stack_over_limit_test.c b/contrib/libcbor/test/stack_over_limit_test.c
new file mode 100644
index 000000000000..73b6bdc2567b
--- /dev/null
+++ b/contrib/libcbor/test/stack_over_limit_test.c
@@ -0,0 +1,28 @@
+#include "assertions.h"
+#include "cbor.h"
+
+static size_t generate_overflow_data(unsigned char **overflow_data) {
+ int i;
+ *overflow_data = (unsigned char *)malloc(CBOR_MAX_STACK_SIZE + 3);
+ for (i = 0; i < CBOR_MAX_STACK_SIZE + 1; i++) {
+ (*overflow_data)[i] = 0xC2; // tag of positive bignum
+ }
+ (*overflow_data)[CBOR_MAX_STACK_SIZE + 1] = 0x41; // bytestring of length 1
+ (*overflow_data)[CBOR_MAX_STACK_SIZE + 2] = 0x01; // a bignum of value 1
+ return CBOR_MAX_STACK_SIZE + 3;
+}
+
+static void test_stack_over_limit(void **_CBOR_UNUSED(_state)) {
+ unsigned char *overflow_data;
+ size_t overflow_data_len;
+ struct cbor_load_result res;
+ overflow_data_len = generate_overflow_data(&overflow_data);
+ assert_null(cbor_load(overflow_data, overflow_data_len, &res));
+ free(overflow_data);
+ assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {cmocka_unit_test(test_stack_over_limit)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/stream_expectations.c b/contrib/libcbor/test/stream_expectations.c
new file mode 100644
index 000000000000..3592c9625da5
--- /dev/null
+++ b/contrib/libcbor/test/stream_expectations.c
@@ -0,0 +1,328 @@
+#include "stream_expectations.h"
+
+struct test_assertion assertions_queue[MAX_QUEUE_ITEMS];
+int queue_size = 0;
+int current_expectation = 0;
+
+int clean_up_stream_assertions(void **state) {
+ if (queue_size != current_expectation) {
+ return 1; // We have not matched all expectations correctly
+ }
+ queue_size = current_expectation = 0;
+ free(*state);
+ return 0;
+}
+
+/* Callbacks */
+struct test_assertion current(void) {
+ return assertions_queue[current_expectation];
+}
+
+/* Assertions builders and matcher callbacks */
+
+void assert_uint8_eq(uint8_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ UINT8_EQ, (union test_expectation_data){.int8 = actual}};
+}
+
+void uint8_callback(void *_CBOR_UNUSED(_context), uint8_t actual) {
+ assert_true(current().expectation == UINT8_EQ);
+ assert_true(current().data.int8 == actual);
+ current_expectation++;
+}
+
+void assert_uint16_eq(uint16_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ UINT16_EQ, (union test_expectation_data){.int16 = actual}};
+}
+
+void uint16_callback(void *_CBOR_UNUSED(_context), uint16_t actual) {
+ assert_true(current().expectation == UINT16_EQ);
+ assert_true(current().data.int16 == actual);
+ current_expectation++;
+}
+
+void assert_uint32_eq(uint32_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ UINT32_EQ, (union test_expectation_data){.int32 = actual}};
+}
+
+void uint32_callback(void *_CBOR_UNUSED(_context), uint32_t actual) {
+ assert_true(current().expectation == UINT32_EQ);
+ assert_true(current().data.int32 == actual);
+ current_expectation++;
+}
+
+void assert_uint64_eq(uint64_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ UINT64_EQ, (union test_expectation_data){.int64 = actual}};
+}
+
+void uint64_callback(void *_CBOR_UNUSED(_context), uint64_t actual) {
+ assert_true(current().expectation == UINT64_EQ);
+ assert_true(current().data.int64 == actual);
+ current_expectation++;
+}
+
+void assert_negint8_eq(uint8_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ NEGINT8_EQ, (union test_expectation_data){.int8 = actual}};
+}
+
+void negint8_callback(void *_CBOR_UNUSED(_context), uint8_t actual) {
+ assert_true(current().expectation == NEGINT8_EQ);
+ assert_true(current().data.int8 == actual);
+ current_expectation++;
+}
+
+void assert_negint16_eq(uint16_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ NEGINT16_EQ, (union test_expectation_data){.int16 = actual}};
+}
+
+void negint16_callback(void *_CBOR_UNUSED(_context), uint16_t actual) {
+ assert_true(current().expectation == NEGINT16_EQ);
+ assert_true(current().data.int16 == actual);
+ current_expectation++;
+}
+
+void assert_negint32_eq(uint32_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ NEGINT32_EQ, (union test_expectation_data){.int32 = actual}};
+}
+
+void negint32_callback(void *_CBOR_UNUSED(_context), uint32_t actual) {
+ assert_true(current().expectation == NEGINT32_EQ);
+ assert_true(current().data.int32 == actual);
+ current_expectation++;
+}
+
+void assert_negint64_eq(uint64_t actual) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ NEGINT64_EQ, (union test_expectation_data){.int64 = actual}};
+}
+
+void negint64_callback(void *_CBOR_UNUSED(_context), uint64_t actual) {
+ assert_true(current().expectation == NEGINT64_EQ);
+ assert_true(current().data.int64 == actual);
+ current_expectation++;
+}
+
+void assert_bstring_mem_eq(cbor_data address, size_t length) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ BSTRING_MEM_EQ,
+ (union test_expectation_data){.string = {address, length}}};
+}
+
+void byte_string_callback(void *_CBOR_UNUSED(_context), cbor_data address,
+ uint64_t length) {
+ assert_true(current().expectation == BSTRING_MEM_EQ);
+ assert_true(current().data.string.address == address);
+ assert_true(current().data.string.length == length);
+ current_expectation++;
+}
+
+void assert_bstring_indef_start(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = BSTRING_INDEF_START};
+}
+
+void byte_string_start_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == BSTRING_INDEF_START);
+ current_expectation++;
+}
+
+void assert_string_mem_eq(cbor_data address, size_t length) {
+ assertions_queue[queue_size++] = (struct test_assertion){
+ STRING_MEM_EQ,
+ (union test_expectation_data){.string = {address, length}}};
+}
+
+void string_callback(void *_CBOR_UNUSED(_context), cbor_data address,
+ uint64_t length) {
+ assert_true(current().expectation == STRING_MEM_EQ);
+ assert_true(current().data.string.address == address);
+ assert_true(current().data.string.length == length);
+ current_expectation++;
+}
+
+void assert_string_indef_start(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = STRING_INDEF_START};
+}
+
+void string_start_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == STRING_INDEF_START);
+ current_expectation++;
+}
+
+void assert_indef_break(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = INDEF_BREAK};
+}
+
+void indef_break_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == INDEF_BREAK);
+ current_expectation++;
+}
+
+void assert_array_start(size_t length) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){ARRAY_START, {.length = length}};
+}
+
+void array_start_callback(void *_CBOR_UNUSED(_context), uint64_t length) {
+ assert_true(current().expectation == ARRAY_START);
+ assert_true(current().data.length == length);
+ current_expectation++;
+}
+
+void assert_indef_array_start(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = ARRAY_INDEF_START};
+}
+
+void indef_array_start_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == ARRAY_INDEF_START);
+ current_expectation++;
+}
+
+void assert_map_start(size_t length) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){MAP_START, {.length = length}};
+}
+
+void map_start_callback(void *_CBOR_UNUSED(_context), uint64_t length) {
+ assert_true(current().expectation == MAP_START);
+ assert_true(current().data.length == length);
+ current_expectation++;
+}
+
+void assert_indef_map_start(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = MAP_INDEF_START};
+}
+
+void indef_map_start_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == MAP_INDEF_START);
+ current_expectation++;
+}
+
+void assert_tag_eq(uint64_t value) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){TAG_EQ, {.int64 = value}};
+}
+
+void tag_callback(void *_CBOR_UNUSED(_context), uint64_t value) {
+ assert_true(current().expectation == TAG_EQ);
+ assert_true(current().data.int64 == value);
+ current_expectation++;
+}
+
+void assert_half(float value) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){HALF_EQ, {.float2 = value}};
+}
+
+void half_callback(void *_CBOR_UNUSED(_context), float actual) {
+ assert_true(current().expectation == HALF_EQ);
+ assert_true(current().data.float2 == actual);
+ current_expectation++;
+}
+
+void assert_float(float value) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){FLOAT_EQ, {.float4 = value}};
+}
+
+void float_callback(void *_CBOR_UNUSED(_context), float actual) {
+ assert_true(current().expectation == FLOAT_EQ);
+ assert_true(current().data.float4 == actual);
+ current_expectation++;
+}
+
+void assert_double(double value) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){DOUBLE_EQ, {.float8 = value}};
+}
+
+void double_callback(void *_CBOR_UNUSED(_context), double actual) {
+ assert_true(current().expectation == DOUBLE_EQ);
+ assert_true(current().data.float8 == actual);
+ current_expectation++;
+}
+
+void assert_bool(bool value) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){BOOL_EQ, {.boolean = value}};
+}
+
+void assert_nil(void) {
+ assertions_queue[queue_size++] = (struct test_assertion){.expectation = NIL};
+}
+
+void assert_undef(void) {
+ assertions_queue[queue_size++] =
+ (struct test_assertion){.expectation = UNDEF};
+}
+
+void bool_callback(void *_CBOR_UNUSED(_context), bool actual) {
+ assert_true(current().expectation == BOOL_EQ);
+ assert_true(current().data.boolean == actual);
+ current_expectation++;
+}
+
+void null_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == NIL);
+ current_expectation++;
+}
+
+void undef_callback(void *_CBOR_UNUSED(_context)) {
+ assert_true(current().expectation == UNDEF);
+ current_expectation++;
+}
+
+const struct cbor_callbacks asserting_callbacks = {
+ .uint8 = &uint8_callback,
+ .uint16 = &uint16_callback,
+ .uint32 = &uint32_callback,
+ .uint64 = &uint64_callback,
+
+ .negint8 = &negint8_callback,
+ .negint16 = &negint16_callback,
+ .negint32 = &negint32_callback,
+ .negint64 = &negint64_callback,
+
+ .byte_string = &byte_string_callback,
+ .byte_string_start = &byte_string_start_callback,
+
+ .string = &string_callback,
+ .string_start = &string_start_callback,
+
+ .array_start = &array_start_callback,
+ .indef_array_start = &indef_array_start_callback,
+
+ .map_start = &map_start_callback,
+ .indef_map_start = &indef_map_start_callback,
+
+ .tag = &tag_callback,
+
+ .float2 = &half_callback,
+ .float4 = &float_callback,
+ .float8 = &double_callback,
+
+ .undefined = &undef_callback,
+ .boolean = &bool_callback,
+ .null = &null_callback,
+ .indef_break = &indef_break_callback};
+
+struct cbor_decoder_result decode(cbor_data source, size_t source_size) {
+ int last_expectation = current_expectation;
+ struct cbor_decoder_result result =
+ cbor_stream_decode(source, source_size, &asserting_callbacks, NULL);
+ if (result.status == CBOR_DECODER_FINISHED) {
+ // Check that we have matched an expectation from the queue
+ assert_true(last_expectation + 1 == current_expectation);
+ }
+ return result;
+}
diff --git a/contrib/libcbor/test/stream_expectations.h b/contrib/libcbor/test/stream_expectations.h
new file mode 100644
index 000000000000..bfc58e97cd9f
--- /dev/null
+++ b/contrib/libcbor/test/stream_expectations.h
@@ -0,0 +1,152 @@
+#ifndef STREAM_EXPECTATIONS_H_
+#define STREAM_EXPECTATIONS_H_
+
+#include "assertions.h"
+#include "cbor.h"
+
+#define MAX_QUEUE_ITEMS 30
+
+// Utilities to test `cbor_stream_decode`. See `cbor_stream_decode_test.cc`.
+//
+// Usage:
+// - The `assert_` helpers build a queue of `test_assertion`s
+// (`assertions_queue` in the implementation file), specifying
+// - Which callback is expected (`test_expectation`)
+// - And what is the expected argument value (if applicable,
+// `test_expectation_data`)
+// - `decode` will invoke `cbor_stream_decode` (test subject)
+// - `cbor_stream_decode` will invoke one of the `_callback` functions, which
+// will check the passed data against the `assertions_queue`
+
+enum test_expectation {
+ UINT8_EQ,
+ UINT16_EQ,
+ UINT32_EQ,
+ UINT64_EQ,
+
+ NEGINT8_EQ,
+ NEGINT16_EQ,
+ NEGINT32_EQ,
+ NEGINT64_EQ,
+
+ // Matches length and memory address for definite strings
+ BSTRING_MEM_EQ,
+ BSTRING_INDEF_START,
+
+ STRING_MEM_EQ,
+ STRING_INDEF_START,
+
+ ARRAY_START, /* Definite arrays only */
+ ARRAY_INDEF_START,
+
+ MAP_START, /* Definite maps only */
+ MAP_INDEF_START,
+
+ TAG_EQ,
+
+ HALF_EQ,
+ FLOAT_EQ,
+ DOUBLE_EQ,
+ BOOL_EQ,
+ NIL,
+ UNDEF,
+ INDEF_BREAK /* Expect "Break" */
+};
+
+union test_expectation_data {
+ uint8_t int8;
+ uint16_t int16;
+ uint32_t int32;
+ uint64_t int64;
+ struct string {
+ cbor_data address;
+ size_t length;
+ } string;
+ size_t length;
+ float float2;
+ float float4;
+ double float8;
+ bool boolean;
+};
+
+struct test_assertion {
+ enum test_expectation expectation;
+ union test_expectation_data data;
+};
+
+/* Test harness -- calls `cbor_stream_decode` and checks assertions */
+struct cbor_decoder_result decode(cbor_data, size_t);
+
+/* Verify all assertions were applied and clean up */
+int clean_up_stream_assertions(void **);
+
+/* Assertions builders */
+void assert_uint8_eq(uint8_t);
+void assert_uint16_eq(uint16_t);
+void assert_uint32_eq(uint32_t);
+void assert_uint64_eq(uint64_t);
+
+void assert_negint8_eq(uint8_t);
+void assert_negint16_eq(uint16_t);
+void assert_negint32_eq(uint32_t);
+void assert_negint64_eq(uint64_t);
+
+void assert_bstring_mem_eq(cbor_data, size_t);
+void assert_bstring_indef_start(void);
+
+void assert_string_mem_eq(cbor_data, size_t);
+void assert_string_indef_start(void);
+
+void assert_array_start(size_t);
+void assert_indef_array_start(void);
+
+void assert_map_start(size_t);
+void assert_indef_map_start(void);
+
+void assert_tag_eq(uint64_t);
+
+void assert_half(float);
+void assert_float(float);
+void assert_double(double);
+
+void assert_bool(bool);
+void assert_nil(void); /* assert_null already exists */
+void assert_undef(void);
+
+void assert_indef_break(void);
+
+/* Assertions verifying callbacks */
+void uint8_callback(void *, uint8_t);
+void uint16_callback(void *, uint16_t);
+void uint32_callback(void *, uint32_t);
+void uint64_callback(void *, uint64_t);
+
+void negint8_callback(void *, uint8_t);
+void negint16_callback(void *, uint16_t);
+void negint32_callback(void *, uint32_t);
+void negint64_callback(void *, uint64_t);
+
+void byte_string_callback(void *, cbor_data, uint64_t);
+void byte_string_start_callback(void *);
+
+void string_callback(void *, cbor_data, uint64_t);
+void string_start_callback(void *);
+
+void array_start_callback(void *, uint64_t);
+void indef_array_start_callback(void *);
+
+void map_start_callback(void *, uint64_t);
+void indef_map_start_callback(void *);
+
+void tag_callback(void *, uint64_t);
+
+void half_callback(void *, float);
+void float_callback(void *, float);
+void double_callback(void *, double);
+void indef_break_callback(void *);
+
+void bool_callback(void *, bool);
+void null_callback(void *);
+void undef_callback(void *);
+
+#endif
diff --git a/contrib/libcbor/test/string_encoders_test.c b/contrib/libcbor/test/string_encoders_test.c
new file mode 100644
index 000000000000..6de1cfb27eb3
--- /dev/null
+++ b/contrib/libcbor/test/string_encoders_test.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_string_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_string_start(1, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x61}), 1);
+}
+
+static void test_string_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_string_start(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x7A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_indef_string_start(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_indef_string_start(buffer, 512));
+ assert_size_equal(0, cbor_encode_indef_string_start(buffer, 0));
+ assert_memory_equal(buffer, ((unsigned char[]){0x7F}), 1);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_embedded_string_start),
+ cmocka_unit_test(test_string_start),
+ cmocka_unit_test(test_indef_string_start)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/string_test.c b/contrib/libcbor/test/string_test.c
new file mode 100644
index 000000000000..c3079b449838
--- /dev/null
+++ b/contrib/libcbor/test/string_test.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <string.h>
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *string;
+struct cbor_load_result res;
+
+unsigned char empty_string_data[] = {0x60};
+
+static void test_empty_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(empty_string_data, 1, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 0);
+ assert_size_equal(cbor_string_codepoint_count(string), 0);
+ assert_true(res.read == 1);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char short_string_data[] = {0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20,
+ 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21};
+
+/* 0x60 + 12 | Hello world! */
+static void test_short_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(short_string_data, 13, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 12);
+ assert_size_equal(cbor_string_codepoint_count(string), 12);
+ assert_memory_equal(&"Hello world!", cbor_string_handle(string), 12);
+ assert_true(res.read == 13);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char short_multibyte_string_data[] = {
+ 0x6F, 0xC4, 0x8C, 0x61, 0x75, 0x65, 0x73, 0x20,
+ 0xC3, 0x9F, 0x76, 0xC4, 0x9B, 0x74, 0x65, 0x21};
+
+/* 0x60 + 15 | Čaues ßvěte! */
+static void test_short_multibyte_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(short_multibyte_string_data, 16, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 15);
+ assert_size_equal(cbor_string_codepoint_count(string), 12);
+ assert_memory_equal(&"Čaues ßvěte!", cbor_string_handle(string), 15);
+ assert_true(res.read == 16);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char int8_string_data[] = {
+ 0x78, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75,
+ 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20,
+ 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63,
+ 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73,
+ 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44,
+ 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C,
+ 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20,
+ 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C,
+ 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72,
+ 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66,
+ 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E,
+ 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20,
+ 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
+
+/* 150 | Lorem ....*/
+static void test_int8_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(int8_string_data, 152, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 150);
+ assert_size_equal(cbor_string_codepoint_count(string), 150);
+ assert_memory_equal(
+ &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
+ cbor_string_handle(string),
+ 150
+ );
+ assert_true(res.read == 152);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char int16_string_data[] = {
+ 0x79, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73,
+ 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74,
+ 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65,
+ 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69,
+ 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20,
+ 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C,
+ 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73,
+ 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75,
+ 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65,
+ 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20,
+ 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65,
+ 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F,
+ 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
+/* 150 | Lorem ....*/
+/* This valid but not realistic - length 150 could be encoded in a single
+ * uint8_t (but we need to keep the test files reasonably compact) */
+static void test_int16_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(int16_string_data, 153, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 150);
+ assert_size_equal(cbor_string_codepoint_count(string), 150);
+ assert_memory_equal(
+ &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
+ cbor_string_handle(string),
+ 150
+ );
+ assert_true(res.read == 153);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char int32_string_data[] = {
+ 0x7A, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69,
+ 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73,
+ 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E,
+ 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69,
+ 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74,
+ 0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74,
+ 0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C,
+ 0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69,
+ 0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20,
+ 0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F,
+ 0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65,
+ 0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73,
+ 0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E};
+
+/* 150 | Lorem ....*/
+static void test_int32_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(int32_string_data, 155, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 150);
+ assert_size_equal(cbor_string_codepoint_count(string), 150);
+ assert_memory_equal(
+ &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
+ cbor_string_handle(string),
+ 150
+ );
+ assert_true(res.read == 155);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char int64_string_data[] = {
+ 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72,
+ 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C,
+ 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C,
+ 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72,
+ 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20,
+ 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20,
+ 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69,
+ 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76,
+ 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75,
+ 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75,
+ 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E,
+ 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74,
+ 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65,
+ 0x72, 0x65, 0x2E};
+
+/* 150 | Lorem ....*/
+static void test_int64_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(int64_string_data, 159, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 150);
+ assert_size_equal(cbor_string_codepoint_count(string), 150);
+ assert_memory_equal(
+ &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.",
+ cbor_string_handle(string),
+ 150
+ );
+ assert_true(res.read == 159);
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+unsigned char short_indef_string_data[] = {0x7F, 0x78, 0x01, 0x65, 0xFF, 0xFF};
+
+/* start | string | break| extra
+ */
+
+static void test_short_indef_string(void **_CBOR_UNUSED(_state)) {
+ string = cbor_load(short_indef_string_data, 6, &res);
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_true(cbor_string_length(string) == 0);
+ assert_true(cbor_string_is_indefinite(string));
+ assert_true(cbor_string_chunk_count(string) == 1);
+ assert_true(res.read == 5);
+ assert_true(cbor_isa_string(cbor_string_chunks_handle(string)[0]));
+ assert_true(cbor_string_length(cbor_string_chunks_handle(string)[0]) == 1);
+ assert_true(*cbor_string_handle(cbor_string_chunks_handle(string)[0]) == 'e');
+ cbor_decref(&string);
+ assert_null(string);
+}
+
+static void test_invalid_utf(void **_CBOR_UNUSED(_state)) {
+ /* 0x60 + 1 | 0xC5 (invalid unfinished 2B codepoint) */
+ unsigned char string_data[] = {0x61, 0xC5};
+ string = cbor_load(string_data, 2, &res);
+
+ assert_non_null(string);
+ assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
+ assert_true(cbor_isa_string(string));
+ assert_size_equal(cbor_string_length(string), 1);
+ assert_size_equal(cbor_string_codepoint_count(string), 0);
+ assert_true(cbor_string_is_definite(string));
+ assert_true(res.read == 2);
+
+ cbor_decref(&string);
+}
+
+static void test_inline_creation(void **_CBOR_UNUSED(_state)) {
+ string = cbor_build_string("Hello!");
+ assert_memory_equal(cbor_string_handle(string), "Hello!", strlen("Hello!"));
+ cbor_decref(&string);
+}
+
+static void test_string_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_string()); });
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_string()); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_new_indefinite_string()); }, 2, MALLOC,
+ MALLOC_FAIL);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_string("Test")); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_build_string("Test")); }, 2, MALLOC,
+ MALLOC_FAIL);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); });
+ WITH_MOCK_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); }, 2, MALLOC,
+ MALLOC_FAIL);
+}
+
+static void test_string_add_chunk(void **_CBOR_UNUSED(_state)) {
+ WITH_MOCK_MALLOC(
+ {
+ cbor_item_t *string = cbor_new_indefinite_string();
+ cbor_item_t *chunk = cbor_build_string("Hello!");
+
+ assert_false(cbor_string_add_chunk(string, chunk));
+ assert_size_equal(cbor_string_chunk_count(string), 0);
+ assert_size_equal(((struct cbor_indefinite_string_data *)string->data)
+ ->chunk_capacity,
+ 0);
+
+ cbor_decref(&chunk);
+ cbor_decref(&string);
+ },
+ 5, MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
+}
+
+static void test_add_chunk_reallocation_overflow(void **_CBOR_UNUSED(_state)) {
+ string = cbor_new_indefinite_string();
+ cbor_item_t *chunk = cbor_build_string("Hello!");
+ struct cbor_indefinite_string_data *metadata =
+ (struct cbor_indefinite_string_data *)string->data;
+ // Pretend we already have many chunks allocated
+ metadata->chunk_count = SIZE_MAX;
+ metadata->chunk_capacity = SIZE_MAX;
+
+ assert_false(cbor_string_add_chunk(string, chunk));
+ assert_size_equal(cbor_refcount(chunk), 1);
+
+ metadata->chunk_count = 0;
+ metadata->chunk_capacity = 0;
+ cbor_decref(&chunk);
+ cbor_decref(&string);
+}
+
+static void test_set_handle(void **_CBOR_UNUSED(_state)) {
+ string = cbor_new_definite_string();
+ char *test_string = "Hello";
+ unsigned char *string_data = malloc(strlen(test_string));
+ memcpy(string_data, test_string, strlen(test_string));
+ assert_ptr_not_equal(string_data, NULL);
+ cbor_string_set_handle(string, string_data, strlen(test_string));
+
+ assert_ptr_equal(cbor_string_handle(string), string_data);
+ assert_size_equal(cbor_string_length(string), 5);
+ assert_size_equal(cbor_string_codepoint_count(string), 5);
+
+ cbor_decref(&string);
+}
+
+static void test_set_handle_multibyte_codepoint(void **_CBOR_UNUSED(_state)) {
+ string = cbor_new_definite_string();
+ // "Štěstíčko" in UTF-8
+ char *test_string = "\xc5\xa0t\xc4\x9bst\xc3\xad\xc4\x8dko";
+ unsigned char *string_data = malloc(strlen(test_string));
+ memcpy(string_data, test_string, strlen(test_string));
+ assert_ptr_not_equal(string_data, NULL);
+ cbor_string_set_handle(string, string_data, strlen(test_string));
+
+ assert_ptr_equal(cbor_string_handle(string), string_data);
+ assert_size_equal(cbor_string_length(string), 13);
+ assert_size_equal(cbor_string_codepoint_count(string), 9);
+
+ cbor_decref(&string);
+}
+
+static void test_set_handle_invalid_utf(void **_CBOR_UNUSED(_state)) {
+ string = cbor_new_definite_string();
+ // Invalid multi-byte character (missing the second byte).
+ char *test_string = "Test: \xc5";
+ unsigned char *string_data = malloc(strlen(test_string));
+ memcpy(string_data, test_string, strlen(test_string));
+ assert_ptr_not_equal(string_data, NULL);
+ cbor_string_set_handle(string, string_data, strlen(test_string));
+
+ assert_ptr_equal(cbor_string_handle(string), string_data);
+ assert_size_equal(cbor_string_length(string), 7);
+ assert_size_equal(cbor_string_codepoint_count(string), 0);
+
+ cbor_decref(&string);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_empty_string),
+ cmocka_unit_test(test_short_string),
+ cmocka_unit_test(test_short_multibyte_string),
+ cmocka_unit_test(test_int8_string),
+ cmocka_unit_test(test_int16_string),
+ cmocka_unit_test(test_int32_string),
+ cmocka_unit_test(test_int64_string),
+ cmocka_unit_test(test_short_indef_string),
+ cmocka_unit_test(test_invalid_utf),
+ cmocka_unit_test(test_inline_creation),
+ cmocka_unit_test(test_string_creation),
+ cmocka_unit_test(test_string_add_chunk),
+ cmocka_unit_test(test_add_chunk_reallocation_overflow),
+ cmocka_unit_test(test_set_handle),
+ cmocka_unit_test(test_set_handle_multibyte_codepoint),
+ cmocka_unit_test(test_set_handle_invalid_utf),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/tag_encoders_test.c b/contrib/libcbor/test/tag_encoders_test.c
new file mode 100644
index 000000000000..5962dd9d8938
--- /dev/null
+++ b/contrib/libcbor/test/tag_encoders_test.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_tag(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_tag(1, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xC1}), 1);
+}
+
+static void test_tag(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(5, cbor_encode_tag(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0xDA, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_embedded_tag),
+ cmocka_unit_test(test_tag),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/tag_test.c b/contrib/libcbor/test/tag_test.c
new file mode 100644
index 000000000000..4bce10589803
--- /dev/null
+++ b/contrib/libcbor/test/tag_test.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+#include "test_allocator.h"
+
+cbor_item_t *tag;
+struct cbor_load_result res;
+
+unsigned char embedded_tag_data[] = {0xC0, 0x00};
+
+static void test_refcounting(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(embedded_tag_data, 2, &res);
+ assert_true(cbor_refcount(tag) == 1);
+ cbor_item_t *item = cbor_tag_item(tag);
+ assert_true(cbor_refcount(item) == 2);
+ cbor_decref(&tag);
+ assert_null(tag);
+ assert_true(cbor_refcount(item) == 1);
+ cbor_decref(&item);
+ assert_null(item);
+}
+
+/* Tag 0 + uint 0 */
+static void test_embedded_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(embedded_tag_data, 2, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 0);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 0);
+ cbor_decref(&tag);
+ assert_null(tag);
+}
+
+unsigned char int8_tag_data[] = {0xD8, 0xFF, 0x01};
+
+/* Tag 255 + uint 1 */
+static void test_int8_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(int8_tag_data, 3, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 255);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 1);
+ cbor_decref(&tag);
+ assert_null(tag);
+}
+
+unsigned char int16_tag_data[] = {0xD9, 0xFF, 0x00, 0x02};
+
+/* Tag 255 << 8 + uint 2 */
+static void test_int16_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(int16_tag_data, 4, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 255 << 8);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 2);
+ cbor_decref(&tag);
+ assert_null(tag);
+}
+
+unsigned char int32_tag_data[] = {0xDA, 0xFF, 0x00, 0x00, 0x00, 0x03};
+
+/* uint 3 */
+static void test_int32_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(int32_tag_data, 6, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 4278190080ULL);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 3);
+ cbor_decref(&tag);
+ assert_null(tag);
+}
+
+unsigned char int64_tag_data[] = {0xDB, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04};
+
+/* uint 4 */
+static void test_int64_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(int64_tag_data, 10, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 18374686479671623680ULL);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 4);
+ cbor_decref(&tag);
+ assert_null(tag);
+}
+
+unsigned char nested_tag_data[] = {0xC0, 0xC1, 0x18, 0x2A};
+
+/* Tag 0, tag 1 + uint 0 */
+static void test_nested_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_load(nested_tag_data, 4, &res);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == 0);
+ cbor_item_t *nested_tag = cbor_tag_item(tag);
+ assert_true(cbor_typeof(nested_tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(nested_tag) == 1);
+ assert_uint8(cbor_move(cbor_tag_item(nested_tag)), 42);
+ cbor_decref(&tag);
+ assert_null(tag);
+ cbor_decref(&nested_tag);
+ assert_null(nested_tag);
+}
+
+static void test_all_tag_values_supported(void **_CBOR_UNUSED(_state)) {
+ /* Test all items in the protected range of
+ * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml */
+ for (int64_t tag_value = 0; tag_value <= 32767; tag_value++) {
+ cbor_item_t *tag_item =
+ cbor_build_tag(tag_value, cbor_move(cbor_build_uint8(42)));
+ unsigned char *serialized_tag;
+ size_t serialized_tag_size =
+ cbor_serialize_alloc(tag_item, &serialized_tag, NULL);
+ assert_true(serialized_tag_size > 0);
+ tag = cbor_load(serialized_tag, serialized_tag_size, &res);
+ assert_true(res.read == serialized_tag_size);
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_true(cbor_tag_value(tag) == tag_value);
+ cbor_decref(&tag);
+ assert_null(tag);
+ cbor_decref(&tag_item);
+ assert_null(tag_item);
+ free(serialized_tag);
+ }
+}
+
+static void test_build_tag(void **_CBOR_UNUSED(_state)) {
+ tag = cbor_build_tag(1, cbor_move(cbor_build_uint8(42)));
+
+ assert_true(cbor_typeof(tag) == CBOR_TYPE_TAG);
+ assert_size_equal(cbor_tag_value(tag), 1);
+ assert_uint8(cbor_move(cbor_tag_item(tag)), 42);
+
+ cbor_decref(&tag);
+}
+
+static void test_build_tag_failure(void **_CBOR_UNUSED(_state)) {
+ cbor_item_t *tagged_item = cbor_build_uint8(42);
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_tag(1, tagged_item)); });
+ assert_size_equal(cbor_refcount(tagged_item), 1);
+
+ cbor_decref(&tagged_item);
+}
+
+static void test_tag_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_tag(42)); });
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_refcounting),
+ cmocka_unit_test(test_embedded_tag),
+ cmocka_unit_test(test_int8_tag),
+ cmocka_unit_test(test_int16_tag),
+ cmocka_unit_test(test_int32_tag),
+ cmocka_unit_test(test_int64_tag),
+ cmocka_unit_test(test_nested_tag),
+ cmocka_unit_test(test_all_tag_values_supported),
+ cmocka_unit_test(test_build_tag),
+ cmocka_unit_test(test_build_tag_failure),
+ cmocka_unit_test(test_tag_creation),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/test_allocator.c b/contrib/libcbor/test/test_allocator.c
new file mode 100644
index 000000000000..a2f98efa22f7
--- /dev/null
+++ b/contrib/libcbor/test/test_allocator.c
@@ -0,0 +1,89 @@
+#include "test_allocator.h"
+
+#ifdef HAS_EXECINFO
+#include <execinfo.h>
+#endif
+
+// How many alloc calls we expect
+int alloc_calls_expected;
+// How many alloc calls we got
+int alloc_calls;
+// Array of booleans indicating whether to return a block or fail with NULL
+call_expectation *expectations;
+
+void set_mock_malloc(int calls, ...) {
+ va_list args;
+ va_start(args, calls);
+ alloc_calls_expected = calls;
+ alloc_calls = 0;
+ expectations = calloc(calls, sizeof(expectations));
+ for (int i = 0; i < calls; i++) {
+ // Promotable types, baby
+ expectations[i] = va_arg(args, call_expectation);
+ }
+ va_end(args);
+}
+
+void finalize_mock_malloc(void) {
+ assert_int_equal(alloc_calls, alloc_calls_expected);
+ free(expectations);
+}
+
+void print_backtrace(void) {
+#if HAS_EXECINFO
+ void *buffer[128];
+ int frames = backtrace(buffer, 128);
+ char **symbols = backtrace_symbols(buffer, frames);
+ // Skip this function and the caller
+ for (int i = 2; i < frames; ++i) {
+ printf("%s\n", symbols[i]);
+ }
+ free(symbols);
+#endif
+}
+
+void *instrumented_malloc(size_t size) {
+ if (alloc_calls >= alloc_calls_expected) {
+ goto error;
+ }
+
+ if (expectations[alloc_calls] == MALLOC) {
+ alloc_calls++;
+ return malloc(size);
+ } else if (expectations[alloc_calls] == MALLOC_FAIL) {
+ alloc_calls++;
+ return NULL;
+ }
+
+error:
+ print_error(
+ "Unexpected call to malloc(%zu) at position %d of %d; expected %d\n",
+ size, alloc_calls, alloc_calls_expected,
+ alloc_calls < alloc_calls_expected ? expectations[alloc_calls] : -1);
+ print_backtrace();
+ fail();
+ return NULL;
+}
+
+void *instrumented_realloc(void *ptr, size_t size) {
+ if (alloc_calls >= alloc_calls_expected) {
+ goto error;
+ }
+
+ if (expectations[alloc_calls] == REALLOC) {
+ alloc_calls++;
+ return realloc(ptr, size);
+ } else if (expectations[alloc_calls] == REALLOC_FAIL) {
+ alloc_calls++;
+ return NULL;
+ }
+
+error:
+ print_error(
+ "Unexpected call to realloc(%zu) at position %d of %d; expected %d\n",
+ size, alloc_calls, alloc_calls_expected,
+ alloc_calls < alloc_calls_expected ? expectations[alloc_calls] : -1);
+ print_backtrace();
+ fail();
+ return NULL;
+}
diff --git a/contrib/libcbor/test/test_allocator.h b/contrib/libcbor/test/test_allocator.h
new file mode 100644
index 000000000000..0e58454edbd6
--- /dev/null
+++ b/contrib/libcbor/test/test_allocator.h
@@ -0,0 +1,35 @@
+#ifndef TEST_ALLOCATOR_H_
+#define TEST_ALLOCATOR_H_
+
+#include "assertions.h"
+#include "cbor.h"
+
+// Harness for mocking `malloc` and `realloc`
+
+typedef enum call_expectation {
+ MALLOC,
+ MALLOC_FAIL,
+ REALLOC,
+ REALLOC_FAIL
+} call_expectation;
+
+void set_mock_malloc(int calls, ...);
+
+void finalize_mock_malloc(void);
+
+void *instrumented_malloc(size_t size);
+
+void *instrumented_realloc(void *ptr, size_t size);
+
+#define WITH_MOCK_MALLOC(block, malloc_calls, ...) \
+ do { \
+ cbor_set_allocs(instrumented_malloc, instrumented_realloc, free); \
+ set_mock_malloc(malloc_calls, __VA_ARGS__); \
+ block; \
+ finalize_mock_malloc(); \
+ cbor_set_allocs(malloc, realloc, free); \
+ } while (0)
+
+#define WITH_FAILING_MALLOC(block) WITH_MOCK_MALLOC(block, 1, MALLOC_FAIL)
+
+#endif // TEST_ALLOCATOR_H_
diff --git a/contrib/libcbor/test/uint_encoders_test.c b/contrib/libcbor/test/uint_encoders_test.c
new file mode 100644
index 000000000000..59b95a33026e
--- /dev/null
+++ b/contrib/libcbor/test/uint_encoders_test.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "cbor.h"
+
+unsigned char buffer[512];
+
+static void test_embedded_uint8(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(1, cbor_encode_uint8(14, buffer, 512));
+ assert_memory_equal(buffer, (unsigned char[]){0x0E}, 1);
+}
+
+static void test_uint8(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_uint8(180, buffer, 1));
+ assert_size_equal(2, cbor_encode_uint8(255, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x18, 0xFF}), 2);
+}
+
+static void test_uint16(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_uint16(1000, buffer, 2));
+ assert_size_equal(3, cbor_encode_uint16(1000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x19, 0x03, 0xE8}), 3);
+}
+
+static void test_uint32(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_uint32(1000000, buffer, 4));
+ assert_size_equal(5, cbor_encode_uint32(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x1A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+}
+
+static void test_uint64(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(0, cbor_encode_uint64(18446744073709551615ULL, buffer, 8));
+ assert_size_equal(9,
+ cbor_encode_uint64(18446744073709551615ULL, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}),
+ 9);
+}
+
+static void test_unspecified(void **_CBOR_UNUSED(_state)) {
+ assert_size_equal(9, cbor_encode_uint(18446744073709551615ULL, buffer, 512));
+ assert_memory_equal(
+ buffer,
+ ((unsigned char[]){0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}),
+ 9);
+ assert_size_equal(5, cbor_encode_uint(1000000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x1A, 0x00, 0x0F, 0x42, 0x40}),
+ 5);
+ assert_size_equal(3, cbor_encode_uint(1000, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x19, 0x03, 0xE8}), 3);
+ assert_size_equal(2, cbor_encode_uint(255, buffer, 512));
+ assert_memory_equal(buffer, ((unsigned char[]){0x18, 0xFF}), 2);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {cmocka_unit_test(test_embedded_uint8),
+ cmocka_unit_test(test_uint8),
+ cmocka_unit_test(test_uint16),
+ cmocka_unit_test(test_uint32),
+ cmocka_unit_test(test_uint64),
+ cmocka_unit_test(test_unspecified)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/uint_test.c b/contrib/libcbor/test/uint_test.c
new file mode 100644
index 000000000000..89eb2b91833e
--- /dev/null
+++ b/contrib/libcbor/test/uint_test.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+#include "test_allocator.h"
+
+#include "cbor.h"
+
+cbor_item_t *number;
+struct cbor_load_result res;
+
+unsigned char data1[] = {0x02, 0xFF};
+unsigned char data2[] = {0x18, 0xFF, 0xFF};
+unsigned char data3[] = {0x19, 0x01, 0xf4, 0xFF};
+unsigned char data4[] = {0x1a, 0xa5, 0xf7, 0x02, 0xb3, 0xFF};
+unsigned char data5[] = {0x1b, 0xa5, 0xf7, 0x02, 0xb3,
+ 0xa5, 0xf7, 0x02, 0xb3, 0xFF};
+
+static void test_very_short_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data1, 2, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_UINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_8);
+ assert_true(cbor_isa_uint(number));
+ assert_false(cbor_isa_negint(number));
+ assert_true(cbor_get_uint8(number) == 2);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 1);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_incomplete_data(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data2, 1, &res);
+ assert_null(number);
+ assert_true(res.error.code == CBOR_ERR_NOTENOUGHDATA);
+}
+
+static void test_short_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data2, 3, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_UINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_8);
+ assert_true(cbor_isa_uint(number));
+ assert_false(cbor_isa_negint(number));
+ assert_true(cbor_get_uint8(number) == 255);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 2);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_half_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data3, 5, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_UINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_16);
+ assert_true(cbor_isa_uint(number));
+ assert_false(cbor_isa_negint(number));
+ assert_true(cbor_get_uint16(number) == 500);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 3);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data4, 6, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_UINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_32);
+ assert_true(cbor_isa_uint(number));
+ assert_false(cbor_isa_negint(number));
+ assert_true(cbor_get_uint32(number) == 2784428723);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 5);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_long_int(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data5, 10, &res);
+ assert_true(cbor_typeof(number) == CBOR_TYPE_UINT);
+ assert_true(cbor_int_get_width(number) == CBOR_INT_64);
+ assert_true(cbor_isa_uint(number));
+ assert_false(cbor_isa_negint(number));
+ assert_true(cbor_get_uint64(number) == 11959030306112471731ULL);
+ assert_true(res.error.code == 0);
+ assert_true(res.read == 9);
+ assert_true(cbor_is_int(number));
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_refcounting(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data5, 10, &res);
+ cbor_incref(number);
+ assert_true(number->refcount == 2);
+ cbor_decref(&number);
+ assert_non_null(number);
+ cbor_decref(&number);
+ assert_null(number);
+}
+
+static void test_empty_input(void **_CBOR_UNUSED(_state)) {
+ number = cbor_load(data5, 0, &res);
+ assert_null(number);
+ assert_true(res.error.code == CBOR_ERR_NODATA);
+}
+
+static void test_inline_creation(void **_CBOR_UNUSED(_state)) {
+ number = cbor_build_uint8(10);
+ assert_true(cbor_get_int(number) == 10);
+ cbor_decref(&number);
+
+ number = cbor_build_uint16(10);
+ assert_true(cbor_get_int(number) == 10);
+ cbor_decref(&number);
+
+ number = cbor_build_uint32(10);
+ assert_true(cbor_get_int(number) == 10);
+ cbor_decref(&number);
+
+ number = cbor_build_uint64(10);
+ assert_true(cbor_get_int(number) == 10);
+ cbor_decref(&number);
+}
+
+static void test_int_creation(void **_CBOR_UNUSED(_state)) {
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int8()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int16()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int32()); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_new_int64()); });
+
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_uint8(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_uint16(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_uint32(0xFF)); });
+ WITH_FAILING_MALLOC({ assert_null(cbor_build_uint64(0xFF)); });
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_very_short_int),
+ cmocka_unit_test(test_short_int),
+ cmocka_unit_test(test_half_int),
+ cmocka_unit_test(test_int),
+ cmocka_unit_test(test_long_int),
+ cmocka_unit_test(test_incomplete_data),
+ cmocka_unit_test(test_refcounting),
+ cmocka_unit_test(test_empty_input),
+ cmocka_unit_test(test_inline_creation),
+ cmocka_unit_test(test_int_creation),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/contrib/libcbor/test/unicode_test.c b/contrib/libcbor/test/unicode_test.c
new file mode 100644
index 000000000000..4b3613e77f78
--- /dev/null
+++ b/contrib/libcbor/test/unicode_test.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "assertions.h"
+
+#include "../src/cbor/internal/unicode.h"
+struct _cbor_unicode_status status;
+
+unsigned char missing_bytes_data[] = {0xC4, 0x8C};
+
+/* Capital accented C */
+static void test_missing_bytes(void **_CBOR_UNUSED(_state)) {
+ assert_true(_cbor_unicode_codepoint_count(missing_bytes_data, 1, &status) ==
+ 0);
+ assert_true(status.status == _CBOR_UNICODE_BADCP);
+ assert_true(status.location == 1);
+
+ assert_true(_cbor_unicode_codepoint_count(missing_bytes_data, 2, &status) ==
+ 1);
+ assert_true(status.status == _CBOR_UNICODE_OK);
+ assert_true(status.location == 0);
+}
+
+unsigned char invalid_sequence_data[] = {0x65, 0xC4, 0x00};
+
+/* e, invalid seq */
+static void test_invalid_sequence(void **_CBOR_UNUSED(_state)) {
+ assert_true(
+ _cbor_unicode_codepoint_count(invalid_sequence_data, 3, &status) == 0);
+ assert_true(status.status == _CBOR_UNICODE_BADCP);
+ assert_true(status.location == 2);
+}
+
+int main(void) {
+ const struct CMUnitTest tests[] = {cmocka_unit_test(test_missing_bytes),
+ cmocka_unit_test(test_invalid_sequence)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}