1 /* 2 * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> 3 * 4 * libcbor is free software; you can redistribute it and/or modify 5 * it under the terms of the MIT license. See LICENSE for details. 6 */ 7 8 #include "assertions.h" 9 #include "cbor.h" 10 #include "test_allocator.h" 11 12 cbor_item_t *arr; 13 struct cbor_load_result res; 14 15 unsigned char data1[] = {0x80, 0xFF}; 16 17 static void test_empty_array(void **_CBOR_UNUSED(_state)) { 18 arr = cbor_load(data1, 2, &res); 19 assert_non_null(arr); 20 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY); 21 assert_true(cbor_isa_array(arr)); 22 assert_true(cbor_array_size(arr) == 0); 23 assert_true(res.read == 1); 24 cbor_decref(&arr); 25 assert_null(arr); 26 } 27 28 unsigned char data2[] = {0x81, 0x01, 0xFF}; 29 30 static void test_simple_array(void **_CBOR_UNUSED(_state)) { 31 arr = cbor_load(data2, 3, &res); 32 assert_non_null(arr); 33 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY); 34 assert_true(cbor_isa_array(arr)); 35 assert_size_equal(cbor_array_size(arr), 1); 36 assert_true(res.read == 2); 37 assert_size_equal(cbor_array_allocated(arr), 1); 38 /* Check the values */ 39 assert_uint8(cbor_array_handle(arr)[0], 1); 40 cbor_item_t *intermediate = cbor_array_get(arr, 0); 41 assert_uint8(intermediate, 1); 42 43 cbor_item_t *new_val = cbor_build_uint8(10); 44 assert_false(cbor_array_set(arr, 1, new_val)); 45 assert_false(cbor_array_set(arr, 3, new_val)); 46 cbor_decref(&new_val); 47 48 cbor_decref(&arr); 49 cbor_decref(&intermediate); 50 assert_null(arr); 51 assert_null(intermediate); 52 } 53 54 unsigned char data3[] = {0x82, 0x01, 0x81, 0x01, 0xFF}; 55 56 static void test_nested_arrays(void **_CBOR_UNUSED(_state)) { 57 arr = cbor_load(data3, 5, &res); 58 assert_non_null(arr); 59 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY); 60 assert_true(cbor_isa_array(arr)); 61 assert_true(cbor_array_size(arr) == 2); 62 assert_true(res.read == 4); 63 /* Check the values */ 64 assert_uint8(cbor_array_handle(arr)[0], 1); 65 66 cbor_item_t *nested = cbor_array_handle(arr)[1]; 67 assert_true(cbor_isa_array(nested)); 68 assert_true(cbor_array_size(nested) == 1); 69 assert_uint8(cbor_array_handle(nested)[0], 1); 70 71 cbor_decref(&arr); 72 assert_null(arr); 73 } 74 75 unsigned char test_indef_arrays_data[] = {0x9f, 0x01, 0x02, 0xFF}; 76 77 static void test_indef_arrays(void **_CBOR_UNUSED(_state)) { 78 arr = cbor_load(test_indef_arrays_data, 4, &res); 79 assert_non_null(arr); 80 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY); 81 assert_true(cbor_isa_array(arr)); 82 assert_true(cbor_array_size(arr) == 2); 83 assert_true(res.read == 4); 84 /* Check the values */ 85 assert_uint8(cbor_array_handle(arr)[0], 1); 86 assert_uint8(cbor_array_handle(arr)[1], 2); 87 88 assert_true(cbor_array_set(arr, 1, cbor_move(cbor_build_uint8(10)))); 89 90 cbor_decref(&arr); 91 assert_null(arr); 92 } 93 94 unsigned char test_nested_indef_arrays_data[] = {0x9f, 0x01, 0x9f, 0x02, 95 0xFF, 0x03, 0xFF}; 96 97 static void test_nested_indef_arrays(void **_CBOR_UNUSED(_state)) { 98 arr = cbor_load(test_nested_indef_arrays_data, 7, &res); 99 assert_non_null(arr); 100 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY); 101 assert_true(cbor_isa_array(arr)); 102 assert_size_equal(cbor_array_size(arr), 3); 103 assert_true(res.read == 7); 104 /* Check the values */ 105 assert_uint8(cbor_array_handle(arr)[0], 1); 106 107 cbor_item_t *nested = cbor_array_handle(arr)[1]; 108 assert_true(cbor_isa_array(nested)); 109 assert_true(cbor_array_size(nested) == 1); 110 assert_uint8(cbor_array_handle(nested)[0], 2); 111 112 cbor_decref(&arr); 113 assert_null(arr); 114 } 115 116 static void test_array_replace(void **_CBOR_UNUSED(_state)) { 117 cbor_item_t *array = cbor_new_definite_array(2); 118 assert_size_equal(cbor_array_size(array), 0); 119 cbor_item_t *one = cbor_build_uint8(1); 120 cbor_item_t *three = cbor_build_uint8(3); 121 assert_size_equal(cbor_refcount(one), 1); 122 assert_size_equal(cbor_refcount(three), 1); 123 124 // No item to replace 125 assert_false(cbor_array_replace(array, 0, three)); 126 assert_size_equal(cbor_refcount(three), 1); 127 128 // Add items [1, 2] 129 assert_true(cbor_array_push(array, one)); 130 assert_true(cbor_array_push(array, cbor_move(cbor_build_uint8(2)))); 131 assert_size_equal(cbor_refcount(one), 2); 132 assert_size_equal(cbor_array_size(array), 2); 133 134 // Array has only two items 135 assert_false(cbor_array_replace(array, 2, three)); 136 assert_size_equal(cbor_refcount(three), 1); 137 138 // Change [1, 2] to [3, 2] 139 assert_true(cbor_array_replace(array, 0, three)); 140 assert_size_equal(cbor_refcount(one), 1); 141 assert_size_equal(cbor_refcount(three), 2); 142 assert_uint8(cbor_move(cbor_array_get(array, 0)), 3); 143 assert_uint8(cbor_move(cbor_array_get(array, 1)), 2); 144 145 cbor_decref(&one); 146 cbor_decref(&three); 147 cbor_decref(&array); 148 } 149 150 static void test_array_push_overflow(void **_CBOR_UNUSED(_state)) { 151 cbor_item_t *array = cbor_new_indefinite_array(); 152 cbor_item_t *one = cbor_build_uint8(1); 153 struct _cbor_array_metadata *metadata = 154 (struct _cbor_array_metadata *)&array->metadata; 155 // Pretend we already have a huge block allocated 156 metadata->allocated = SIZE_MAX; 157 metadata->end_ptr = SIZE_MAX; 158 159 assert_false(cbor_array_push(array, one)); 160 assert_size_equal(cbor_refcount(one), 1); 161 162 cbor_decref(&one); 163 metadata->allocated = 0; 164 metadata->end_ptr = 0; 165 cbor_decref(&array); 166 } 167 168 static void test_array_creation(void **_CBOR_UNUSED(_state)) { 169 WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_array(42)); }); 170 WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_array(42)); }, 2, MALLOC, 171 MALLOC_FAIL); 172 173 WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_array()); }); 174 } 175 176 static void test_array_push(void **_CBOR_UNUSED(_state)) { 177 WITH_MOCK_MALLOC( 178 { 179 cbor_item_t *array = cbor_new_indefinite_array(); 180 cbor_item_t *string = cbor_build_string("Hello!"); 181 182 assert_false(cbor_array_push(array, string)); 183 assert_size_equal(cbor_array_allocated(array), 0); 184 assert_null(array->data); 185 assert_size_equal(array->metadata.array_metadata.end_ptr, 0); 186 187 cbor_decref(&string); 188 cbor_decref(&array); 189 }, 190 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL); 191 } 192 193 static unsigned char simple_indef_array[] = {0x9F, 0x01, 0x02, 0xFF}; 194 static void test_indef_array_decode(void **_CBOR_UNUSED(_state)) { 195 WITH_MOCK_MALLOC( 196 { 197 cbor_item_t *array; 198 struct cbor_load_result res; 199 array = cbor_load(simple_indef_array, 4, &res); 200 201 assert_null(array); 202 assert_size_equal(res.error.code, CBOR_ERR_MEMERROR); 203 }, 204 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL); 205 } 206 207 int main(void) { 208 const struct CMUnitTest tests[] = { 209 cmocka_unit_test(test_empty_array), 210 cmocka_unit_test(test_simple_array), 211 cmocka_unit_test(test_nested_arrays), 212 cmocka_unit_test(test_indef_arrays), 213 cmocka_unit_test(test_nested_indef_arrays), 214 cmocka_unit_test(test_array_replace), 215 cmocka_unit_test(test_array_push_overflow), 216 cmocka_unit_test(test_array_creation), 217 cmocka_unit_test(test_array_push), 218 cmocka_unit_test(test_indef_array_decode), 219 }; 220 221 return cmocka_run_group_tests(tests, NULL, NULL); 222 } 223