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 <setjmp.h>
9 #include <stdarg.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13
14 #include <cmocka.h>
15
16 #include "assertions.h"
17 #include "cbor.h"
18 #include "test_allocator.h"
19
20 cbor_item_t* map;
21 struct cbor_load_result res;
22
23 unsigned char empty_map[] = {0xA0};
24
test_empty_map(void ** _state _CBOR_UNUSED)25 static void test_empty_map(void** _state _CBOR_UNUSED) {
26 map = cbor_load(empty_map, 1, &res);
27 assert_non_null(map);
28 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
29 assert_true(cbor_isa_map(map));
30 assert_true(cbor_map_size(map) == 0);
31 assert_true(res.read == 1);
32 assert_size_equal(cbor_map_allocated(map), 0);
33 cbor_decref(&map);
34 assert_null(map);
35 }
36
37 unsigned char simple_map[] = {0xA2, 0x01, 0x02, 0x03, 0x04};
38
39 /* {1: 2, 3: 4} */
test_simple_map(void ** _state _CBOR_UNUSED)40 static void test_simple_map(void** _state _CBOR_UNUSED) {
41 map = cbor_load(simple_map, 5, &res);
42 assert_non_null(map);
43 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
44 assert_true(cbor_isa_map(map));
45 assert_true(cbor_map_is_definite(map));
46 assert_true(cbor_map_size(map) == 2);
47 assert_true(res.read == 5);
48 struct cbor_pair* handle = cbor_map_handle(map);
49 assert_uint8(handle[0].key, 1);
50 assert_uint8(handle[0].value, 2);
51 assert_uint8(handle[1].key, 3);
52 assert_uint8(handle[1].value, 4);
53 cbor_decref(&map);
54 assert_null(map);
55 }
56
57 unsigned char simple_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
58
59 /* {_ 1: 2, 3: 4} */
test_indef_simple_map(void ** _state _CBOR_UNUSED)60 static void test_indef_simple_map(void** _state _CBOR_UNUSED) {
61 map = cbor_load(simple_indef_map, 6, &res);
62 assert_non_null(map);
63 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
64 assert_true(cbor_isa_map(map));
65 assert_true(cbor_map_is_indefinite(map));
66 assert_true(cbor_map_size(map) == 2);
67 assert_true(res.read == 6);
68 struct cbor_pair* handle = cbor_map_handle(map);
69 assert_uint8(handle[0].key, 1);
70 assert_uint8(handle[0].value, 2);
71 assert_uint8(handle[1].key, 3);
72 assert_uint8(handle[1].value, 4);
73 cbor_decref(&map);
74 assert_null(map);
75 }
76
77 //{
78 // "glossary": {
79 // "title": "example glossary"
80 // }
81 //}
82 unsigned char def_nested_map[] = {
83 0xA1, 0x68, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79, 0xA1, 0x65,
84 0x74, 0x69, 0x74, 0x6C, 0x65, 0x70, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C,
85 0x65, 0x20, 0x67, 0x6C, 0x6F, 0x73, 0x73, 0x61, 0x72, 0x79};
86
test_def_nested_map(void ** _state _CBOR_UNUSED)87 static void test_def_nested_map(void** _state _CBOR_UNUSED) {
88 map = cbor_load(def_nested_map, 34, &res);
89 assert_non_null(map);
90 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
91 assert_true(cbor_isa_map(map));
92 assert_true(cbor_map_is_definite(map));
93 assert_true(cbor_map_size(map) == 1);
94 assert_true(res.read == 34);
95 struct cbor_pair* handle = cbor_map_handle(map);
96 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
97 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_MAP);
98 struct cbor_pair* inner_handle = cbor_map_handle(handle[0].value);
99 assert_true(cbor_typeof(inner_handle[0].key) == CBOR_TYPE_STRING);
100 assert_true(cbor_typeof(inner_handle[0].value) == CBOR_TYPE_STRING);
101 assert_memory_equal(cbor_string_handle(inner_handle[0].value),
102 "example glossary", strlen("example glossary"));
103 cbor_decref(&map);
104 assert_null(map);
105 }
106
107 unsigned char streamed_key_map[] = {0xA1, 0x7F, 0x61, 0x61,
108 0x61, 0x62, 0xFF, 0xA0};
109
110 /* '{ (_"a" "b"): {}}' */
test_streamed_key_map(void ** _state _CBOR_UNUSED)111 static void test_streamed_key_map(void** _state _CBOR_UNUSED) {
112 map = cbor_load(streamed_key_map, 8, &res);
113 assert_non_null(map);
114 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
115 assert_true(cbor_isa_map(map));
116 assert_true(cbor_map_is_definite(map));
117 assert_true(cbor_map_size(map) == 1);
118 assert_true(res.read == 8);
119 struct cbor_pair* handle = cbor_map_handle(map);
120 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
121 assert_true(cbor_string_is_indefinite(handle[0].key));
122 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
123 assert_true(cbor_isa_map(handle[0].value));
124 assert_size_equal(cbor_map_size(handle[0].value), 0);
125 cbor_decref(&map);
126 assert_null(map);
127 }
128
129 unsigned char streamed_kv_map[] = {0xA1, 0x7F, 0x61, 0x61, 0x61, 0x62, 0xFF,
130 0x7F, 0x61, 0x63, 0x61, 0x64, 0xFF};
131
132 /* '{ (_"a" "b"): (_"c", "d")}' */
test_streamed_kv_map(void ** _state _CBOR_UNUSED)133 static void test_streamed_kv_map(void** _state _CBOR_UNUSED) {
134 map = cbor_load(streamed_kv_map, 13, &res);
135 assert_non_null(map);
136 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
137 assert_true(cbor_isa_map(map));
138 assert_true(cbor_map_is_definite(map));
139 assert_size_equal(cbor_map_size(map), 1);
140 assert_size_equal(res.read, 13);
141 struct cbor_pair* handle = cbor_map_handle(map);
142 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
143 assert_true(cbor_string_is_indefinite(handle[0].key));
144 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
145 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
146 assert_true(cbor_string_is_indefinite(handle[0].value));
147 assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
148 assert_memory_equal(
149 cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
150 1);
151 cbor_decref(&map);
152 assert_null(map);
153 }
154
155 unsigned char streamed_streamed_kv_map[] = {0xBF, 0x7F, 0x61, 0x61, 0x61,
156 0x62, 0xFF, 0x7F, 0x61, 0x63,
157 0x61, 0x64, 0xFF, 0xFF};
158
159 /* '{_ (_"a" "b"): (_"c", "d")}' */
test_streamed_streamed_kv_map(void ** _state _CBOR_UNUSED)160 static void test_streamed_streamed_kv_map(void** _state _CBOR_UNUSED) {
161 map = cbor_load(streamed_streamed_kv_map, 14, &res);
162 assert_non_null(map);
163 assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
164 assert_true(cbor_isa_map(map));
165 assert_true(cbor_map_is_indefinite(map));
166 assert_size_equal(cbor_map_size(map), 1);
167 assert_size_equal(res.read, 14);
168 struct cbor_pair* handle = cbor_map_handle(map);
169 assert_true(cbor_typeof(handle[0].key) == CBOR_TYPE_STRING);
170 assert_true(cbor_string_is_indefinite(handle[0].key));
171 assert_size_equal(cbor_string_chunk_count(handle[0].key), 2);
172 assert_true(cbor_typeof(handle[0].value) == CBOR_TYPE_STRING);
173 assert_true(cbor_string_is_indefinite(handle[0].value));
174 assert_size_equal(cbor_string_chunk_count(handle[0].value), 2);
175 assert_memory_equal(
176 cbor_string_handle(cbor_string_chunks_handle(handle[0].value)[1]), "d",
177 1);
178 cbor_decref(&map);
179 assert_null(map);
180 }
181
test_map_add_full(void ** _state _CBOR_UNUSED)182 static void test_map_add_full(void** _state _CBOR_UNUSED) {
183 map = cbor_new_definite_map(0);
184 cbor_item_t* one = cbor_build_uint8(1);
185 cbor_item_t* two = cbor_build_uint8(2);
186
187 assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
188
189 cbor_decref(&map);
190 cbor_decref(&one);
191 cbor_decref(&two);
192 }
193
test_map_add_too_big_to_realloc(void ** _state _CBOR_UNUSED)194 static void test_map_add_too_big_to_realloc(void** _state _CBOR_UNUSED) {
195 map = cbor_new_indefinite_map();
196 struct _cbor_map_metadata* metadata =
197 (struct _cbor_map_metadata*)&map->metadata;
198 // Pretend we already have a huge memory block
199 metadata->allocated = SIZE_MAX;
200 metadata->end_ptr = SIZE_MAX;
201 cbor_item_t* one = cbor_build_uint8(1);
202 cbor_item_t* two = cbor_build_uint8(2);
203
204 assert_false(cbor_map_add(map, (struct cbor_pair){.key = one, .value = two}));
205
206 metadata->allocated = 0;
207 metadata->end_ptr = 0;
208 cbor_decref(&map);
209 cbor_decref(&one);
210 cbor_decref(&two);
211 }
212
test_map_creation(void ** _state _CBOR_UNUSED)213 static void test_map_creation(void** _state _CBOR_UNUSED) {
214 WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_map(42)); });
215 WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_map(42)); }, 2, MALLOC,
216 MALLOC_FAIL);
217
218 WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_map()); });
219 }
220
test_map_add(void ** _state _CBOR_UNUSED)221 static void test_map_add(void** _state _CBOR_UNUSED) {
222 WITH_MOCK_MALLOC(
223 {
224 cbor_item_t* map = cbor_new_indefinite_map();
225 cbor_item_t* key = cbor_build_uint8(0);
226 cbor_item_t* value = cbor_build_bool(true);
227
228 assert_false(
229 cbor_map_add(map, (struct cbor_pair){.key = key, .value = value}));
230 assert_size_equal(cbor_map_allocated(map), 0);
231 assert_null(map->data);
232
233 cbor_decref(&map);
234 cbor_decref(&key);
235 cbor_decref(&value);
236 },
237 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
238 }
239
240 static unsigned char test_indef_map[] = {0xBF, 0x01, 0x02, 0x03, 0x04, 0xFF};
test_indef_map_decode(void ** _state _CBOR_UNUSED)241 static void test_indef_map_decode(void** _state _CBOR_UNUSED) {
242 WITH_MOCK_MALLOC(
243 {
244 cbor_item_t* map;
245 struct cbor_load_result res;
246 map = cbor_load(test_indef_map, 6, &res);
247
248 assert_null(map);
249 assert_int_equal(res.error.code, CBOR_ERR_MEMERROR);
250 },
251 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
252 }
253
254 // The value in the third pair is missing, 0xFF instead.
255 static unsigned char test_break_in_def_map[] = {0xA3, 0x30, 0x30, 0x30,
256 0x30, 0x00, 0xFF};
test_break_in_def_map_decode(void ** _state _CBOR_UNUSED)257 static void test_break_in_def_map_decode(void** _state _CBOR_UNUSED) {
258 cbor_item_t* map;
259 struct cbor_load_result res;
260 map = cbor_load(test_break_in_def_map, 7, &res);
261
262 assert_null(map);
263 assert_int_equal(res.error.code, CBOR_ERR_SYNTAXERROR);
264 assert_size_equal(res.error.position, 7);
265 }
266
main(void)267 int main(void) {
268 const struct CMUnitTest tests[] = {
269 cmocka_unit_test(test_empty_map),
270 cmocka_unit_test(test_simple_map),
271 cmocka_unit_test(test_indef_simple_map),
272 cmocka_unit_test(test_def_nested_map),
273 cmocka_unit_test(test_streamed_key_map),
274 cmocka_unit_test(test_streamed_kv_map),
275 cmocka_unit_test(test_streamed_streamed_kv_map),
276 cmocka_unit_test(test_map_add_full),
277 cmocka_unit_test(test_map_add_too_big_to_realloc),
278 cmocka_unit_test(test_map_creation),
279 cmocka_unit_test(test_map_add),
280 cmocka_unit_test(test_indef_map_decode),
281 cmocka_unit_test(test_break_in_def_map_decode),
282 };
283 return cmocka_run_group_tests(tests, NULL, NULL);
284 }
285