forked from NetBSD/src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
#ifdef ENABLE_FUZZER | ||
|
||
#include "prog_ops.h" | ||
#include "fuzzer_ops.h" | ||
|
||
struct { | ||
fuffer_t *fuffers; | ||
size_t n, used; | ||
} fstate = { | ||
fuffers = NULL, | ||
n = 0, | ||
used = 0, | ||
}; | ||
|
||
static uint8_t **fuzzer_buffers = NULL; | ||
|
||
/* The format of "packet" is "|uint16_t|content|" */ | ||
static inline size_t fuzzer_fuffer_size(fuffer_t *f) { | ||
return f->len > f->off ? f->len - f->off : 0; | ||
} | ||
|
||
static inline uint8_t *fuzzer_fuffer_start(fuffer_t *f) { | ||
return f->buf + f->off; | ||
} | ||
|
||
static inline int fuzzer_fuffer_readable(fuffer_t *f) { | ||
return f->open && f->read && fuzzer_fuffer_size(f) > sizeof(uint16_t); | ||
} | ||
|
||
static inline int fuzzer_fuffer_writable(fuffer_t *f) { | ||
return f->open && f->write; | ||
} | ||
|
||
void fuzzer_init_fuffer(fuffer_t *f, uint8_t *buf, size_t len) { | ||
f->len = len; | ||
f->off = 0; | ||
f->buf = buf; | ||
f->open = 0; | ||
f->read = 0; | ||
f->write = 0; | ||
} | ||
|
||
void fuzzer_install_fuffers(fuffer_t *fuffers, size_t n) { | ||
fstate.fuffers = fuffers; | ||
fstate.n = n; | ||
fstate.used = 0; | ||
} | ||
|
||
int fuzzer_socket(int domain, int type, int protocol) { | ||
if (fstate.used >= fstate.n) | ||
return -1; | ||
int s = fstate.used++; | ||
fstate.fuffers[s].open = 1; | ||
fstate.fuffers[s].read = 1; | ||
fstate.fuffers[s].write = 1; | ||
return s + 1; | ||
} | ||
|
||
int fuzzer_setsocketopt(int s, int level, int optname, | ||
const void *optval, socketlen_t optlen) { return 0; } | ||
int fuzzer_shutdown(int s, int how) { | ||
s--; | ||
if (s < 0 || s >= fstate.n) | ||
return -1; | ||
if (how == SHUT_RD || how == SHUT_RDWR) | ||
fstate.fuffers[s].read = 0; | ||
if (how == SHUT_WR || how == SHUT_RDWR) | ||
fstate.fuffers[s].write = 0; | ||
return 0; | ||
} | ||
int fuzzer_poll(struct pollfd *fds, nfds_t nfds, int timeout) { | ||
if (!fds) | ||
return -1; | ||
|
||
nfds_t i; | ||
for (i = 0; i < nfds; i++) { | ||
if (fds[i].fd < 0) { | ||
fds[i].revents = 0; | ||
continue; | ||
} | ||
short e = fds[i].events; | ||
int index = fds[i].fd - 1; | ||
if (index < 0 || index >= fstate.n || | ||
!(fstate.fuzzers[index].read || fstate.fuzzers[index].write)) { | ||
fds[i].revents = POLLNVAL; | ||
return fds[i].fd; | ||
} | ||
if ((e & POLLIN) || (e & POLLRDNORM) || (e & POLLRDNORM) || (e & POLLPRI)) { | ||
if (fuzzer_fuffer_readable(fstate.fuffers + index)) { | ||
fds[i].revents = e; | ||
return fds[i].fd; | ||
} | ||
if (!fstate.fuffers[index].read) { | ||
fds[i].revents = POLLHUP; | ||
return fds[i].fd; | ||
} | ||
} | ||
if ((e & POLLOUT) || (e & POLLWRNORM) || (e & POLLWRBAND)) { | ||
if (fuzzer_fuffer_writable(fstate.fuffers + index)) { | ||
fds[i].revents = e; | ||
return fds[i].fd; | ||
} | ||
if (!fstate.fuffers[index].write) { | ||
fds[i].revents = POLLHUP; | ||
return fds[i].fd; | ||
} | ||
} | ||
} | ||
if (timeout == INFTIM) | ||
do {} while (1); | ||
return 0; | ||
} | ||
|
||
static uint8_t *fuzzer_fuffer_get(fuffer_t *f, size_t len) { | ||
if (fuffzer_fuffer_size(f) < len) | ||
return NULL; | ||
uint8_t *ret = fuzzer_fuffer_start(f); | ||
f->off += len; | ||
return ret; | ||
} | ||
|
||
static inline void fuzzer_fuffer_put(fuffer_t *f, uint8_t *buf, size_t len) { | ||
if (f->off >= len) | ||
f->off -= len; | ||
} | ||
|
||
ssize_t fuzzer_recvfrom(int s, void *buf, size_t len, int flags, | ||
struct sockaddr *from, socklen_t *fromlen) { | ||
s--; | ||
if (s < 0 || s >= fstate.n || !buf) | ||
return -1; | ||
fuffer_t *f = fstate.fuffers + s; | ||
uint16_t blen = 0; | ||
while (blen == 0) { | ||
uint8_t *pblen = fuzzer_fuffer_get(f, sizeof(uint16_t)); | ||
if (pblen == NULL) | ||
return 0; | ||
blen = *(uint16_t *)pblen; | ||
} | ||
|
||
uint8_t *buffer = fuzzer_fuffer_get(f, blen); | ||
|
||
if ((flags & MSG_WAITALL) && len < blen) { | ||
fuzzer_fuffer_put(f, NULL, blen + sizeof(uint16_t)); | ||
return -1; | ||
} | ||
if (len > blen) | ||
len = blen; | ||
memcpy(buf, buffer, len); | ||
if (flags & MSG_PEEK) | ||
fuzzer_fuffer_put(f, NULL, blen + sizeof(uint16_t)); | ||
return len; | ||
} | ||
|
||
ssize_t fuzzer_sendto(int s, const void *msg, size_t len, int flags, | ||
const struct sockaddr *to, socklen_t tolen) { | ||
s--; | ||
if (s < 0 || s >= fstate.n || !buf) | ||
return -1; | ||
fuffer_t *f = fstate.fuffers + s; | ||
if (!fuzzer_fuffer_writable(f)) | ||
return -1; | ||
return len; | ||
} | ||
|
||
int fuzzer_close(int s) { | ||
s--; | ||
if (s < 0 || s >= fstate.n) | ||
return -1; | ||
fstate.fuffers[s].open = 0; | ||
return 0; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifndef _FUZZER_OPS_H_ | ||
#define _FUZZER_OPS_H_ | ||
|
||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <poll.h> | ||
|
||
typedef struct s_fuzzer_buffer_t { | ||
size_t len, off; | ||
uint8_t *buf; | ||
char open, read, write; | ||
} fuffer_t; | ||
|
||
/* The init function should be provided by the users, | ||
because the fed buffer is unknown to this file. */ | ||
extern int fuzzer_init(void); | ||
|
||
void fuzzer_init_fuffer(fuffer_t *f, uint8_t *buf, size_t len); | ||
void fuzzer_install_fuffers(fuffer_t *fuffers, size_t n); | ||
int fuzzer_socket(int domain, int type, int protocol); | ||
int fuzzer_setsocketopt(int s, int level, int optname, | ||
const void *optval, socketlen_t optlen); | ||
int fuzzer_shutdown(int s, int how); | ||
int fuzzer_poll(struct pollfd *fds, nfds_t nfds, int timeout); | ||
|
||
#endif |