summaryrefslogtreecommitdiff
path: root/tests/fuzz_parallel.c
blob: afd4425970a2beb4b580c9c7e07cba5e43cf6812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*-
 * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <sys/param.h>
#include <sys/socket.h>

#include <assert.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <libder.h>

#include "fuzzers.h"

struct fuzz_frame {
	uint8_t		frame_threads;
};

struct thread_input {
	const uint8_t	*data;
	size_t		 datasz;
};

static void *
thread_main(void *cookie)
{
	const struct thread_input *input = cookie;
	struct libder_ctx *ctx;
	struct libder_object *obj;
	const uint8_t *data = input->data;
	size_t readsz, sz = input->datasz;

	ctx = libder_open();
	readsz = sz;
	obj = libder_read(ctx, data, &readsz);
	if (obj == NULL || readsz != sz)
		goto out;

	if (obj != NULL) {
		uint8_t *buf = NULL;
		size_t bufsz = 0;

		/*
		 * If we successfully read it, then it shouldn't
		 * overflow.  We're letting libder allocate the buffer,
		 * so we shouldn't be able to hit the 'too small' bit.
		 *
		 * I can't imagine what other errors might happen, so
		 * we'll just assert on it.
		 */
		buf = libder_write(ctx, obj, buf, &bufsz);
		if (buf == NULL)
			goto out;

		assert(bufsz != 0);

		free(buf);
	}

out:
	libder_obj_free(obj);
	libder_close(ctx);
	return (NULL);
}

int
LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz)
{
	const struct fuzz_frame *frame;
	pthread_t *threads;
	struct thread_input inp;
	size_t nthreads;

	if (sz <= sizeof(*frame))
		return (-1);

	frame = (const void *)data;
	data += sizeof(*frame);
	sz -= sizeof(*frame);

	if (frame->frame_threads < 2)
		return (-1);

	threads = malloc(sizeof(*threads) * frame->frame_threads);
	if (threads == NULL)
		return (-1);

	inp.data = data;
	inp.datasz = sz;

	for (nthreads = 0; nthreads < frame->frame_threads; nthreads++) {
		if (pthread_create(&threads[nthreads], NULL, thread_main,
		    &inp) != 0)
			break;
	}

	for (uint8_t i = 0; i < nthreads; i++)
		pthread_join(threads[i], NULL);

	free(threads);

	return (0);
}