1 /*-
2 * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/param.h>
8 #include <sys/socket.h>
9
10 #include <assert.h>
11 #include <pthread.h>
12 #include <signal.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18
19 #include <libder.h>
20
21 #include "fuzzers.h"
22
23 struct fuzz_frame {
24 uint8_t frame_threads;
25 };
26
27 struct thread_input {
28 const uint8_t *data;
29 size_t datasz;
30 };
31
32 static void *
thread_main(void * cookie)33 thread_main(void *cookie)
34 {
35 const struct thread_input *input = cookie;
36 struct libder_ctx *ctx;
37 struct libder_object *obj;
38 const uint8_t *data = input->data;
39 size_t readsz, sz = input->datasz;
40
41 ctx = libder_open();
42 readsz = sz;
43 obj = libder_read(ctx, data, &readsz);
44 if (obj == NULL || readsz != sz)
45 goto out;
46
47 if (obj != NULL) {
48 uint8_t *buf = NULL;
49 size_t bufsz = 0;
50
51 /*
52 * If we successfully read it, then it shouldn't
53 * overflow. We're letting libder allocate the buffer,
54 * so we shouldn't be able to hit the 'too small' bit.
55 *
56 * I can't imagine what other errors might happen, so
57 * we'll just assert on it.
58 */
59 buf = libder_write(ctx, obj, buf, &bufsz);
60 if (buf == NULL)
61 goto out;
62
63 assert(bufsz != 0);
64
65 free(buf);
66 }
67
68 out:
69 libder_obj_free(obj);
70 libder_close(ctx);
71 return (NULL);
72 }
73
74 int
LLVMFuzzerTestOneInput(const uint8_t * data,size_t sz)75 LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz)
76 {
77 const struct fuzz_frame *frame;
78 pthread_t *threads;
79 struct thread_input inp;
80 size_t nthreads;
81
82 if (sz <= sizeof(*frame))
83 return (-1);
84
85 frame = (const void *)data;
86 data += sizeof(*frame);
87 sz -= sizeof(*frame);
88
89 if (frame->frame_threads < 2)
90 return (-1);
91
92 threads = malloc(sizeof(*threads) * frame->frame_threads);
93 if (threads == NULL)
94 return (-1);
95
96 inp.data = data;
97 inp.datasz = sz;
98
99 for (nthreads = 0; nthreads < frame->frame_threads; nthreads++) {
100 if (pthread_create(&threads[nthreads], NULL, thread_main,
101 &inp) != 0)
102 break;
103 }
104
105 for (uint8_t i = 0; i < nthreads; i++)
106 pthread_join(threads[i], NULL);
107
108 free(threads);
109
110 return (0);
111 }
112