
Some checks failed
CIFuzz / Fuzzing (push) Waiting to run
C/C++ CI self-hosted / win10 cygwin-release (push) Waiting to run
C/C++ CI self-hosted / ARM default (push) Waiting to run
C/C++ CI self-hosted / ARM64 default (push) Waiting to run
C/C++ CI self-hosted / alpine default (push) Waiting to run
C/C++ CI self-hosted / centos7 default (push) Waiting to run
C/C++ CI self-hosted / debian-i386 default (push) Waiting to run
C/C++ CI self-hosted / dfly30 default (push) Waiting to run
C/C++ CI self-hosted / dfly48 default (push) Waiting to run
C/C++ CI self-hosted / dfly60 default (push) Waiting to run
C/C++ CI self-hosted / dfly62 default (push) Waiting to run
C/C++ CI self-hosted / dfly64 default (push) Waiting to run
C/C++ CI self-hosted / fbsd10 default (push) Waiting to run
C/C++ CI self-hosted / fbsd12 default (push) Waiting to run
C/C++ CI self-hosted / fbsd13 default (push) Waiting to run
C/C++ CI self-hosted / fbsd14 default (push) Waiting to run
C/C++ CI self-hosted / nbsd10 default (push) Waiting to run
C/C++ CI self-hosted / nbsd3 default (push) Waiting to run
C/C++ CI self-hosted / nbsd4 default (push) Waiting to run
C/C++ CI self-hosted / nbsd8 default (push) Waiting to run
C/C++ CI self-hosted / nbsd9 default (push) Waiting to run
C/C++ CI self-hosted / obsd51 default (push) Waiting to run
C/C++ CI self-hosted / obsd67 default (push) Waiting to run
C/C++ CI self-hosted / obsd72 default (push) Waiting to run
C/C++ CI self-hosted / obsd73 default (push) Waiting to run
C/C++ CI self-hosted / obsd74 default (push) Waiting to run
C/C++ CI self-hosted / obsdsnap default (push) Waiting to run
C/C++ CI self-hosted / obsdsnap-i386 default (push) Waiting to run
C/C++ CI self-hosted / omnios default (push) Waiting to run
C/C++ CI self-hosted / openindiana default (push) Waiting to run
C/C++ CI self-hosted / ubuntu-2204 default (push) Waiting to run
C/C++ CI self-hosted / obsd-arm64 default (push) Waiting to run
C/C++ CI self-hosted / aix51 default (push) Waiting to run
C/C++ CI self-hosted / fbsd14-ppc64 default (push) Waiting to run
C/C++ CI self-hosted / sol10 default (push) Waiting to run
C/C++ CI self-hosted / sol11 default (push) Waiting to run
C/C++ CI self-hosted / win10 default (push) Waiting to run
C/C++ CI self-hosted / debian-riscv64 default (push) Waiting to run
C/C++ CI self-hosted / openwrt-mips default (push) Waiting to run
C/C++ CI self-hosted / openwrt-mipsel default (push) Waiting to run
C/C++ CI self-hosted / ARM64 pam (push) Waiting to run
C/C++ CI self-hosted / centos7 pam (push) Waiting to run
C/C++ CI self-hosted / debian-i386 pam (push) Waiting to run
C/C++ CI self-hosted / dfly48 pam (push) Waiting to run
C/C++ CI self-hosted / dfly58 pam (push) Waiting to run
C/C++ CI self-hosted / dfly60 pam (push) Waiting to run
C/C++ CI self-hosted / dfly62 pam (push) Waiting to run
C/C++ CI self-hosted / dfly64 pam (push) Waiting to run
C/C++ CI self-hosted / fbsd10 pam (push) Waiting to run
C/C++ CI self-hosted / fbsd12 pam (push) Waiting to run
C/C++ CI self-hosted / fbsd13 pam (push) Waiting to run
C/C++ CI self-hosted / fbsd14 pam (push) Waiting to run
C/C++ CI self-hosted / nbsd10 pam (push) Waiting to run
C/C++ CI self-hosted / nbsd8 pam (push) Waiting to run
C/C++ CI self-hosted / nbsd9 pam (push) Waiting to run
C/C++ CI self-hosted / omnios pam (push) Waiting to run
C/C++ CI self-hosted / openindiana pam (push) Waiting to run
C/C++ CI self-hosted / sol10 pam (push) Waiting to run
C/C++ CI self-hosted / sol11 pam-krb5 (push) Waiting to run
C/C++ CI self-hosted / sol11 sol64 (push) Waiting to run
C/C++ CI self-hosted / dfly30 without-openssl (push) Waiting to run
C/C++ CI / ubuntu-latest aws-lc (push) Failing after 31s
C/C++ CI / ubuntu-latest boringssl (push) Failing after 31s
C/C++ CI / ubuntu-latest clang-15 (push) Failing after 31s
C/C++ CI / ubuntu-latest clang-19 (push) Failing after 19s
C/C++ CI / ubuntu-latest default (push) Failing after 3s
C/C++ CI / ubuntu-latest gcc-14 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-3.2.6 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-3.3.6 (push) Failing after 3s
C/C++ CI / ubuntu-latest libressl-3.4.3 (push) Failing after 3s
C/C++ CI / ubuntu-latest libressl-3.5.3 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-3.6.1 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-3.7.2 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-3.8.4 (push) Failing after 3s
C/C++ CI / ubuntu-latest libressl-3.9.2 (push) Failing after 3s
C/C++ CI / ubuntu-latest libressl-4.0.0 (push) Failing after 4s
C/C++ CI / ubuntu-latest libressl-master (push) Failing after 4s
C/C++ CI / ubuntu-latest musl (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-1.1.1 (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-1.1.1_stable (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-1.1.1t (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-1.1.1w (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-3.0 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.0.0 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.0.15 (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-3.1 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.1.0 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.1.7 (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-3.2 (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-3.2.3 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.3 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-3.3.2 (push) Failing after 4s
C/C++ CI / ubuntu-latest openssl-3.4.0 (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-master (push) Failing after 3s
C/C++ CI / ubuntu-latest openssl-noec (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.71 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.72 (push) Failing after 3s
C/C++ CI / ubuntu-latest putty-0.73 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.74 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.75 (push) Failing after 3s
C/C++ CI / ubuntu-latest putty-0.76 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.77 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.78 (push) Failing after 3s
C/C++ CI / ubuntu-latest putty-0.79 (push) Failing after 3s
C/C++ CI / ubuntu-latest putty-0.80 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.81 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-0.82 (push) Failing after 3s
C/C++ CI / ubuntu-latest putty-0.83 (push) Failing after 4s
C/C++ CI / ubuntu-latest putty-snapshot (push) Failing after 4s
C/C++ CI / ubuntu-latest tcmalloc (push) Failing after 3s
C/C++ CI / ubuntu-latest zlib-develop (push) Failing after 3s
C/C++ CI / ubuntu-22.04 c89 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 clang-11 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 clang-12-Werror (push) Has been cancelled
C/C++ CI / ubuntu-22.04 clang-14 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 clang-sanitize-address (push) Has been cancelled
C/C++ CI / ubuntu-22.04 clang-sanitize-undefined (push) Has been cancelled
C/C++ CI / windows-2019 cygwin-release (push) Has been cancelled
C/C++ CI / windows-2022 cygwin-release (push) Has been cancelled
C/C++ CI / macos-13 default (push) Has been cancelled
C/C++ CI / macos-14 default (push) Has been cancelled
C/C++ CI / macos-15 default (push) Has been cancelled
C/C++ CI / ubuntu-22.04 default (push) Has been cancelled
C/C++ CI / ubuntu-22.04-arm default (push) Has been cancelled
C/C++ CI / ubuntu-24.04-arm default (push) Has been cancelled
C/C++ CI / windows-2019 default (push) Has been cancelled
C/C++ CI / windows-2022 default (push) Has been cancelled
C/C++ CI / ubuntu-22.04 gcc-11-Werror (push) Has been cancelled
C/C++ CI / ubuntu-22.04 gcc-12-Werror (push) Has been cancelled
C/C++ CI / ubuntu-22.04 gcc-9 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 gcc-sanitize-address (push) Has been cancelled
C/C++ CI / ubuntu-22.04 gcc-sanitize-undefined (push) Has been cancelled
C/C++ CI / ubuntu-22.04 hardenedmalloc (push) Has been cancelled
C/C++ CI / ubuntu-22.04 heimdal (push) Has been cancelled
C/C++ CI / ubuntu-22.04 kitchensink (push) Has been cancelled
C/C++ CI / ubuntu-22.04-arm kitchensink (push) Has been cancelled
C/C++ CI / ubuntu-24.04-arm kitchensink (push) Has been cancelled
C/C++ CI / ubuntu-22.04 krb5 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 libedit (push) Has been cancelled
C/C++ CI / macos-13 pam (push) Has been cancelled
C/C++ CI / macos-14 pam (push) Has been cancelled
C/C++ CI / macos-15 pam (push) Has been cancelled
C/C++ CI / ubuntu-22.04 pam (push) Has been cancelled
C/C++ CI / ubuntu-22.04 selinux (push) Has been cancelled
C/C++ CI / ubuntu-22.04 sk (push) Has been cancelled
C/C++ CI / ubuntu-22.04 valgrind-1 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 valgrind-2 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 valgrind-3 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 valgrind-4 (push) Has been cancelled
C/C++ CI / ubuntu-22.04 valgrind-unit (push) Has been cancelled
C/C++ CI / ubuntu-22.04 without-openssl (push) Has been cancelled
439 lines
10 KiB
C
439 lines
10 KiB
C
/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */
|
|
/*
|
|
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/* Utility functions/framework for fuzz tests */
|
|
|
|
#include "includes.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/uio.h>
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#ifdef HAVE_STDINT_H
|
|
# include <stdint.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include "test_helper.h"
|
|
#include "atomicio.h"
|
|
|
|
/* #define FUZZ_DEBUG */
|
|
|
|
#ifdef FUZZ_DEBUG
|
|
# define FUZZ_DBG(x) do { \
|
|
printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
|
|
printf x; \
|
|
printf("\n"); \
|
|
fflush(stdout); \
|
|
} while (0)
|
|
#else
|
|
# define FUZZ_DBG(x)
|
|
#endif
|
|
|
|
/* For brevity later */
|
|
typedef unsigned long long fuzz_ullong;
|
|
|
|
/* For base-64 fuzzing */
|
|
static const char fuzz_b64chars[] =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
struct fuzz {
|
|
/* Fuzz method currently in use */
|
|
int strategy;
|
|
|
|
/* Fuzz methods remaining */
|
|
int strategies;
|
|
|
|
/* Original seed data blob */
|
|
void *seed;
|
|
size_t slen;
|
|
|
|
/* Current working copy of seed with fuzz mutations applied */
|
|
u_char *fuzzed;
|
|
|
|
/* Used by fuzz methods */
|
|
size_t o1, o2;
|
|
};
|
|
|
|
static const char *
|
|
fuzz_ntop(u_int n)
|
|
{
|
|
switch (n) {
|
|
case 0:
|
|
return "NONE";
|
|
case FUZZ_1_BIT_FLIP:
|
|
return "FUZZ_1_BIT_FLIP";
|
|
case FUZZ_2_BIT_FLIP:
|
|
return "FUZZ_2_BIT_FLIP";
|
|
case FUZZ_1_BYTE_FLIP:
|
|
return "FUZZ_1_BYTE_FLIP";
|
|
case FUZZ_2_BYTE_FLIP:
|
|
return "FUZZ_2_BYTE_FLIP";
|
|
case FUZZ_TRUNCATE_START:
|
|
return "FUZZ_TRUNCATE_START";
|
|
case FUZZ_TRUNCATE_END:
|
|
return "FUZZ_TRUNCATE_END";
|
|
case FUZZ_BASE64:
|
|
return "FUZZ_BASE64";
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static int
|
|
fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
|
|
{
|
|
if (fuzz == NULL)
|
|
return -1;
|
|
|
|
switch (fuzz->strategy) {
|
|
case FUZZ_1_BIT_FLIP:
|
|
snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
fuzz->o1, fuzz->slen * 8, fuzz->o1);
|
|
return 0;
|
|
case FUZZ_2_BIT_FLIP:
|
|
snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
(((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
|
|
((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
|
|
fuzz->o1, fuzz->o2);
|
|
return 0;
|
|
case FUZZ_1_BYTE_FLIP:
|
|
snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
fuzz->o1, fuzz->slen, fuzz->o1);
|
|
return 0;
|
|
case FUZZ_2_BYTE_FLIP:
|
|
snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
(((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
|
|
((fuzz_ullong)fuzz->slen) * fuzz->slen,
|
|
fuzz->o1, fuzz->o2);
|
|
return 0;
|
|
case FUZZ_TRUNCATE_START:
|
|
snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
fuzz->o1, fuzz->slen, fuzz->o1);
|
|
return 0;
|
|
case FUZZ_TRUNCATE_END:
|
|
snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
fuzz->o1, fuzz->slen, fuzz->o1);
|
|
return 0;
|
|
case FUZZ_BASE64:
|
|
assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
|
|
snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
|
|
fuzz_ntop(fuzz->strategy),
|
|
(fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
|
|
fuzz->slen * (fuzz_ullong)64, fuzz->o1,
|
|
fuzz_b64chars[fuzz->o2]);
|
|
return 0;
|
|
default:
|
|
return -1;
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static void
|
|
dump(u_char *p, size_t len)
|
|
{
|
|
size_t i, j;
|
|
|
|
for (i = 0; i < len; i += 16) {
|
|
fprintf(stderr, "%.4zd: ", i);
|
|
for (j = i; j < i + 16; j++) {
|
|
if (j < len)
|
|
fprintf(stderr, "%02x ", p[j]);
|
|
else
|
|
fprintf(stderr, " ");
|
|
}
|
|
fprintf(stderr, " ");
|
|
for (j = i; j < i + 16; j++) {
|
|
if (j < len) {
|
|
if (isascii(p[j]) && isprint(p[j]))
|
|
fprintf(stderr, "%c", p[j]);
|
|
else
|
|
fprintf(stderr, ".");
|
|
}
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
fuzz_dump(struct fuzz *fuzz)
|
|
{
|
|
char buf[256];
|
|
|
|
if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
|
|
fprintf(stderr, "%s: fuzz invalid\n", __func__);
|
|
abort();
|
|
}
|
|
fputs(buf, stderr);
|
|
fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
|
|
dump(fuzz->seed, fuzz->slen);
|
|
fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
|
|
dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
|
|
}
|
|
|
|
static struct fuzz *last_fuzz;
|
|
|
|
static void
|
|
siginfo(int unused __attribute__((__unused__)))
|
|
{
|
|
char buf[256];
|
|
|
|
test_info(buf, sizeof(buf));
|
|
atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
|
|
if (last_fuzz != NULL) {
|
|
fuzz_fmt(last_fuzz, buf, sizeof(buf));
|
|
atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
|
|
}
|
|
}
|
|
|
|
struct fuzz *
|
|
fuzz_begin(u_int strategies, const void *p, size_t l)
|
|
{
|
|
struct fuzz *ret = calloc(1, sizeof(*ret));
|
|
|
|
assert(p != NULL);
|
|
assert(ret != NULL);
|
|
ret->seed = malloc(l);
|
|
assert(ret->seed != NULL);
|
|
memcpy(ret->seed, p, l);
|
|
ret->slen = l;
|
|
ret->strategies = strategies;
|
|
|
|
assert(ret->slen < SIZE_MAX / 8);
|
|
assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
|
|
|
|
FUZZ_DBG(("begin, ret = %p", ret));
|
|
|
|
fuzz_next(ret);
|
|
|
|
last_fuzz = ret;
|
|
#ifdef SIGINFO
|
|
signal(SIGINFO, siginfo);
|
|
#endif
|
|
signal(SIGUSR1, siginfo);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
fuzz_cleanup(struct fuzz *fuzz)
|
|
{
|
|
FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
|
|
last_fuzz = NULL;
|
|
#ifdef SIGINFO
|
|
signal(SIGINFO, SIG_DFL);
|
|
#endif
|
|
signal(SIGUSR1, SIG_DFL);
|
|
assert(fuzz != NULL);
|
|
assert(fuzz->seed != NULL);
|
|
assert(fuzz->fuzzed != NULL);
|
|
free(fuzz->seed);
|
|
free(fuzz->fuzzed);
|
|
free(fuzz);
|
|
}
|
|
|
|
static int
|
|
fuzz_strategy_done(struct fuzz *fuzz)
|
|
{
|
|
FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
|
|
fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
|
|
|
|
switch (fuzz->strategy) {
|
|
case FUZZ_1_BIT_FLIP:
|
|
return fuzz->o1 >= fuzz->slen * 8;
|
|
case FUZZ_2_BIT_FLIP:
|
|
return fuzz->o2 >= fuzz->slen * 8;
|
|
case FUZZ_2_BYTE_FLIP:
|
|
return fuzz->o2 >= fuzz->slen;
|
|
case FUZZ_1_BYTE_FLIP:
|
|
case FUZZ_TRUNCATE_START:
|
|
case FUZZ_TRUNCATE_END:
|
|
case FUZZ_BASE64:
|
|
return fuzz->o1 >= fuzz->slen;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
void
|
|
fuzz_next(struct fuzz *fuzz)
|
|
{
|
|
u_int i;
|
|
|
|
FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
|
|
"o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
|
|
(u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
|
|
|
|
if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
|
|
/* If we are just starting out, we need to allocate too */
|
|
if (fuzz->fuzzed == NULL) {
|
|
FUZZ_DBG(("alloc"));
|
|
fuzz->fuzzed = calloc(fuzz->slen, 1);
|
|
}
|
|
/* Pick next strategy */
|
|
FUZZ_DBG(("advance"));
|
|
for (i = 1; i <= FUZZ_MAX; i <<= 1) {
|
|
if ((fuzz->strategies & i) != 0) {
|
|
fuzz->strategy = i;
|
|
break;
|
|
}
|
|
}
|
|
FUZZ_DBG(("selected = %u", fuzz->strategy));
|
|
if (fuzz->strategy == 0) {
|
|
FUZZ_DBG(("done, no more strategies"));
|
|
return;
|
|
}
|
|
fuzz->strategies &= ~(fuzz->strategy);
|
|
fuzz->o1 = fuzz->o2 = 0;
|
|
}
|
|
|
|
assert(fuzz->fuzzed != NULL);
|
|
|
|
switch (fuzz->strategy) {
|
|
case FUZZ_1_BIT_FLIP:
|
|
assert(fuzz->o1 / 8 < fuzz->slen);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
|
|
fuzz->o1++;
|
|
break;
|
|
case FUZZ_2_BIT_FLIP:
|
|
assert(fuzz->o1 / 8 < fuzz->slen);
|
|
assert(fuzz->o2 / 8 < fuzz->slen);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
|
|
fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
|
|
fuzz->o1++;
|
|
if (fuzz->o1 >= fuzz->slen * 8) {
|
|
fuzz->o1 = 0;
|
|
fuzz->o2++;
|
|
}
|
|
break;
|
|
case FUZZ_1_BYTE_FLIP:
|
|
assert(fuzz->o1 < fuzz->slen);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->fuzzed[fuzz->o1] ^= 0xff;
|
|
fuzz->o1++;
|
|
break;
|
|
case FUZZ_2_BYTE_FLIP:
|
|
assert(fuzz->o1 < fuzz->slen);
|
|
assert(fuzz->o2 < fuzz->slen);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->fuzzed[fuzz->o1] ^= 0xff;
|
|
fuzz->fuzzed[fuzz->o2] ^= 0xff;
|
|
fuzz->o1++;
|
|
if (fuzz->o1 >= fuzz->slen) {
|
|
fuzz->o1 = 0;
|
|
fuzz->o2++;
|
|
}
|
|
break;
|
|
case FUZZ_TRUNCATE_START:
|
|
case FUZZ_TRUNCATE_END:
|
|
assert(fuzz->o1 < fuzz->slen);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->o1++;
|
|
break;
|
|
case FUZZ_BASE64:
|
|
assert(fuzz->o1 < fuzz->slen);
|
|
assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
|
|
memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
|
|
fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
|
|
fuzz->o2++;
|
|
if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
|
|
fuzz->o2 = 0;
|
|
fuzz->o1++;
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
|
|
FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
|
|
"o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
|
|
(u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
|
|
}
|
|
|
|
int
|
|
fuzz_matches_original(struct fuzz *fuzz)
|
|
{
|
|
if (fuzz_len(fuzz) != fuzz->slen)
|
|
return 0;
|
|
return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
|
|
}
|
|
|
|
int
|
|
fuzz_done(struct fuzz *fuzz)
|
|
{
|
|
FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
|
|
(u_long)fuzz->strategies));
|
|
|
|
return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
|
|
}
|
|
|
|
size_t
|
|
fuzz_len(struct fuzz *fuzz)
|
|
{
|
|
assert(fuzz->fuzzed != NULL);
|
|
switch (fuzz->strategy) {
|
|
case FUZZ_1_BIT_FLIP:
|
|
case FUZZ_2_BIT_FLIP:
|
|
case FUZZ_1_BYTE_FLIP:
|
|
case FUZZ_2_BYTE_FLIP:
|
|
case FUZZ_BASE64:
|
|
return fuzz->slen;
|
|
case FUZZ_TRUNCATE_START:
|
|
case FUZZ_TRUNCATE_END:
|
|
assert(fuzz->o1 <= fuzz->slen);
|
|
return fuzz->slen - fuzz->o1;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
u_char *
|
|
fuzz_ptr(struct fuzz *fuzz)
|
|
{
|
|
assert(fuzz->fuzzed != NULL);
|
|
switch (fuzz->strategy) {
|
|
case FUZZ_1_BIT_FLIP:
|
|
case FUZZ_2_BIT_FLIP:
|
|
case FUZZ_1_BYTE_FLIP:
|
|
case FUZZ_2_BYTE_FLIP:
|
|
case FUZZ_BASE64:
|
|
return fuzz->fuzzed;
|
|
case FUZZ_TRUNCATE_START:
|
|
assert(fuzz->o1 <= fuzz->slen);
|
|
return fuzz->fuzzed + fuzz->o1;
|
|
case FUZZ_TRUNCATE_END:
|
|
assert(fuzz->o1 <= fuzz->slen);
|
|
return fuzz->fuzzed;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|