Add a fuzzer for libgit2 (#1604)

* Add a libgit2 fuzzer for the `git fetch` client

* Use a fresh remote each time

* Build fewer things, use fewer deps

* no ssh, either

* Add a corpus with one file.

Slightly tweaked network dump of a `git clone` on a tiny repo.

* auto_ccs is a list

* Rename the fuzzer

* only email in project.yaml

* Use `master`

I had left in a `-b oss-fuzz` from testing off my fork
This commit is contained in:
Nelson Elhage 2018-07-13 08:13:05 -07:00 committed by Kostya Serebryany
parent 6ec00106a5
commit c0661eefc4
5 changed files with 219 additions and 0 deletions

View File

@ -0,0 +1,24 @@
# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
MAINTAINER Nelson Elhage <nelhage@nelhage.com>
RUN apt-get update && apt-get install -y make autoconf automake libtool cmake
RUN git clone --depth 1 https://github.com/libgit2/libgit2 libgit2
WORKDIR libgit2
COPY download_refs_fuzzer.cc build.sh $SRC/
COPY corpora $SRC/corpora

35
projects/libgit2/build.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash -eu
# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
# build project
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX="$WORK" \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_CLAR=OFF \
-DUSE_HTTPS=OFF \
-DUSE_SSH=OFF \
-DUSE_BUNDLED_ZLIB=ON \
make -j$(nproc)
make install
$CXX $CXXFLAGS -std=c++11 -I"$WORK/include" \
/src/download_refs_fuzzer.cc -o $OUT/download_refs_fuzzer \
-lFuzzingEngine "$WORK/lib/libgit2.a"
zip -j "$OUT/download_refs_fuzzer_seed_corpus.zip" $SRC/corpora/download_refs/*

Binary file not shown.

View File

@ -0,0 +1,156 @@
#include <git2.h>
#include <git2/sys/transport.h>
#include <cstring>
#include <cstdlib>
#include <sys/stat.h>
#include <string>
struct fuzz_buffer {
const uint8_t *data;
size_t size;
};
class fuzzer_stream {
public:
git_smart_subtransport_stream base;
fuzzer_stream(fuzz_buffer data) : readp(data.data), endp(data.data + data.size) {
base.read = fuzzer_stream::read;
base.write = fuzzer_stream::write;
base.free = fuzzer_stream::free;
}
int do_read(char *buffer, size_t buf_size, size_t *bytes_read) {
size_t avail = endp - readp;
*bytes_read = std::min(buf_size, avail);
memcpy(buffer, readp, *bytes_read);
readp += *bytes_read;
return 0;
}
static int read(git_smart_subtransport_stream *stream,
char *buffer,
size_t buf_size,
size_t *bytes_read) {
fuzzer_stream *fs = reinterpret_cast<fuzzer_stream*>(stream);
return fs->do_read(buffer, buf_size, bytes_read);
}
static int write(git_smart_subtransport_stream *stream,
const char *buffer,
size_t len) {
return 0;
}
static void free(git_smart_subtransport_stream *stream) {
fuzzer_stream *fs = reinterpret_cast<fuzzer_stream*>(stream);
delete fs;
}
private:
const uint8_t *readp;
const uint8_t *endp;
};
class fuzzer_subtransport {
public:
git_smart_subtransport base;
fuzzer_subtransport(git_transport *owner, fuzz_buffer data) : owner(owner), data(data) {
base.action = fuzzer_subtransport::action;
base.close = fuzzer_subtransport::close;
base.free = fuzzer_subtransport::free;
}
int do_action(git_smart_subtransport_stream **out,
git_smart_subtransport *transport,
const char *url,
git_smart_service_t action) {
fuzzer_stream *stream = new fuzzer_stream(this->data);
*out = &stream->base;
return 0;
}
static int action(git_smart_subtransport_stream **out,
git_smart_subtransport *transport,
const char *url,
git_smart_service_t action) {
fuzzer_subtransport *ft = reinterpret_cast<fuzzer_subtransport*>(transport);
return ft->do_action(out, transport, url, action);
}
static int close(git_smart_subtransport *transport) {
return 0;
}
static void free(git_smart_subtransport *transport) {
fuzzer_subtransport *ft = reinterpret_cast<fuzzer_subtransport*>(transport);
delete ft;
}
private:
git_transport *owner;
fuzz_buffer data;
};
int fuzzer_subtransport_cb(git_smart_subtransport **out,
git_transport* owner,
void* param) {
fuzz_buffer *buf = static_cast<fuzz_buffer*>(param);
fuzzer_subtransport *sub = new fuzzer_subtransport(owner, *buf);
*out = &sub->base;
return 0;
}
int create_fuzzer_transport(git_transport **out, git_remote *owner, void *param) {
git_smart_subtransport_definition fuzzer_subtransport {fuzzer_subtransport_cb, 1, param};
return git_transport_smart(out, owner, &fuzzer_subtransport);
}
void fuzzer_git_abort(const char *op) {
const git_error *err = giterr_last();
fprintf(stderr, "unexpected libgit error: %s: %s\n",
op, err ? err->message : "<none>");
abort();
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
static git_repository *repo = nullptr;
if (repo == nullptr) {
git_libgit2_init();
char tmp[] = "/tmp/git2.XXXXXX";
if (mkdtemp(tmp) != tmp) {
abort();
}
int err = git_repository_init(&repo, tmp, true);
if (err != 0) {
fuzzer_git_abort("git_repository_init");
}
}
int err;
git_remote *remote;
err = git_remote_create_anonymous(&remote, repo, "fuzzer://remote-url");
if (err != 0) {
fuzzer_git_abort("git_remote_create");
}
fuzz_buffer buffer = {data, size};
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
callbacks.transport = create_fuzzer_transport;
callbacks.payload = &buffer;
err = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, nullptr, nullptr);
if (err != 0) {
goto out;
}
git_remote_download(remote, nullptr, nullptr);
out:
git_remote_free(remote);
return 0;
}

View File

@ -0,0 +1,4 @@
homepage: "https://libgit2.github.com/"
auto_ccs:
- "nelhage@nelhage.com"
primary_contact: "<ps@pks.im>"