/ external / libder / tests / fuzz_parallel.c
fuzz_parallel.c
  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 *
 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
 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  }