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 "assertions.h"
9 #include "cbor.h"
10 #include "test_allocator.h"
11
12 cbor_item_t *arr;
13 struct cbor_load_result res;
14
15 unsigned char data1[] = {0x80, 0xFF};
16
test_empty_array(void ** _CBOR_UNUSED (_state))17 static void test_empty_array(void **_CBOR_UNUSED(_state)) {
18 arr = cbor_load(data1, 2, &res);
19 assert_non_null(arr);
20 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
21 assert_true(cbor_isa_array(arr));
22 assert_true(cbor_array_size(arr) == 0);
23 assert_true(res.read == 1);
24 cbor_decref(&arr);
25 assert_null(arr);
26 }
27
28 unsigned char data2[] = {0x81, 0x01, 0xFF};
29
test_simple_array(void ** _CBOR_UNUSED (_state))30 static void test_simple_array(void **_CBOR_UNUSED(_state)) {
31 arr = cbor_load(data2, 3, &res);
32 assert_non_null(arr);
33 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
34 assert_true(cbor_isa_array(arr));
35 assert_size_equal(cbor_array_size(arr), 1);
36 assert_true(res.read == 2);
37 assert_size_equal(cbor_array_allocated(arr), 1);
38 /* Check the values */
39 assert_uint8(cbor_array_handle(arr)[0], 1);
40 cbor_item_t *intermediate = cbor_array_get(arr, 0);
41 assert_uint8(intermediate, 1);
42
43 cbor_item_t *new_val = cbor_build_uint8(10);
44 assert_false(cbor_array_set(arr, 1, new_val));
45 assert_false(cbor_array_set(arr, 3, new_val));
46 cbor_decref(&new_val);
47
48 cbor_decref(&arr);
49 cbor_decref(&intermediate);
50 assert_null(arr);
51 assert_null(intermediate);
52 }
53
54 unsigned char data3[] = {0x82, 0x01, 0x81, 0x01, 0xFF};
55
test_nested_arrays(void ** _CBOR_UNUSED (_state))56 static void test_nested_arrays(void **_CBOR_UNUSED(_state)) {
57 arr = cbor_load(data3, 5, &res);
58 assert_non_null(arr);
59 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
60 assert_true(cbor_isa_array(arr));
61 assert_true(cbor_array_size(arr) == 2);
62 assert_true(res.read == 4);
63 /* Check the values */
64 assert_uint8(cbor_array_handle(arr)[0], 1);
65
66 cbor_item_t *nested = cbor_array_handle(arr)[1];
67 assert_true(cbor_isa_array(nested));
68 assert_true(cbor_array_size(nested) == 1);
69 assert_uint8(cbor_array_handle(nested)[0], 1);
70
71 cbor_decref(&arr);
72 assert_null(arr);
73 }
74
75 unsigned char test_indef_arrays_data[] = {0x9f, 0x01, 0x02, 0xFF};
76
test_indef_arrays(void ** _CBOR_UNUSED (_state))77 static void test_indef_arrays(void **_CBOR_UNUSED(_state)) {
78 arr = cbor_load(test_indef_arrays_data, 4, &res);
79 assert_non_null(arr);
80 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
81 assert_true(cbor_isa_array(arr));
82 assert_true(cbor_array_size(arr) == 2);
83 assert_true(res.read == 4);
84 /* Check the values */
85 assert_uint8(cbor_array_handle(arr)[0], 1);
86 assert_uint8(cbor_array_handle(arr)[1], 2);
87
88 assert_true(cbor_array_set(arr, 1, cbor_move(cbor_build_uint8(10))));
89
90 cbor_decref(&arr);
91 assert_null(arr);
92 }
93
94 unsigned char test_nested_indef_arrays_data[] = {0x9f, 0x01, 0x9f, 0x02,
95 0xFF, 0x03, 0xFF};
96
test_nested_indef_arrays(void ** _CBOR_UNUSED (_state))97 static void test_nested_indef_arrays(void **_CBOR_UNUSED(_state)) {
98 arr = cbor_load(test_nested_indef_arrays_data, 7, &res);
99 assert_non_null(arr);
100 assert_true(cbor_typeof(arr) == CBOR_TYPE_ARRAY);
101 assert_true(cbor_isa_array(arr));
102 assert_size_equal(cbor_array_size(arr), 3);
103 assert_true(res.read == 7);
104 /* Check the values */
105 assert_uint8(cbor_array_handle(arr)[0], 1);
106
107 cbor_item_t *nested = cbor_array_handle(arr)[1];
108 assert_true(cbor_isa_array(nested));
109 assert_true(cbor_array_size(nested) == 1);
110 assert_uint8(cbor_array_handle(nested)[0], 2);
111
112 cbor_decref(&arr);
113 assert_null(arr);
114 }
115
test_array_replace(void ** _CBOR_UNUSED (_state))116 static void test_array_replace(void **_CBOR_UNUSED(_state)) {
117 cbor_item_t *array = cbor_new_definite_array(2);
118 assert_size_equal(cbor_array_size(array), 0);
119 cbor_item_t *one = cbor_build_uint8(1);
120 cbor_item_t *three = cbor_build_uint8(3);
121 assert_size_equal(cbor_refcount(one), 1);
122 assert_size_equal(cbor_refcount(three), 1);
123
124 // No item to replace
125 assert_false(cbor_array_replace(array, 0, three));
126 assert_size_equal(cbor_refcount(three), 1);
127
128 // Add items [1, 2]
129 assert_true(cbor_array_push(array, one));
130 assert_true(cbor_array_push(array, cbor_move(cbor_build_uint8(2))));
131 assert_size_equal(cbor_refcount(one), 2);
132 assert_size_equal(cbor_array_size(array), 2);
133
134 // Array has only two items
135 assert_false(cbor_array_replace(array, 2, three));
136 assert_size_equal(cbor_refcount(three), 1);
137
138 // Change [1, 2] to [3, 2]
139 assert_true(cbor_array_replace(array, 0, three));
140 assert_size_equal(cbor_refcount(one), 1);
141 assert_size_equal(cbor_refcount(three), 2);
142 assert_uint8(cbor_move(cbor_array_get(array, 0)), 3);
143 assert_uint8(cbor_move(cbor_array_get(array, 1)), 2);
144
145 cbor_decref(&one);
146 cbor_decref(&three);
147 cbor_decref(&array);
148 }
149
test_array_push_overflow(void ** _CBOR_UNUSED (_state))150 static void test_array_push_overflow(void **_CBOR_UNUSED(_state)) {
151 cbor_item_t *array = cbor_new_indefinite_array();
152 cbor_item_t *one = cbor_build_uint8(1);
153 struct _cbor_array_metadata *metadata =
154 (struct _cbor_array_metadata *)&array->metadata;
155 // Pretend we already have a huge block allocated
156 metadata->allocated = SIZE_MAX;
157 metadata->end_ptr = SIZE_MAX;
158
159 assert_false(cbor_array_push(array, one));
160 assert_size_equal(cbor_refcount(one), 1);
161
162 cbor_decref(&one);
163 metadata->allocated = 0;
164 metadata->end_ptr = 0;
165 cbor_decref(&array);
166 }
167
test_array_creation(void ** _CBOR_UNUSED (_state))168 static void test_array_creation(void **_CBOR_UNUSED(_state)) {
169 WITH_FAILING_MALLOC({ assert_null(cbor_new_definite_array(42)); });
170 WITH_MOCK_MALLOC({ assert_null(cbor_new_definite_array(42)); }, 2, MALLOC,
171 MALLOC_FAIL);
172
173 WITH_FAILING_MALLOC({ assert_null(cbor_new_indefinite_array()); });
174 }
175
test_array_push(void ** _CBOR_UNUSED (_state))176 static void test_array_push(void **_CBOR_UNUSED(_state)) {
177 WITH_MOCK_MALLOC(
178 {
179 cbor_item_t *array = cbor_new_indefinite_array();
180 cbor_item_t *string = cbor_build_string("Hello!");
181
182 assert_false(cbor_array_push(array, string));
183 assert_size_equal(cbor_array_allocated(array), 0);
184 assert_null(array->data);
185 assert_size_equal(array->metadata.array_metadata.end_ptr, 0);
186
187 cbor_decref(&string);
188 cbor_decref(&array);
189 },
190 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
191 }
192
193 static unsigned char simple_indef_array[] = {0x9F, 0x01, 0x02, 0xFF};
test_indef_array_decode(void ** _CBOR_UNUSED (_state))194 static void test_indef_array_decode(void **_CBOR_UNUSED(_state)) {
195 WITH_MOCK_MALLOC(
196 {
197 cbor_item_t *array;
198 struct cbor_load_result res;
199 array = cbor_load(simple_indef_array, 4, &res);
200
201 assert_null(array);
202 assert_size_equal(res.error.code, CBOR_ERR_MEMERROR);
203 },
204 4, MALLOC, MALLOC, MALLOC, REALLOC_FAIL);
205 }
206
main(void)207 int main(void) {
208 const struct CMUnitTest tests[] = {
209 cmocka_unit_test(test_empty_array),
210 cmocka_unit_test(test_simple_array),
211 cmocka_unit_test(test_nested_arrays),
212 cmocka_unit_test(test_indef_arrays),
213 cmocka_unit_test(test_nested_indef_arrays),
214 cmocka_unit_test(test_array_replace),
215 cmocka_unit_test(test_array_push_overflow),
216 cmocka_unit_test(test_array_creation),
217 cmocka_unit_test(test_array_push),
218 cmocka_unit_test(test_indef_array_decode),
219 };
220
221 return cmocka_run_group_tests(tests, NULL, NULL);
222 }
223