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 #include "assertions.h" 8 #include "cbor.h" 9 #include "cbor/internal/builder_callbacks.h" 10 #include "cbor/internal/stack.h" 11 #include "test_allocator.h" 12 13 unsigned char data[] = { 14 0x93, 0x01, 0x19, 0x01, 0x01, 0x1A, 0x00, 0x01, 0x05, 0xB8, 0x1B, 0x00, 15 0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8, 0xB8, 0x20, 0x39, 0x01, 0x00, 0x3A, 16 0x00, 0x01, 0x05, 0xB7, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x8F, 0x5A, 0xE8, 17 0xB7, 0x5F, 0x41, 0x01, 0x41, 0x02, 0xFF, 0x7F, 0x61, 0x61, 0x61, 0x62, 18 0xFF, 0x9F, 0xFF, 0xA1, 0x61, 0x61, 0x61, 0x62, 0xC0, 0xBF, 0xFF, 0xF9, 19 0x3C, 0x00, 0xFA, 0x47, 0xC3, 0x50, 0x00, 0xFB, 0x7E, 0x37, 0xE4, 0x3C, 20 0x88, 0x00, 0x75, 0x9C, 0xF6, 0xF7, 0xF5}; 21 22 /* Exercise the default callbacks */ 23 static void test_default_callbacks(void** _CBOR_UNUSED(_state)) { 24 size_t read = 0; 25 while (read < 79) { 26 struct cbor_decoder_result result = 27 cbor_stream_decode(data + read, 79 - read, &cbor_empty_callbacks, NULL); 28 read += result.read; 29 } 30 } 31 32 unsigned char bytestring_data[] = {0x01, 0x02, 0x03}; 33 static void test_builder_byte_string_callback_append( 34 void** _CBOR_UNUSED(_state)) { 35 struct _cbor_stack stack = _cbor_stack_init(); 36 assert_non_null( 37 _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0)); 38 struct _cbor_decoder_context context = { 39 .creation_failed = false, 40 .syntax_error = false, 41 .root = NULL, 42 .stack = &stack, 43 }; 44 45 cbor_builder_byte_string_callback(&context, bytestring_data, 3); 46 47 assert_false(context.creation_failed); 48 assert_false(context.syntax_error); 49 assert_size_equal(context.stack->size, 1); 50 51 cbor_item_t* bytestring = stack.top->item; 52 assert_size_equal(cbor_refcount(bytestring), 1); 53 assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING); 54 assert_true(cbor_isa_bytestring(bytestring)); 55 assert_size_equal(cbor_bytestring_length(bytestring), 0); 56 assert_true(cbor_bytestring_is_indefinite(bytestring)); 57 assert_size_equal(cbor_bytestring_chunk_count(bytestring), 1); 58 59 cbor_item_t* chunk = cbor_bytestring_chunks_handle(bytestring)[0]; 60 assert_size_equal(cbor_refcount(chunk), 1); 61 assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING); 62 assert_true(cbor_isa_bytestring(chunk)); 63 assert_true(cbor_bytestring_is_definite(chunk)); 64 assert_size_equal(cbor_bytestring_length(chunk), 3); 65 assert_memory_equal(cbor_bytestring_handle(chunk), bytestring_data, 3); 66 // Data is copied 67 assert_ptr_not_equal(cbor_bytestring_handle(chunk), bytestring_data); 68 69 cbor_decref(&bytestring); 70 _cbor_stack_pop(&stack); 71 } 72 73 static void test_builder_byte_string_callback_append_alloc_failure( 74 void** _CBOR_UNUSED(_state)) { 75 struct _cbor_stack stack = _cbor_stack_init(); 76 assert_non_null( 77 _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0)); 78 struct _cbor_decoder_context context = { 79 .creation_failed = false, 80 .syntax_error = false, 81 .root = NULL, 82 .stack = &stack, 83 }; 84 85 WITH_FAILING_MALLOC( 86 { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }); 87 88 assert_true(context.creation_failed); 89 assert_false(context.syntax_error); 90 assert_size_equal(context.stack->size, 1); 91 92 // The stack remains unchanged 93 cbor_item_t* bytestring = stack.top->item; 94 assert_size_equal(cbor_refcount(bytestring), 1); 95 assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING); 96 assert_true(cbor_isa_bytestring(bytestring)); 97 assert_size_equal(cbor_bytestring_length(bytestring), 0); 98 assert_true(cbor_bytestring_is_indefinite(bytestring)); 99 assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0); 100 101 cbor_decref(&bytestring); 102 _cbor_stack_pop(&stack); 103 } 104 105 static void test_builder_byte_string_callback_append_item_alloc_failure( 106 void** _CBOR_UNUSED(_state)) { 107 struct _cbor_stack stack = _cbor_stack_init(); 108 assert_non_null( 109 _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0)); 110 struct _cbor_decoder_context context = { 111 .creation_failed = false, 112 .syntax_error = false, 113 .root = NULL, 114 .stack = &stack, 115 }; 116 117 // Allocate new data block, but fail to allocate a new item with it 118 WITH_MOCK_MALLOC( 119 { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 2, 120 MALLOC, MALLOC_FAIL); 121 122 assert_true(context.creation_failed); 123 assert_false(context.syntax_error); 124 assert_size_equal(context.stack->size, 1); 125 126 // The stack remains unchanged 127 cbor_item_t* bytestring = stack.top->item; 128 assert_size_equal(cbor_refcount(bytestring), 1); 129 assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING); 130 assert_true(cbor_isa_bytestring(bytestring)); 131 assert_size_equal(cbor_bytestring_length(bytestring), 0); 132 assert_true(cbor_bytestring_is_indefinite(bytestring)); 133 assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0); 134 135 cbor_decref(&bytestring); 136 _cbor_stack_pop(&stack); 137 } 138 139 static void test_builder_byte_string_callback_append_parent_alloc_failure( 140 void** _CBOR_UNUSED(_state)) { 141 struct _cbor_stack stack = _cbor_stack_init(); 142 assert_non_null( 143 _cbor_stack_push(&stack, cbor_new_indefinite_bytestring(), 0)); 144 struct _cbor_decoder_context context = { 145 .creation_failed = false, 146 .syntax_error = false, 147 .root = NULL, 148 .stack = &stack, 149 }; 150 151 // Allocate new item, but fail to push it into the parent on the stack 152 WITH_MOCK_MALLOC( 153 { cbor_builder_byte_string_callback(&context, bytestring_data, 3); }, 3, 154 MALLOC, MALLOC, REALLOC_FAIL); 155 156 assert_true(context.creation_failed); 157 assert_false(context.syntax_error); 158 assert_size_equal(context.stack->size, 1); 159 160 // The stack remains unchanged 161 cbor_item_t* bytestring = stack.top->item; 162 assert_size_equal(cbor_refcount(bytestring), 1); 163 assert_true(cbor_typeof(bytestring) == CBOR_TYPE_BYTESTRING); 164 assert_true(cbor_isa_bytestring(bytestring)); 165 assert_size_equal(cbor_bytestring_length(bytestring), 0); 166 assert_true(cbor_bytestring_is_indefinite(bytestring)); 167 assert_size_equal(cbor_bytestring_chunk_count(bytestring), 0); 168 169 cbor_decref(&bytestring); 170 _cbor_stack_pop(&stack); 171 } 172 173 unsigned char string_data[] = {0x61, 0x62, 0x63}; 174 static void test_builder_string_callback_append(void** _CBOR_UNUSED(_state)) { 175 struct _cbor_stack stack = _cbor_stack_init(); 176 assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0)); 177 struct _cbor_decoder_context context = { 178 .creation_failed = false, 179 .syntax_error = false, 180 .root = NULL, 181 .stack = &stack, 182 }; 183 184 cbor_builder_string_callback(&context, string_data, 3); 185 186 assert_false(context.creation_failed); 187 assert_false(context.syntax_error); 188 assert_size_equal(context.stack->size, 1); 189 190 cbor_item_t* string = stack.top->item; 191 assert_size_equal(cbor_refcount(string), 1); 192 assert_true(cbor_isa_string(string)); 193 assert_size_equal(cbor_string_length(string), 0); 194 assert_true(cbor_string_is_indefinite(string)); 195 assert_size_equal(cbor_string_chunk_count(string), 1); 196 197 cbor_item_t* chunk = cbor_string_chunks_handle(string)[0]; 198 assert_size_equal(cbor_refcount(chunk), 1); 199 assert_true(cbor_isa_string(chunk)); 200 assert_true(cbor_string_is_definite(chunk)); 201 assert_size_equal(cbor_string_length(chunk), 3); 202 assert_memory_equal(cbor_string_handle(chunk), "abc", 3); 203 // Data is copied 204 assert_ptr_not_equal(cbor_string_handle(chunk), string_data); 205 206 cbor_decref(&string); 207 _cbor_stack_pop(&stack); 208 } 209 210 static void test_builder_string_callback_append_alloc_failure( 211 void** _CBOR_UNUSED(_state)) { 212 struct _cbor_stack stack = _cbor_stack_init(); 213 assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0)); 214 struct _cbor_decoder_context context = { 215 .creation_failed = false, 216 .syntax_error = false, 217 .root = NULL, 218 .stack = &stack, 219 }; 220 221 WITH_FAILING_MALLOC( 222 { cbor_builder_string_callback(&context, string_data, 3); }); 223 224 assert_true(context.creation_failed); 225 assert_false(context.syntax_error); 226 assert_size_equal(context.stack->size, 1); 227 228 // The stack remains unchanged 229 cbor_item_t* string = stack.top->item; 230 assert_size_equal(cbor_refcount(string), 1); 231 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 232 assert_true(cbor_isa_string(string)); 233 assert_size_equal(cbor_string_length(string), 0); 234 assert_true(cbor_string_is_indefinite(string)); 235 assert_size_equal(cbor_string_chunk_count(string), 0); 236 237 cbor_decref(&string); 238 _cbor_stack_pop(&stack); 239 } 240 241 static void test_builder_string_callback_append_item_alloc_failure( 242 void** _CBOR_UNUSED(_state)) { 243 struct _cbor_stack stack = _cbor_stack_init(); 244 assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0)); 245 struct _cbor_decoder_context context = { 246 .creation_failed = false, 247 .syntax_error = false, 248 .root = NULL, 249 .stack = &stack, 250 }; 251 252 // Allocate new data block, but fail to allocate a new item with it 253 WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); }, 254 2, MALLOC, MALLOC_FAIL); 255 256 assert_true(context.creation_failed); 257 assert_false(context.syntax_error); 258 assert_size_equal(context.stack->size, 1); 259 260 // The stack remains unchanged 261 cbor_item_t* string = stack.top->item; 262 assert_size_equal(cbor_refcount(string), 1); 263 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 264 assert_true(cbor_isa_string(string)); 265 assert_size_equal(cbor_string_length(string), 0); 266 assert_true(cbor_string_is_indefinite(string)); 267 assert_size_equal(cbor_string_chunk_count(string), 0); 268 269 cbor_decref(&string); 270 _cbor_stack_pop(&stack); 271 } 272 273 static void test_builder_string_callback_append_parent_alloc_failure( 274 void** _CBOR_UNUSED(_state)) { 275 struct _cbor_stack stack = _cbor_stack_init(); 276 assert_non_null(_cbor_stack_push(&stack, cbor_new_indefinite_string(), 0)); 277 struct _cbor_decoder_context context = { 278 .creation_failed = false, 279 .syntax_error = false, 280 .root = NULL, 281 .stack = &stack, 282 }; 283 284 // Allocate new item, but fail to push it into the parent on the stack 285 WITH_MOCK_MALLOC({ cbor_builder_string_callback(&context, string_data, 3); }, 286 3, MALLOC, MALLOC, REALLOC_FAIL); 287 288 assert_true(context.creation_failed); 289 assert_false(context.syntax_error); 290 assert_size_equal(context.stack->size, 1); 291 292 // The stack remains unchanged 293 cbor_item_t* string = stack.top->item; 294 assert_size_equal(cbor_refcount(string), 1); 295 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 296 assert_true(cbor_isa_string(string)); 297 assert_size_equal(cbor_string_length(string), 0); 298 assert_true(cbor_string_is_indefinite(string)); 299 assert_size_equal(cbor_string_chunk_count(string), 0); 300 301 cbor_decref(&string); 302 _cbor_stack_pop(&stack); 303 } 304 305 static void test_append_array_failure(void** _CBOR_UNUSED(_state)) { 306 struct _cbor_stack stack = _cbor_stack_init(); 307 assert_non_null(_cbor_stack_push(&stack, cbor_new_definite_array(0), 0)); 308 stack.top->subitems = 1; 309 struct _cbor_decoder_context context = { 310 .creation_failed = false, 311 .syntax_error = false, 312 .root = NULL, 313 .stack = &stack, 314 }; 315 cbor_item_t* item = cbor_build_uint8(42); 316 317 _cbor_builder_append(item, &context); 318 319 assert_true(context.creation_failed); 320 assert_false(context.syntax_error); 321 assert_size_equal(context.stack->size, 1); 322 323 // The stack remains unchanged 324 cbor_item_t* array = stack.top->item; 325 assert_size_equal(cbor_refcount(array), 1); 326 assert_true(cbor_isa_array(array)); 327 assert_size_equal(cbor_array_size(array), 0); 328 329 // item free'd by _cbor_builder_append 330 cbor_decref(&array); 331 _cbor_stack_pop(&stack); 332 } 333 334 static void test_append_map_failure(void** _CBOR_UNUSED(_state)) { 335 struct _cbor_stack stack = _cbor_stack_init(); 336 assert_non_null( 337 _cbor_stack_push(&stack, cbor_new_indefinite_map(), /*subitems=*/0)); 338 struct _cbor_decoder_context context = { 339 .creation_failed = false, 340 .syntax_error = false, 341 .root = NULL, 342 .stack = &stack, 343 }; 344 cbor_item_t* item = cbor_build_uint8(42); 345 346 WITH_MOCK_MALLOC({ _cbor_builder_append(item, &context); }, 1, REALLOC_FAIL); 347 348 assert_true(context.creation_failed); 349 assert_false(context.syntax_error); 350 assert_size_equal(context.stack->size, 1); 351 352 // The stack remains unchanged 353 cbor_item_t* map = stack.top->item; 354 assert_size_equal(cbor_refcount(map), 1); 355 assert_true(cbor_isa_map(map)); 356 assert_size_equal(cbor_map_size(map), 0); 357 358 // item free'd by _cbor_builder_append 359 cbor_decref(&map); 360 _cbor_stack_pop(&stack); 361 } 362 363 // Size 1 array start, but we get an indef break 364 unsigned char invalid_indef_break_data[] = {0x81, 0xFF}; 365 static void test_invalid_indef_break(void** _CBOR_UNUSED(_state)) { 366 struct cbor_load_result res; 367 cbor_item_t* item = cbor_load(invalid_indef_break_data, 2, &res); 368 369 assert_null(item); 370 assert_size_equal(res.read, 2); 371 assert_true(res.error.code == CBOR_ERR_SYNTAXERROR); 372 } 373 374 static void test_invalid_state_indef_break(void** _CBOR_UNUSED(_state)) { 375 struct _cbor_stack stack = _cbor_stack_init(); 376 assert_non_null(_cbor_stack_push(&stack, cbor_new_int8(), /*subitems=*/0)); 377 struct _cbor_decoder_context context = { 378 .creation_failed = false, 379 .syntax_error = false, 380 .root = NULL, 381 .stack = &stack, 382 }; 383 384 cbor_builder_indef_break_callback(&context); 385 386 assert_false(context.creation_failed); 387 assert_true(context.syntax_error); 388 assert_size_equal(context.stack->size, 1); 389 // The stack remains unchanged 390 cbor_item_t* small_int = stack.top->item; 391 assert_size_equal(cbor_refcount(small_int), 1); 392 assert_true(cbor_isa_uint(small_int)); 393 394 cbor_decref(&small_int); 395 _cbor_stack_pop(&stack); 396 } 397 398 int main(void) { 399 const struct CMUnitTest tests[] = { 400 cmocka_unit_test(test_default_callbacks), 401 cmocka_unit_test(test_builder_byte_string_callback_append), 402 cmocka_unit_test(test_builder_byte_string_callback_append_alloc_failure), 403 cmocka_unit_test( 404 test_builder_byte_string_callback_append_item_alloc_failure), 405 cmocka_unit_test( 406 test_builder_byte_string_callback_append_parent_alloc_failure), 407 cmocka_unit_test(test_builder_string_callback_append), 408 cmocka_unit_test(test_builder_string_callback_append_alloc_failure), 409 cmocka_unit_test(test_builder_string_callback_append_item_alloc_failure), 410 cmocka_unit_test( 411 test_builder_string_callback_append_parent_alloc_failure), 412 cmocka_unit_test(test_append_array_failure), 413 cmocka_unit_test(test_append_map_failure), 414 cmocka_unit_test(test_invalid_indef_break), 415 cmocka_unit_test(test_invalid_state_indef_break), 416 }; 417 418 cmocka_run_group_tests(tests, NULL, NULL); 419 } 420