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 <string.h> 9 #include "assertions.h" 10 #include "cbor.h" 11 #include "test_allocator.h" 12 13 cbor_item_t *string; 14 struct cbor_load_result res; 15 16 unsigned char empty_string_data[] = {0x60}; 17 18 static void test_empty_string(void **_CBOR_UNUSED(_state)) { 19 string = cbor_load(empty_string_data, 1, &res); 20 assert_non_null(string); 21 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 22 assert_true(cbor_isa_string(string)); 23 assert_size_equal(cbor_string_length(string), 0); 24 assert_size_equal(cbor_string_codepoint_count(string), 0); 25 assert_true(res.read == 1); 26 cbor_decref(&string); 27 assert_null(string); 28 } 29 30 unsigned char short_string_data[] = {0x6C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 31 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21}; 32 33 /* 0x60 + 12 | Hello world! */ 34 static void test_short_string(void **_CBOR_UNUSED(_state)) { 35 string = cbor_load(short_string_data, 13, &res); 36 assert_non_null(string); 37 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 38 assert_true(cbor_isa_string(string)); 39 assert_size_equal(cbor_string_length(string), 12); 40 assert_size_equal(cbor_string_codepoint_count(string), 12); 41 assert_memory_equal(&"Hello world!", cbor_string_handle(string), 12); 42 assert_true(res.read == 13); 43 cbor_decref(&string); 44 assert_null(string); 45 } 46 47 unsigned char short_multibyte_string_data[] = { 48 0x6F, 0xC4, 0x8C, 0x61, 0x75, 0x65, 0x73, 0x20, 49 0xC3, 0x9F, 0x76, 0xC4, 0x9B, 0x74, 0x65, 0x21}; 50 51 /* 0x60 + 15 | Čaues ßvěte! */ 52 static void test_short_multibyte_string(void **_CBOR_UNUSED(_state)) { 53 string = cbor_load(short_multibyte_string_data, 16, &res); 54 assert_non_null(string); 55 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 56 assert_true(cbor_isa_string(string)); 57 assert_size_equal(cbor_string_length(string), 15); 58 assert_size_equal(cbor_string_codepoint_count(string), 12); 59 assert_memory_equal(&"Čaues ßvěte!", cbor_string_handle(string), 15); 60 assert_true(res.read == 16); 61 cbor_decref(&string); 62 assert_null(string); 63 } 64 65 unsigned char int8_string_data[] = { 66 0x78, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75, 67 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 68 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63, 69 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 70 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44, 71 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C, 72 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20, 73 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C, 74 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72, 75 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66, 76 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E, 77 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20, 78 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E}; 79 80 /* 150 | Lorem ....*/ 81 static void test_int8_string(void **_CBOR_UNUSED(_state)) { 82 string = cbor_load(int8_string_data, 152, &res); 83 assert_non_null(string); 84 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 85 assert_true(cbor_isa_string(string)); 86 assert_size_equal(cbor_string_length(string), 150); 87 assert_size_equal(cbor_string_codepoint_count(string), 150); 88 assert_memory_equal( 89 &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.", 90 cbor_string_handle(string), 91 150 92 ); 93 assert_true(res.read == 152); 94 cbor_decref(&string); 95 assert_null(string); 96 } 97 98 unsigned char int16_string_data[] = { 99 0x79, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 100 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 101 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 102 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 103 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 104 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 105 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 106 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 107 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 108 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 109 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 110 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 111 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E}; 112 /* 150 | Lorem ....*/ 113 /* This valid but not realistic - length 150 could be encoded in a single 114 * uint8_t (but we need to keep the test files reasonably compact) */ 115 static void test_int16_string(void **_CBOR_UNUSED(_state)) { 116 string = cbor_load(int16_string_data, 153, &res); 117 assert_non_null(string); 118 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 119 assert_true(cbor_isa_string(string)); 120 assert_size_equal(cbor_string_length(string), 150); 121 assert_size_equal(cbor_string_codepoint_count(string), 150); 122 assert_memory_equal( 123 &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.", 124 cbor_string_handle(string), 125 150 126 ); 127 assert_true(res.read == 153); 128 cbor_decref(&string); 129 assert_null(string); 130 } 131 132 unsigned char int32_string_data[] = { 133 0x7A, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20, 0x69, 134 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 135 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20, 0x63, 0x6F, 0x6E, 136 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 137 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 138 0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 0x6D, 0x69, 0x20, 0x74, 139 0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 0x61, 0x63, 0x75, 0x6C, 140 0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 141 0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 0x69, 0x73, 0x2C, 0x20, 142 0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 0x6D, 0x20, 0x6E, 0x6F, 143 0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 0x20, 0x4D, 0x61, 0x65, 144 0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 0x20, 0x6A, 0x75, 0x73, 145 0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 0x72, 0x65, 0x2E}; 146 147 /* 150 | Lorem ....*/ 148 static void test_int32_string(void **_CBOR_UNUSED(_state)) { 149 string = cbor_load(int32_string_data, 155, &res); 150 assert_non_null(string); 151 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 152 assert_true(cbor_isa_string(string)); 153 assert_size_equal(cbor_string_length(string), 150); 154 assert_size_equal(cbor_string_codepoint_count(string), 150); 155 assert_memory_equal( 156 &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.", 157 cbor_string_handle(string), 158 150 159 ); 160 assert_true(res.read == 155); 161 cbor_decref(&string); 162 assert_null(string); 163 } 164 165 unsigned char int64_string_data[] = { 166 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x4C, 0x6F, 0x72, 167 0x65, 0x6D, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 168 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 169 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 170 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 171 0x65, 0x6C, 0x69, 0x74, 0x2E, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x63, 0x20, 172 0x6D, 0x69, 0x20, 0x74, 0x65, 0x6C, 0x6C, 0x75, 0x73, 0x2C, 0x20, 0x69, 173 0x61, 0x63, 0x75, 0x6C, 0x69, 0x73, 0x20, 0x6E, 0x65, 0x63, 0x20, 0x76, 174 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6C, 0x75, 0x6D, 0x20, 0x71, 0x75, 175 0x69, 0x73, 0x2C, 0x20, 0x66, 0x65, 0x72, 0x6D, 0x65, 0x6E, 0x74, 0x75, 176 0x6D, 0x20, 0x6E, 0x6F, 0x6E, 0x20, 0x66, 0x65, 0x6C, 0x69, 0x73, 0x2E, 177 0x20, 0x4D, 0x61, 0x65, 0x63, 0x65, 0x6E, 0x61, 0x73, 0x20, 0x75, 0x74, 178 0x20, 0x6A, 0x75, 0x73, 0x74, 0x6F, 0x20, 0x70, 0x6F, 0x73, 0x75, 0x65, 179 0x72, 0x65, 0x2E}; 180 181 /* 150 | Lorem ....*/ 182 static void test_int64_string(void **_CBOR_UNUSED(_state)) { 183 string = cbor_load(int64_string_data, 159, &res); 184 assert_non_null(string); 185 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 186 assert_true(cbor_isa_string(string)); 187 assert_size_equal(cbor_string_length(string), 150); 188 assert_size_equal(cbor_string_codepoint_count(string), 150); 189 assert_memory_equal( 190 &"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.", 191 cbor_string_handle(string), 192 150 193 ); 194 assert_true(res.read == 159); 195 cbor_decref(&string); 196 assert_null(string); 197 } 198 199 unsigned char short_indef_string_data[] = {0x7F, 0x78, 0x01, 0x65, 0xFF, 0xFF}; 200 201 /* start | string | break| extra 202 */ 203 204 static void test_short_indef_string(void **_CBOR_UNUSED(_state)) { 205 string = cbor_load(short_indef_string_data, 6, &res); 206 assert_non_null(string); 207 assert_true(cbor_typeof(string) == CBOR_TYPE_STRING); 208 assert_true(cbor_isa_string(string)); 209 assert_true(cbor_string_length(string) == 0); 210 assert_true(cbor_string_is_indefinite(string)); 211 assert_true(cbor_string_chunk_count(string) == 1); 212 assert_true(res.read == 5); 213 assert_true(cbor_isa_string(cbor_string_chunks_handle(string)[0])); 214 assert_true(cbor_string_length(cbor_string_chunks_handle(string)[0]) == 1); 215 assert_true(*cbor_string_handle(cbor_string_chunks_handle(string)[0]) == 'e'); 216 cbor_decref(&string); 217 assert_null(string); 218 } 219 220 static void test_inline_creation(void **_CBOR_UNUSED(_state)) { 221 string = cbor_build_string("Hello!"); 222 assert_memory_equal(cbor_string_handle(string), "Hello!", strlen("Hello!")); 223 cbor_decref(&string); 224 } 225 226 static void test_string_creation(void **_CBOR_UNUSED(_state)) { 227 WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_string()); }); 228 229 WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_string()); }); 230 WITH_MOCK_MALLOC({ assert_null(cbor_new_indefinite_string()); }, 2, MALLOC, 231 MALLOC_FAIL); 232 233 WITH_FAILING_MALLOC({ assert_null(cbor_build_string("Test")); }); 234 WITH_MOCK_MALLOC({ assert_null(cbor_build_string("Test")); }, 2, MALLOC, 235 MALLOC_FAIL); 236 237 WITH_FAILING_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); }); 238 WITH_MOCK_MALLOC({ assert_null(cbor_build_stringn("Test", 4)); }, 2, MALLOC, 239 MALLOC_FAIL); 240 } 241 242 static void test_string_add_chunk(void **_CBOR_UNUSED(_state)) { 243 WITH_MOCK_MALLOC( 244 { 245 cbor_item_t *string = cbor_new_indefinite_string(); 246 cbor_item_t *chunk = cbor_build_string("Hello!"); 247 248 assert_false(cbor_string_add_chunk(string, chunk)); 249 assert_size_equal(cbor_string_chunk_count(string), 0); 250 assert_size_equal(((struct cbor_indefinite_string_data *)string->data) 251 ->chunk_capacity, 252 0); 253 254 cbor_decref(&chunk); 255 cbor_decref(&string); 256 }, 257 5, MALLOC, MALLOC, MALLOC, MALLOC, REALLOC_FAIL); 258 } 259 260 static void test_add_chunk_reallocation_overflow(void **_CBOR_UNUSED(_state)) { 261 string = cbor_new_indefinite_string(); 262 cbor_item_t *chunk = cbor_build_string("Hello!"); 263 struct cbor_indefinite_string_data *metadata = 264 (struct cbor_indefinite_string_data *)string->data; 265 // Pretend we already have many chunks allocated 266 metadata->chunk_count = SIZE_MAX; 267 metadata->chunk_capacity = SIZE_MAX; 268 269 assert_false(cbor_string_add_chunk(string, chunk)); 270 assert_size_equal(cbor_refcount(chunk), 1); 271 272 metadata->chunk_count = 0; 273 metadata->chunk_capacity = 0; 274 cbor_decref(&chunk); 275 cbor_decref(&string); 276 } 277 278 int main(void) { 279 const struct CMUnitTest tests[] = { 280 cmocka_unit_test(test_empty_string), 281 cmocka_unit_test(test_short_string), 282 cmocka_unit_test(test_short_multibyte_string), 283 cmocka_unit_test(test_int8_string), 284 cmocka_unit_test(test_int16_string), 285 cmocka_unit_test(test_int32_string), 286 cmocka_unit_test(test_int64_string), 287 cmocka_unit_test(test_short_indef_string), 288 cmocka_unit_test(test_inline_creation), 289 cmocka_unit_test(test_string_creation), 290 cmocka_unit_test(test_string_add_chunk), 291 cmocka_unit_test(test_add_chunk_reallocation_overflow), 292 }; 293 return cmocka_run_group_tests(tests, NULL, NULL); 294 } 295