Hash :
de53972f
Author :
Date :
2018-07-20T11:07:47
fuzzers: avoid use of libgit2 internals in packfile_raw The packfile_raw fuzzer is using some internal APIs from libgit2, which makes it hard to compile it as part of the oss-fuzz project. As oss-fuzz requires us to link against the C++ FuzzingEngine library, we cannot use "-DBUILD_FUZZERS=ON" directly but instead have to first compile an object from our fuzzers and then link against the C++ library. Compiling the fuzzer objects thus requires an external invocation of CC, and we certainly don't want to do further black magic by adding libgit2's private source directory to the header include path. To fix the issue, convert the code to not use any internal APIs. Besides some headers which we have to add now, this also requires us to change to the hashing function of the ODB. Note that this will change the hashing result, as we have previously not prepended the object header to the data that is to be hashed. But this shouldn't matter in practice, as we don't care for the hash value anyway.
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
/*
* libgit2 packfile fuzzer target.
*
* 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 <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include <unistd.h>
#include "git2.h"
#include "git2/sys/mempack.h"
#define UNUSED(x) (void)(x)
static git_odb *odb = NULL;
static git_odb_backend *mempack = NULL;
/* Arbitrary object to seed the ODB. */
static const unsigned char base_obj[] = { 07, 076 };
static const unsigned int base_obj_len = 2;
int LLVMFuzzerInitialize(int *argc, char ***argv)
{
UNUSED(argc);
UNUSED(argv);
if (git_libgit2_init() < 0) {
fprintf(stderr, "Failed to initialize libgit2\n");
abort();
}
if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS, 10000000) < 0) {
fprintf(stderr, "Failed to limit maximum pack object count\n");
abort();
}
if (git_odb_new(&odb) < 0) {
fprintf(stderr, "Failed to create the odb\n");
abort();
}
if (git_mempack_new(&mempack) < 0) {
fprintf(stderr, "Failed to create the mempack\n");
abort();
}
if (git_odb_add_backend(odb, mempack, 999) < 0) {
fprintf(stderr, "Failed to add the mempack\n");
abort();
}
return 0;
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
git_indexer *indexer = NULL;
git_transfer_progress stats = {0, 0};
bool append_hash = false;
git_oid id;
char hash[GIT_OID_HEXSZ + 1] = {0};
char path[PATH_MAX];
if (size == 0)
return 0;
if (!odb || !mempack) {
fprintf(stderr, "Global state not initialized\n");
abort();
}
git_mempack_reset(mempack);
if (git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB) < 0) {
fprintf(stderr, "Failed to add an object to the odb\n");
abort();
}
if (git_indexer_new(&indexer, ".", 0, odb, NULL, NULL) < 0) {
fprintf(stderr, "Failed to create the indexer: %s\n",
giterr_last()->message);
abort();
}
/*
* If the first byte in the stream has the high bit set, append the
* SHA1 hash so that the packfile is somewhat valid.
*/
append_hash = *data & 0x80;
++data;
--size;
if (git_indexer_append(indexer, data, size, &stats) < 0)
goto cleanup;
if (append_hash) {
git_oid oid;
if (git_odb_hash(&oid, data, size, GIT_OBJ_BLOB) < 0) {
fprintf(stderr, "Failed to compute the SHA1 hash\n");
abort();
}
if (git_indexer_append(indexer, &oid, sizeof(oid), &stats) < 0) {
goto cleanup;
}
}
if (git_indexer_commit(indexer, &stats) < 0)
goto cleanup;
/*
* We made it! We managed to produce a valid packfile.
* Let's clean it up.
*/
git_oid_fmt(hash, git_indexer_hash(indexer));
printf("Generated packfile %s\n", hash);
snprintf(path, sizeof(path), "pack-%s.idx", hash);
unlink(path);
snprintf(path, sizeof(path), "pack-%s.pack", hash);
unlink(path);
cleanup:
git_mempack_reset(mempack);
git_indexer_free(indexer);
return 0;
}