xref: /freebsd/contrib/libcbor/test/callbacks_test.c (revision abd872540f24cfc7dbd1ea29b6918c7082a22108)
110ff414cSEd Maste /*
210ff414cSEd Maste  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
310ff414cSEd Maste  *
410ff414cSEd Maste  * libcbor is free software; you can redistribute it and/or modify
510ff414cSEd Maste  * it under the terms of the MIT license. See LICENSE for details.
610ff414cSEd Maste  */
75d3e7166SEd Maste #include "assertions.h"
810ff414cSEd Maste #include "cbor.h"
95d3e7166SEd Maste #include "cbor/internal/builder_callbacks.h"
105d3e7166SEd Maste #include "cbor/internal/stack.h"
115d3e7166SEd Maste #include "test_allocator.h"
1210ff414cSEd Maste 
1310ff414cSEd Maste unsigned char data[] = {
1410ff414cSEd Maste     0x93, 0x01, 0x19, 0x01, 0x01, 0x1A, 0x00, 0x01, 0x05, 0xB8, 0x1B, 0x00,
1510ff414cSEd Maste     0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8, 0xB8, 0x20, 0x39, 0x01, 0x00, 0x3A,
1610ff414cSEd Maste     0x00, 0x01, 0x05, 0xB7, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8,
1710ff414cSEd Maste     0xB7, 0x5F, 0x41, 0x01, 0x41, 0x02, 0xFF, 0x7F, 0x61, 0x61, 0x61, 0x62,
1810ff414cSEd Maste     0xFF, 0x9F, 0xFF, 0xA1, 0x61, 0x61, 0x61, 0x62, 0xC0, 0xBF, 0xFF, 0xF9,
1910ff414cSEd Maste     0x3C, 0x00, 0xFA, 0x47, 0xC3, 0x50, 0x00, 0xFB, 0x7E, 0x37, 0xE4, 0x3C,
2010ff414cSEd Maste     0x88, 0x00, 0x75, 0x9C, 0xF6, 0xF7, 0xF5};
2110ff414cSEd Maste 
2210ff414cSEd Maste /* Exercise the default callbacks */
235d3e7166SEd Maste static void test_default_callbacks(void** _CBOR_UNUSED(_state)) {
2410ff414cSEd Maste   size_t read = 0;
2510ff414cSEd Maste   while (read < 79) {
2610ff414cSEd Maste     struct cbor_decoder_result result =
2710ff414cSEd Maste         cbor_stream_decode(data + read, 79 - read, &cbor_empty_callbacks, NULL);
2810ff414cSEd Maste     read += result.read;
2910ff414cSEd Maste   }
3010ff414cSEd Maste }
3110ff414cSEd Maste 
325d3e7166SEd Maste unsigned char bytestring_data[] = {0x01, 0x02, 0x03};
335d3e7166SEd Maste static void test_builder_byte_string_callback_append(
345d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
355d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
365d3e7166SEd Maste   assert_non_null(
375d3e7166SEd Maste       _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
385d3e7166SEd Maste   struct _cbor_decoder_context context = {
395d3e7166SEd Maste       .creation_failed = false,
405d3e7166SEd Maste       .syntax_error = false,
415d3e7166SEd Maste       .root = NULL,
425d3e7166SEd Maste       .stack = &stack,
435d3e7166SEd Maste   };
445d3e7166SEd Maste 
455d3e7166SEd Maste   cbor_builder_byte_string_callback(&context, bytestring_data, 3);
465d3e7166SEd Maste 
475d3e7166SEd Maste   assert_false(context.creation_failed);
485d3e7166SEd Maste   assert_false(context.syntax_error);
495d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
505d3e7166SEd Maste 
515d3e7166SEd Maste   cbor_item_t* bytestring = stack.top->item;
525d3e7166SEd Maste   assert_size_equal(cbor_refcount(bytestring), 1);
535d3e7166SEd Maste   assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
545d3e7166SEd Maste   assert_true(cbor_isa_bytestring(bytestring));
555d3e7166SEd Maste   assert_size_equal(cbor_bytestring_length(bytestring), 0);
565d3e7166SEd Maste   assert_true(cbor_bytestring_is_indefinite(bytestring));
575d3e7166SEd Maste   assert_size_equal(cbor_bytestring_chunk_count(bytestring), 1);
585d3e7166SEd Maste 
595d3e7166SEd Maste   cbor_item_t* chunk = cbor_bytestring_chunks_handle(bytestring)[0];
605d3e7166SEd Maste   assert_size_equal(cbor_refcount(chunk), 1);
615d3e7166SEd Maste   assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
625d3e7166SEd Maste   assert_true(cbor_isa_bytestring(chunk));
635d3e7166SEd Maste   assert_true(cbor_bytestring_is_definite(chunk));
645d3e7166SEd Maste   assert_size_equal(cbor_bytestring_length(chunk), 3);
655d3e7166SEd Maste   assert_memory_equal(cbor_bytestring_handle(chunk), bytestring_data, 3);
665d3e7166SEd Maste   // Data is copied
675d3e7166SEd Maste   assert_ptr_not_equal(cbor_bytestring_handle(chunk), bytestring_data);
685d3e7166SEd Maste 
695d3e7166SEd Maste   cbor_decref(&bytestring);
705d3e7166SEd Maste   _cbor_stack_pop(&stack);
715d3e7166SEd Maste }
725d3e7166SEd Maste 
735d3e7166SEd Maste static void test_builder_byte_string_callback_append_alloc_failure(
745d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
755d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
765d3e7166SEd Maste   assert_non_null(
775d3e7166SEd Maste       _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
785d3e7166SEd Maste   struct _cbor_decoder_context context = {
795d3e7166SEd Maste       .creation_failed = false,
805d3e7166SEd Maste       .syntax_error = false,
815d3e7166SEd Maste       .root = NULL,
825d3e7166SEd Maste       .stack = &stack,
835d3e7166SEd Maste   };
845d3e7166SEd Maste 
855d3e7166SEd Maste   WITH_FAILING_MALLOC(
865d3e7166SEd Maste       { cbor_builder_byte_string_callback(&context, bytestring_data, 3); });
875d3e7166SEd Maste 
885d3e7166SEd Maste   assert_true(context.creation_failed);
895d3e7166SEd Maste   assert_false(context.syntax_error);
905d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
915d3e7166SEd Maste 
925d3e7166SEd Maste   // The stack remains unchanged
935d3e7166SEd Maste   cbor_item_t* bytestring = stack.top->item;
945d3e7166SEd Maste   assert_size_equal(cbor_refcount(bytestring), 1);
955d3e7166SEd Maste   assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
965d3e7166SEd Maste   assert_true(cbor_isa_bytestring(bytestring));
975d3e7166SEd Maste   assert_size_equal(cbor_bytestring_length(bytestring), 0);
985d3e7166SEd Maste   assert_true(cbor_bytestring_is_indefinite(bytestring));
995d3e7166SEd Maste   assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
1005d3e7166SEd Maste 
1015d3e7166SEd Maste   cbor_decref(&bytestring);
1025d3e7166SEd Maste   _cbor_stack_pop(&stack);
1035d3e7166SEd Maste }
1045d3e7166SEd Maste 
1055d3e7166SEd Maste static void test_builder_byte_string_callback_append_item_alloc_failure(
1065d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
1075d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
1085d3e7166SEd Maste   assert_non_null(
1095d3e7166SEd Maste       _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
1105d3e7166SEd Maste   struct _cbor_decoder_context context = {
1115d3e7166SEd Maste       .creation_failed = false,
1125d3e7166SEd Maste       .syntax_error = false,
1135d3e7166SEd Maste       .root = NULL,
1145d3e7166SEd Maste       .stack = &stack,
1155d3e7166SEd Maste   };
1165d3e7166SEd Maste 
1175d3e7166SEd Maste   // Allocate new data block, but fail to allocate a new item with it
1185d3e7166SEd Maste   WITH_MOCK_MALLOC(
1195d3e7166SEd Maste       { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 2,
1205d3e7166SEd Maste       MALLOC, MALLOC_FAIL);
1215d3e7166SEd Maste 
1225d3e7166SEd Maste   assert_true(context.creation_failed);
1235d3e7166SEd Maste   assert_false(context.syntax_error);
1245d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
1255d3e7166SEd Maste 
1265d3e7166SEd Maste   // The stack remains unchanged
1275d3e7166SEd Maste   cbor_item_t* bytestring = stack.top->item;
1285d3e7166SEd Maste   assert_size_equal(cbor_refcount(bytestring), 1);
1295d3e7166SEd Maste   assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
1305d3e7166SEd Maste   assert_true(cbor_isa_bytestring(bytestring));
1315d3e7166SEd Maste   assert_size_equal(cbor_bytestring_length(bytestring), 0);
1325d3e7166SEd Maste   assert_true(cbor_bytestring_is_indefinite(bytestring));
1335d3e7166SEd Maste   assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
1345d3e7166SEd Maste 
1355d3e7166SEd Maste   cbor_decref(&bytestring);
1365d3e7166SEd Maste   _cbor_stack_pop(&stack);
1375d3e7166SEd Maste }
1385d3e7166SEd Maste 
1395d3e7166SEd Maste static void test_builder_byte_string_callback_append_parent_alloc_failure(
1405d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
1415d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
1425d3e7166SEd Maste   assert_non_null(
1435d3e7166SEd Maste       _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0));
1445d3e7166SEd Maste   struct _cbor_decoder_context context = {
1455d3e7166SEd Maste       .creation_failed = false,
1465d3e7166SEd Maste       .syntax_error = false,
1475d3e7166SEd Maste       .root = NULL,
1485d3e7166SEd Maste       .stack = &stack,
1495d3e7166SEd Maste   };
1505d3e7166SEd Maste 
1515d3e7166SEd Maste   // Allocate new item, but fail to push it into the parent on the stack
1525d3e7166SEd Maste   WITH_MOCK_MALLOC(
1535d3e7166SEd Maste       { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 3,
1545d3e7166SEd Maste       MALLOC, MALLOC, REALLOC_FAIL);
1555d3e7166SEd Maste 
1565d3e7166SEd Maste   assert_true(context.creation_failed);
1575d3e7166SEd Maste   assert_false(context.syntax_error);
1585d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
1595d3e7166SEd Maste 
1605d3e7166SEd Maste   // The stack remains unchanged
1615d3e7166SEd Maste   cbor_item_t* bytestring = stack.top->item;
1625d3e7166SEd Maste   assert_size_equal(cbor_refcount(bytestring), 1);
1635d3e7166SEd Maste   assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING);
1645d3e7166SEd Maste   assert_true(cbor_isa_bytestring(bytestring));
1655d3e7166SEd Maste   assert_size_equal(cbor_bytestring_length(bytestring), 0);
1665d3e7166SEd Maste   assert_true(cbor_bytestring_is_indefinite(bytestring));
1675d3e7166SEd Maste   assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0);
1685d3e7166SEd Maste 
1695d3e7166SEd Maste   cbor_decref(&bytestring);
1705d3e7166SEd Maste   _cbor_stack_pop(&stack);
1715d3e7166SEd Maste }
1725d3e7166SEd Maste 
1735d3e7166SEd Maste unsigned char string_data[] = {0x61, 0x62, 0x63};
1745d3e7166SEd Maste static void test_builder_string_callback_append(void** _CBOR_UNUSED(_state)) {
1755d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
1765d3e7166SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
1775d3e7166SEd Maste   struct _cbor_decoder_context context = {
1785d3e7166SEd Maste       .creation_failed = false,
1795d3e7166SEd Maste       .syntax_error = false,
1805d3e7166SEd Maste       .root = NULL,
1815d3e7166SEd Maste       .stack = &stack,
1825d3e7166SEd Maste   };
1835d3e7166SEd Maste 
1845d3e7166SEd Maste   cbor_builder_string_callback(&context, string_data, 3);
1855d3e7166SEd Maste 
1865d3e7166SEd Maste   assert_false(context.creation_failed);
1875d3e7166SEd Maste   assert_false(context.syntax_error);
1885d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
1895d3e7166SEd Maste 
1905d3e7166SEd Maste   cbor_item_t* string = stack.top->item;
1915d3e7166SEd Maste   assert_size_equal(cbor_refcount(string), 1);
1925d3e7166SEd Maste   assert_true(cbor_isa_string(string));
1935d3e7166SEd Maste   assert_size_equal(cbor_string_length(string), 0);
1945d3e7166SEd Maste   assert_true(cbor_string_is_indefinite(string));
1955d3e7166SEd Maste   assert_size_equal(cbor_string_chunk_count(string), 1);
1965d3e7166SEd Maste 
1975d3e7166SEd Maste   cbor_item_t* chunk = cbor_string_chunks_handle(string)[0];
1985d3e7166SEd Maste   assert_size_equal(cbor_refcount(chunk), 1);
1995d3e7166SEd Maste   assert_true(cbor_isa_string(chunk));
2005d3e7166SEd Maste   assert_true(cbor_string_is_definite(chunk));
2015d3e7166SEd Maste   assert_size_equal(cbor_string_length(chunk), 3);
2025d3e7166SEd Maste   assert_memory_equal(cbor_string_handle(chunk), "abc", 3);
2035d3e7166SEd Maste   // Data is copied
2045d3e7166SEd Maste   assert_ptr_not_equal(cbor_string_handle(chunk), string_data);
2055d3e7166SEd Maste 
2065d3e7166SEd Maste   cbor_decref(&string);
2075d3e7166SEd Maste   _cbor_stack_pop(&stack);
2085d3e7166SEd Maste }
2095d3e7166SEd Maste 
2105d3e7166SEd Maste static void test_builder_string_callback_append_alloc_failure(
2115d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
2125d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
2135d3e7166SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
2145d3e7166SEd Maste   struct _cbor_decoder_context context = {
2155d3e7166SEd Maste       .creation_failed = false,
2165d3e7166SEd Maste       .syntax_error = false,
2175d3e7166SEd Maste       .root = NULL,
2185d3e7166SEd Maste       .stack = &stack,
2195d3e7166SEd Maste   };
2205d3e7166SEd Maste 
2215d3e7166SEd Maste   WITH_FAILING_MALLOC(
2225d3e7166SEd Maste       { cbor_builder_string_callback(&context, string_data, 3); });
2235d3e7166SEd Maste 
2245d3e7166SEd Maste   assert_true(context.creation_failed);
2255d3e7166SEd Maste   assert_false(context.syntax_error);
2265d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
2275d3e7166SEd Maste 
2285d3e7166SEd Maste   // The stack remains unchanged
2295d3e7166SEd Maste   cbor_item_t* string = stack.top->item;
2305d3e7166SEd Maste   assert_size_equal(cbor_refcount(string), 1);
2315d3e7166SEd Maste   assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
2325d3e7166SEd Maste   assert_true(cbor_isa_string(string));
2335d3e7166SEd Maste   assert_size_equal(cbor_string_length(string), 0);
2345d3e7166SEd Maste   assert_true(cbor_string_is_indefinite(string));
2355d3e7166SEd Maste   assert_size_equal(cbor_string_chunk_count(string), 0);
2365d3e7166SEd Maste 
2375d3e7166SEd Maste   cbor_decref(&string);
2385d3e7166SEd Maste   _cbor_stack_pop(&stack);
2395d3e7166SEd Maste }
2405d3e7166SEd Maste 
2415d3e7166SEd Maste static void test_builder_string_callback_append_item_alloc_failure(
2425d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
2435d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
2445d3e7166SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
2455d3e7166SEd Maste   struct _cbor_decoder_context context = {
2465d3e7166SEd Maste       .creation_failed = false,
2475d3e7166SEd Maste       .syntax_error = false,
2485d3e7166SEd Maste       .root = NULL,
2495d3e7166SEd Maste       .stack = &stack,
2505d3e7166SEd Maste   };
2515d3e7166SEd Maste 
2525d3e7166SEd Maste   // Allocate new data block, but fail to allocate a new item with it
2535d3e7166SEd Maste   WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); },
2545d3e7166SEd Maste                    2, MALLOC, MALLOC_FAIL);
2555d3e7166SEd Maste 
2565d3e7166SEd Maste   assert_true(context.creation_failed);
2575d3e7166SEd Maste   assert_false(context.syntax_error);
2585d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
2595d3e7166SEd Maste 
2605d3e7166SEd Maste   // The stack remains unchanged
2615d3e7166SEd Maste   cbor_item_t* string = stack.top->item;
2625d3e7166SEd Maste   assert_size_equal(cbor_refcount(string), 1);
2635d3e7166SEd Maste   assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
2645d3e7166SEd Maste   assert_true(cbor_isa_string(string));
2655d3e7166SEd Maste   assert_size_equal(cbor_string_length(string), 0);
2665d3e7166SEd Maste   assert_true(cbor_string_is_indefinite(string));
2675d3e7166SEd Maste   assert_size_equal(cbor_string_chunk_count(string), 0);
2685d3e7166SEd Maste 
2695d3e7166SEd Maste   cbor_decref(&string);
2705d3e7166SEd Maste   _cbor_stack_pop(&stack);
2715d3e7166SEd Maste }
2725d3e7166SEd Maste 
2735d3e7166SEd Maste static void test_builder_string_callback_append_parent_alloc_failure(
2745d3e7166SEd Maste     void** _CBOR_UNUSED(_state)) {
2755d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
2765d3e7166SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0));
2775d3e7166SEd Maste   struct _cbor_decoder_context context = {
2785d3e7166SEd Maste       .creation_failed = false,
2795d3e7166SEd Maste       .syntax_error = false,
2805d3e7166SEd Maste       .root = NULL,
2815d3e7166SEd Maste       .stack = &stack,
2825d3e7166SEd Maste   };
2835d3e7166SEd Maste 
2845d3e7166SEd Maste   // Allocate new item, but fail to push it into the parent on the stack
2855d3e7166SEd Maste   WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); },
2865d3e7166SEd Maste                    3, MALLOC, MALLOC, REALLOC_FAIL);
2875d3e7166SEd Maste 
2885d3e7166SEd Maste   assert_true(context.creation_failed);
2895d3e7166SEd Maste   assert_false(context.syntax_error);
2905d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
2915d3e7166SEd Maste 
2925d3e7166SEd Maste   // The stack remains unchanged
2935d3e7166SEd Maste   cbor_item_t* string = stack.top->item;
2945d3e7166SEd Maste   assert_size_equal(cbor_refcount(string), 1);
2955d3e7166SEd Maste   assert_true(cbor_typeof(string) == CBOR_TYPE_STRING);
2965d3e7166SEd Maste   assert_true(cbor_isa_string(string));
2975d3e7166SEd Maste   assert_size_equal(cbor_string_length(string), 0);
2985d3e7166SEd Maste   assert_true(cbor_string_is_indefinite(string));
2995d3e7166SEd Maste   assert_size_equal(cbor_string_chunk_count(string), 0);
3005d3e7166SEd Maste 
3015d3e7166SEd Maste   cbor_decref(&string);
3025d3e7166SEd Maste   _cbor_stack_pop(&stack);
3035d3e7166SEd Maste }
3045d3e7166SEd Maste 
3055d3e7166SEd Maste static void test_append_array_failure(void** _CBOR_UNUSED(_state)) {
3065d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
3075d3e7166SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_definite_array(0), 0));
3085d3e7166SEd Maste   stack.top->subitems = 1;
3095d3e7166SEd Maste   struct _cbor_decoder_context context = {
3105d3e7166SEd Maste       .creation_failed = false,
3115d3e7166SEd Maste       .syntax_error = false,
3125d3e7166SEd Maste       .root = NULL,
3135d3e7166SEd Maste       .stack = &stack,
3145d3e7166SEd Maste   };
3155d3e7166SEd Maste   cbor_item_t* item = cbor_build_uint8(42);
3165d3e7166SEd Maste 
3175d3e7166SEd Maste   _cbor_builder_append(item, &context);
3185d3e7166SEd Maste 
3195d3e7166SEd Maste   assert_true(context.creation_failed);
3205d3e7166SEd Maste   assert_false(context.syntax_error);
3215d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
3225d3e7166SEd Maste 
3235d3e7166SEd Maste   // The stack remains unchanged
3245d3e7166SEd Maste   cbor_item_t* array = stack.top->item;
3255d3e7166SEd Maste   assert_size_equal(cbor_refcount(array), 1);
3265d3e7166SEd Maste   assert_true(cbor_isa_array(array));
3275d3e7166SEd Maste   assert_size_equal(cbor_array_size(array), 0);
3285d3e7166SEd Maste 
3295d3e7166SEd Maste   // item free'd by _cbor_builder_append
3305d3e7166SEd Maste   cbor_decref(&array);
3315d3e7166SEd Maste   _cbor_stack_pop(&stack);
3325d3e7166SEd Maste }
3335d3e7166SEd Maste 
3345d3e7166SEd Maste static void test_append_map_failure(void** _CBOR_UNUSED(_state)) {
3355d3e7166SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
3365d3e7166SEd Maste   assert_non_null(
3375d3e7166SEd Maste       _cbor_stack_push(&stack, cbor_new_indefinite_map(), /*subitems=*/0));
3385d3e7166SEd Maste   struct _cbor_decoder_context context = {
3395d3e7166SEd Maste       .creation_failed = false,
3405d3e7166SEd Maste       .syntax_error = false,
3415d3e7166SEd Maste       .root = NULL,
3425d3e7166SEd Maste       .stack = &stack,
3435d3e7166SEd Maste   };
3445d3e7166SEd Maste   cbor_item_t* item = cbor_build_uint8(42);
3455d3e7166SEd Maste 
3465d3e7166SEd Maste   WITH_MOCK_MALLOC({ _cbor_builder_append(item, &context); }, 1, REALLOC_FAIL);
3475d3e7166SEd Maste 
3485d3e7166SEd Maste   assert_true(context.creation_failed);
3495d3e7166SEd Maste   assert_false(context.syntax_error);
3505d3e7166SEd Maste   assert_size_equal(context.stack->size, 1);
3515d3e7166SEd Maste 
3525d3e7166SEd Maste   // The stack remains unchanged
3535d3e7166SEd Maste   cbor_item_t* map = stack.top->item;
3545d3e7166SEd Maste   assert_size_equal(cbor_refcount(map), 1);
3555d3e7166SEd Maste   assert_true(cbor_isa_map(map));
3565d3e7166SEd Maste   assert_size_equal(cbor_map_size(map), 0);
3575d3e7166SEd Maste 
3585d3e7166SEd Maste   // item free'd by _cbor_builder_append
3595d3e7166SEd Maste   cbor_decref(&map);
3605d3e7166SEd Maste   _cbor_stack_pop(&stack);
3615d3e7166SEd Maste }
3625d3e7166SEd Maste 
3635d3e7166SEd Maste // Size 1 array start, but we get an indef break
3645d3e7166SEd Maste unsigned char invalid_indef_break_data[] = {0x81, 0xFF};
3655d3e7166SEd Maste static void test_invalid_indef_break(void** _CBOR_UNUSED(_state)) {
3665d3e7166SEd Maste   struct cbor_load_result res;
3675d3e7166SEd Maste   cbor_item_t* item = cbor_load(invalid_indef_break_data, 2, &res);
3685d3e7166SEd Maste 
3695d3e7166SEd Maste   assert_null(item);
3705d3e7166SEd Maste   assert_size_equal(res.read, 2);
3715d3e7166SEd Maste   assert_true(res.error.code == CBOR_ERR_SYNTAXERROR);
3725d3e7166SEd Maste }
3735d3e7166SEd Maste 
374*abd87254SEd Maste static void test_invalid_state_indef_break(void** _CBOR_UNUSED(_state)) {
375*abd87254SEd Maste   struct _cbor_stack stack = _cbor_stack_init();
376*abd87254SEd Maste   assert_non_null(_cbor_stack_push(&stack, cbor_new_int8(), /*subitems=*/0));
377*abd87254SEd Maste   struct _cbor_decoder_context context = {
378*abd87254SEd Maste       .creation_failed = false,
379*abd87254SEd Maste       .syntax_error = false,
380*abd87254SEd Maste       .root = NULL,
381*abd87254SEd Maste       .stack = &stack,
382*abd87254SEd Maste   };
383*abd87254SEd Maste 
384*abd87254SEd Maste   cbor_builder_indef_break_callback(&context);
385*abd87254SEd Maste 
386*abd87254SEd Maste   assert_false(context.creation_failed);
387*abd87254SEd Maste   assert_true(context.syntax_error);
388*abd87254SEd Maste   assert_size_equal(context.stack->size, 1);
389*abd87254SEd Maste   // The stack remains unchanged
390*abd87254SEd Maste   cbor_item_t* small_int = stack.top->item;
391*abd87254SEd Maste   assert_size_equal(cbor_refcount(small_int), 1);
392*abd87254SEd Maste   assert_true(cbor_isa_uint(small_int));
393*abd87254SEd Maste 
394*abd87254SEd Maste   cbor_decref(&small_int);
395*abd87254SEd Maste   _cbor_stack_pop(&stack);
396*abd87254SEd Maste }
397*abd87254SEd Maste 
39810ff414cSEd Maste int main(void) {
39910ff414cSEd Maste   const struct CMUnitTest tests[] = {
4005d3e7166SEd Maste       cmocka_unit_test(test_default_callbacks),
4015d3e7166SEd Maste       cmocka_unit_test(test_builder_byte_string_callback_append),
4025d3e7166SEd Maste       cmocka_unit_test(test_builder_byte_string_callback_append_alloc_failure),
4035d3e7166SEd Maste       cmocka_unit_test(
4045d3e7166SEd Maste           test_builder_byte_string_callback_append_item_alloc_failure),
4055d3e7166SEd Maste       cmocka_unit_test(
4065d3e7166SEd Maste           test_builder_byte_string_callback_append_parent_alloc_failure),
4075d3e7166SEd Maste       cmocka_unit_test(test_builder_string_callback_append),
4085d3e7166SEd Maste       cmocka_unit_test(test_builder_string_callback_append_alloc_failure),
4095d3e7166SEd Maste       cmocka_unit_test(test_builder_string_callback_append_item_alloc_failure),
4105d3e7166SEd Maste       cmocka_unit_test(
4115d3e7166SEd Maste           test_builder_string_callback_append_parent_alloc_failure),
4125d3e7166SEd Maste       cmocka_unit_test(test_append_array_failure),
4135d3e7166SEd Maste       cmocka_unit_test(test_append_map_failure),
4145d3e7166SEd Maste       cmocka_unit_test(test_invalid_indef_break),
415*abd87254SEd Maste       cmocka_unit_test(test_invalid_state_indef_break),
4165d3e7166SEd Maste   };
41710ff414cSEd Maste 
4185d3e7166SEd Maste   cmocka_run_group_tests(tests, NULL, NULL);
41910ff414cSEd Maste }
420