diff options
Diffstat (limited to 'contrib/libcbor/test')
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(©); + + item = cbor_build_uint16(10); + assert_uint16(copy = cbor_copy(item), 10); + cbor_decref(&item); + cbor_decref(©); + + item = cbor_build_uint32(10); + assert_uint32(copy = cbor_copy(item), 10); + cbor_decref(&item); + cbor_decref(©); + + item = cbor_build_uint64(10); + assert_uint64(copy = cbor_copy(item), 10); + cbor_decref(&item); + cbor_decref(©); +} + +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(©); + + item = cbor_build_negint16(10); + assert_true(cbor_get_uint16(copy = cbor_copy(item)) == 10); + cbor_decref(&item); + cbor_decref(©); + + item = cbor_build_negint32(10); + assert_true(cbor_get_uint32(copy = cbor_copy(item)) == 10); + cbor_decref(&item); + cbor_decref(©); + + item = cbor_build_negint64(10); + assert_true(cbor_get_uint64(copy = cbor_copy(item)) == 10); + cbor_decref(&item); + cbor_decref(©); +} + +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(©); +} + +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(©); +} + +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(©); +} + +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(©); +} + +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(©); + 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(©); + 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(©); +} + +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(©); +} + +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(©); +} + +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(©); +} + +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(©); + + 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(©); + + 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(©); +} + +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 Binary files differnew file mode 100644 index 000000000000..6903268bc8d7 --- /dev/null +++ b/contrib/libcbor/test/data/callbacks.cbor 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); +} |
