/* * zzuf - general purpose fuzzer * Copyright (c) 2006 Sam Hocevar * All Rights Reserved * * $Id$ * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://sam.zoy.org/wtfpl/COPYING for more details. */ /* * libzzuf.c: preloaded wrapper library */ #include "config.h" #define _GNU_SOURCE #if defined HAVE_STDINT_H # include #elif defined HAVE_INTTYPES_H # include #endif #include #include #include "libzzuf.h" #include "fd.h" /* Regex stuff */ static regex_t * re_include = NULL; static regex_t * re_exclude = NULL; /* File descriptor stuff */ static struct files { int managed; uint64_t seed; uint64_t pos; /* Public stuff */ struct fuzz fuzz; } *files; static int *fds; static int maxfd, nfiles; void _zz_include(char const *regex) { re_include = malloc(sizeof(*re_include)); if(regcomp(re_include, regex, REG_EXTENDED) != 0) { free(re_include); re_include = NULL; } } void _zz_exclude(char const *regex) { re_exclude = malloc(sizeof(*re_exclude)); if(regcomp(re_exclude, regex, REG_EXTENDED) != 0) { free(re_exclude); re_exclude = NULL; } } void _zz_fd_init(void) { files = NULL; nfiles = 0; /* Start with one fd in the lookup table */ fds = malloc(1 * sizeof(int)); for(maxfd = 0; maxfd < 1; maxfd++) fds[maxfd] = -1; } void _zz_fd_fini(void) { int i; for(i = 0; i < maxfd; i++) { if(!files[fds[i]].managed) continue; /* XXX: What are we supposed to do? If filedescriptors weren't * closed properly, there's a leak, but it's not our problem. */ } free(files); free(fds); } int _zz_mustwatch(char const *file) { if(re_include && regexec(re_include, file, 0, NULL, 0) == REG_NOMATCH) return 0; /* not included: ignore */ if(re_exclude && regexec(re_exclude, file, 0, NULL, 0) != REG_NOMATCH) return 0; /* excluded: ignore */ return 1; /* default */ } int _zz_iswatched(int fd) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return 0; return 1; } void _zz_register(int fd) { int i; if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1)) return; while(fd >= maxfd) { fds = realloc(fds, 2 * maxfd * sizeof(int)); for(i = maxfd; i < maxfd * 2; i++) fds[i] = -1; maxfd *= 2; } /* Find an empty slot */ for(i = 0; i < nfiles; i++) if(files[i].managed == 0) break; /* No slot found, allocate memory */ if(i == nfiles) { nfiles++; files = realloc(files, nfiles * sizeof(struct files)); } files[i].managed = 1; files[i].pos = 0; files[i].fuzz.cur = -1; files[i].fuzz.data = malloc(CHUNKBYTES); #ifdef HAVE_FGETLN files[i].fuzz.tmp = NULL; #endif fds[fd] = i; } void _zz_unregister(int fd) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return; files[fds[fd]].managed = 0; free(files[fds[fd]].fuzz.data); #ifdef HAVE_FGETLN if(files[fds[fd]].fuzz.tmp) free(files[fds[fd]].fuzz.tmp); #endif fds[fd] = -1; } long int _zz_getpos(int fd) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return 0; return files[fds[fd]].pos; } void _zz_setpos(int fd, long int pos) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return; files[fds[fd]].pos = pos; } void _zz_addpos(int fd, long int off) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return; files[fds[fd]].pos += off; } struct fuzz *_zz_getfuzz(int fd) { if(fd < 0 || fd >= maxfd || fds[fd] == -1) return NULL; return &files[fds[fd]].fuzz; }