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