xref: /freebsd/contrib/libder/tests/fuzz_parallel.c (revision 35c0a8c449fd2b7f75029ebed5e10852240f0865)
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