diff --git a/fuzz/test-corpus.c b/fuzz/test-corpus.c index c553697d6c..7eeac4ca90 100644 --- a/fuzz/test-corpus.c +++ b/fuzz/test-corpus.c @@ -16,9 +16,47 @@ #include #include +#include #include #include #include "fuzzer.h" +#include "internal/o_dir.h" + +#if defined(_WIN32) && defined(_MAX_PATH) +# define PATH_MAX _MAX_PATH +#endif + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +# 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; + + if (stat(pathname, &st) < 0 || !S_ISREG(st.st_mode)) + return; + printf("# %s\n", pathname); + fflush(stdout); + f = fopen(pathname, "rb"); + if (f == NULL) + 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; @@ -26,21 +64,38 @@ int main(int argc, char **argv) { FuzzerInitialize(&argc, &argv); for (n = 1; n < argc; ++n) { - struct stat st; - FILE *f; - unsigned char *buf; - size_t s; + size_t dirname_len = strlen(argv[n]); + const char *filename = NULL; + char *pathname = NULL; + OPENSSL_DIR_CTX *ctx = NULL; + int wasdir = 0; - stat(argv[n], &st); - f = fopen(argv[n], "rb"); - if (f == NULL) - continue; - buf = malloc(st.st_size); - s = fread(buf, 1, st.st_size, f); - OPENSSL_assert(s == (size_t)st.st_size); - FuzzerTestOneInput(buf, s); - free(buf); - fclose(f); + /* + * 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; } diff --git a/test/recipes/90-test_fuzz.t b/test/recipes/90-test_fuzz.t index d152925733..753a1f2123 100644 --- a/test/recipes/90-test_fuzz.t +++ b/test/recipes/90-test_fuzz.t @@ -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", $_]))); } }