xref: /freebsd/contrib/libcbor/test/fuzz_test.c (revision af0a81b6470aba4af4a24ae9804053722846ded4)
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 <time.h>
9 #include "assertions.h"
10 #include "cbor.h"
11 
12 #ifdef HUGE_FUZZ
13 #define ROUNDS 65536ULL
14 #define MAXLEN 131072ULL
15 #else
16 #define ROUNDS 256ULL
17 #define MAXLEN 2048ULL
18 #endif
19 
20 #ifdef PRINT_FUZZ
21 static void printmem(const unsigned char *ptr, size_t length) {
22   for (size_t i = 0; i < length; i++) printf("%02X", ptr[i]);
23   printf("\n");
24 }
25 #endif
26 
27 unsigned seed;
28 
29 void *mock_malloc(size_t size) {
30   if (size > (1 << 19))
31     return NULL;
32   else
33     return malloc(size);
34 }
35 
36 static void run_round(void) {
37   cbor_item_t *item;
38   struct cbor_load_result res;
39 
40   size_t length = rand() % MAXLEN + 1;
41   unsigned char *data = malloc(length);
42   for (size_t i = 0; i < length; i++) {
43     data[i] = rand() % 0xFF;
44   }
45 
46 #ifdef PRINT_FUZZ
47   printmem(data, length);
48 #endif
49 
50   item = cbor_load(data, length, &res);
51 
52   if (res.error.code == CBOR_ERR_NONE) cbor_decref(&item);
53   /* Otherwise there should be nothing left behind by the decoder */
54 
55   free(data);
56 }
57 
58 static void fuzz(void **_CBOR_UNUSED(_state)) {
59   cbor_set_allocs(mock_malloc, realloc, free);
60   printf("Fuzzing %llu rounds of up to %llu bytes with seed %u\n", ROUNDS,
61          MAXLEN, seed);
62   srand(seed);
63 
64   for (size_t i = 0; i < ROUNDS; i++) run_round();
65 
66   printf("Successfully fuzzed through %llu kB of data\n",
67          (ROUNDS * MAXLEN) / 1024);
68 }
69 
70 int main(int argc, char *argv[]) {
71   if (argc > 1)
72     seed = (unsigned)strtoul(argv[1], NULL, 10);
73   else
74     seed = (unsigned)time(NULL);
75 
76   const struct CMUnitTest tests[] = {cmocka_unit_test(fuzz)};
77   return cmocka_run_group_tests(tests, NULL, NULL);
78 }
79