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