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