Commit 0bdcf53f authored by Richard Levitte's avatar Richard Levitte
Browse files

Faster fuzz test: teach the fuzz test programs to handle directories



Instead of invoking the fuzz test programs once for every corpora
file, we invoke them once for each directory of corpora files.  This
dramatically reduces the number of program invokations, as well as the
time 90-test_fuzz.t takes to complete.

fuzz/test-corpus.c was enhanced to handle directories as well as
regular files.

Reviewed-by: default avatarBernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/5788)
parent 7ee2a430
Loading
Loading
Loading
Loading
+70 −15
Original line number Diff line number Diff line
@@ -16,31 +16,86 @@

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <openssl/crypto.h>
#include "fuzzer.h"
#include "internal/o_dir.h"

int main(int argc, char **argv) {
    int n;
#if defined(_WIN32) && defined(_MAX_PATH)
# define PATH_MAX _MAX_PATH
#endif

    FuzzerInitialize(&argc, &argv);
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif

    for (n = 1; n < argc; ++n) {
# if !defined(S_ISREG)
#   define S_ISREG(m) ((m) & S_IFREG)
# endif

static void testfile(const char *pathname)
{
    struct stat st;
    FILE *f;
    unsigned char *buf;
    size_t s;

        stat(argv[n], &st);
        f = fopen(argv[n], "rb");
    if (stat(pathname, &st) < 0 || !S_ISREG(st.st_mode))
        return;
    printf("# %s\n", pathname);
    fflush(stdout);
    f = fopen(pathname, "rb");
    if (f == NULL)
            continue;
        return;
    buf = malloc(st.st_size);
    if (buf != NULL) {
        s = fread(buf, 1, st.st_size, f);
        OPENSSL_assert(s == (size_t)st.st_size);
        FuzzerTestOneInput(buf, s);
        free(buf);
    }
    fclose(f);
}

int main(int argc, char **argv) {
    int n;

    FuzzerInitialize(&argc, &argv);

    for (n = 1; n < argc; ++n) {
        size_t dirname_len = strlen(argv[n]);
        const char *filename = NULL;
        char *pathname = NULL;
        OPENSSL_DIR_CTX *ctx = NULL;
        int wasdir = 0;

        /*
         * We start with trying to read the given path as a directory.
         */
        while ((filename = OPENSSL_DIR_read(&ctx, argv[n])) != NULL) {
            wasdir = 1;
            if (pathname == NULL) {
                pathname = malloc(PATH_MAX);
                if (pathname == NULL)
                    break;
                strcpy(pathname, argv[n]);
#ifdef __VMS
                if (strchr(":<]", pathname[dirname_len - 1]) == NULL)
#endif
                    pathname[dirname_len++] = '/';
                pathname[dirname_len] = '\0';
            }
            strcpy(pathname + dirname_len, filename);
            testfile(pathname);
        }
        OPENSSL_DIR_end(&ctx);

        /* If it wasn't a directory, treat it as a file instead */
        if (!wasdir)
            testfile(argv[n]);

        free(pathname);
    }
    return 0;
}
+5 −5
Original line number Diff line number Diff line
@@ -26,14 +26,14 @@ plan tests => scalar @fuzzers;

foreach my $f (@fuzzers) {
    subtest "Fuzzing $f" => sub {
        my @files = glob(srctop_file('fuzz', 'corpora', $f, '*'));
        push @files, glob(srctop_file('fuzz', 'corpora', "$f-*", '*'));
        my @dirs = glob(srctop_file('fuzz', 'corpora', $f));
        push @dirs, glob(srctop_file('fuzz', 'corpora', "$f-*"));

        plan skip_all => "No corpora for $f-test" unless @files;
        plan skip_all => "No corpora for $f-test" unless @dirs;

        plan tests => scalar @files;
        plan tests => scalar @dirs;

        foreach (@files) {
        foreach (@dirs) {
            ok(run(fuzz(["$f-test", $_])));
        }
    }