Hash :
6956a954
Author :
Date :
2018-10-11T12:26:44
fuzzers: initialize libgit2 in standalone driver The standalone driver for libgit2's fuzzing targets makes use of functions from libgit2 itself. While this is totally fine to do, we need to make sure to always have libgit2 initialized via `git_libgit2_init` before we call out to any of these. While this happens in most cases as we call `LLVMFuzzerInitialize`, which is provided by our fuzzers and which right now always calls `git_libgit2_init`, one exception to this rule is our error path when not enough arguments have been given. In this case, we will call `git_vector_free_deep` without libgit2 having been initialized. As we did not set up our allocation functions in that case, this will lead to a segmentation fault. Fix the issue by always initializing and shutting down libgit2 in the standalone driver. Note that we cannot let this replace the initialization in `LLVMFuzzerInitialize`, as it is required when using the "real" fuzzers by LLVM without our standalone driver. It's no problem to call the initialization and deinitialization functions multiple times, though.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <assert.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "git2.h"
#include "fileops.h"
#include "path.h"
extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
extern int LLVMFuzzerInitialize(int *argc, char ***argv);
static int run_one_file(const char *filename)
{
git_buf buf = GIT_BUF_INIT;
int error = 0;
if (git_futils_readbuffer(&buf, filename) < 0) {
fprintf(stderr, "Failed to read %s: %m\n", filename);
error = -1;
goto exit;
}
LLVMFuzzerTestOneInput((const unsigned char *)buf.ptr, buf.size);
exit:
git_buf_dispose(&buf);
return error;
}
int main(int argc, char **argv)
{
git_vector corpus_files = GIT_VECTOR_INIT;
char *filename = NULL;
unsigned i = 0;
int error = 0;
if (git_libgit2_init() < 0) {
fprintf(stderr, "Failed to initialize libgit2\n");
abort();
}
if (argc != 2) {
fprintf(stderr, "Usage: %s <corpus directory>\n", argv[0]);
error = -1;
goto exit;
}
fprintf(stderr, "Running %s against %s\n", argv[0], argv[1]);
LLVMFuzzerInitialize(&argc, &argv);
if (git_path_dirload(&corpus_files, argv[1], 0, 0x0) < 0) {
fprintf(stderr, "Failed to scan corpus directory: %m\n");
error = -1;
goto exit;
}
git_vector_foreach(&corpus_files, i, filename) {
fprintf(stderr, "\tRunning %s...\n", filename);
if (run_one_file(filename) < 0) {
error = -1;
goto exit;
}
}
fprintf(stderr, "Done %d runs\n", i);
exit:
git_vector_free_deep(&corpus_files);
git_libgit2_shutdown();
return error;
}