xref: /freebsd/contrib/libcbor/test/string_test.c (revision 02e9120893770924227138ba49df1edb3896112a)
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