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 } 112