xref: /freebsd/contrib/libcbor/oss-fuzz/cbor_load_fuzzer.cc (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1 #include <cstdint>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <unordered_map>
5 
6 #include "cbor.h"
7 
8 static size_t allocated_mem = 0;
9 static std::unordered_map<void*, size_t> allocated_len_map;
10 static constexpr size_t kMemoryLimit = 1 << 30;
11 
12 void *limited_malloc(size_t size) {
13     if (size + allocated_mem > kMemoryLimit) {
14         return nullptr;
15     }
16     if (size == 0) {
17         return nullptr;
18     }
19     void* m = malloc(size);
20     if (m != nullptr) {
21         allocated_mem += size;
22         allocated_len_map[m] = size;
23     }
24     return m;
25 }
26 
27 void limited_free(void *ptr) {
28     if (ptr != NULL && allocated_len_map.find(ptr) == allocated_len_map.end()) {
29         abort();
30     }
31     free(ptr);
32     if (ptr != NULL) {
33         allocated_mem -= allocated_len_map[ptr];
34         allocated_len_map.erase(ptr);
35     }
36 }
37 
38 void *limited_realloc(void *ptr, size_t size) {
39     if (ptr != NULL && allocated_len_map.find(ptr) == allocated_len_map.end()) {
40         abort();
41     }
42     if (ptr == NULL) {
43         return limited_malloc(size);
44     }
45     long delta = (long) size - allocated_len_map[ptr];
46     if (delta + allocated_mem > kMemoryLimit) {
47         return nullptr;
48     }
49     void* new_ptr = realloc(ptr, size);
50     if (size > 0 && new_ptr == nullptr) {
51         return nullptr;
52     }
53     allocated_mem += delta;
54     allocated_len_map.erase(ptr);
55     if (size > 0) {
56         allocated_len_map[new_ptr] = size;
57     }
58     return new_ptr;
59 }
60 
61 struct State {
62     FILE* fout;
63 
64     State() : fout(fopen("/dev/null", "r")) {
65         cbor_set_allocs(limited_malloc, limited_realloc, limited_free);
66     }
67 };
68 
69 static State kState;
70 
71 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
72     cbor_load_result result;
73     cbor_item_t *item = cbor_load(Data, Size, &result);
74     if (result.error.code == CBOR_ERR_NONE) {
75         cbor_describe(item, kState.fout);
76         unsigned char *buffer;
77         size_t buffer_size;
78         cbor_serialize_alloc(item, &buffer, &buffer_size);
79         free(buffer);
80         cbor_item_t *copied = cbor_copy(item);
81         cbor_decref(&copied);
82         cbor_decref(&item);
83     }
84     return 0;
85 }
86