From c0661eefc43657b391666caf0bf2f91fda52245f Mon Sep 17 00:00:00 2001 From: Nelson Elhage Date: Fri, 13 Jul 2018 08:13:05 -0700 Subject: [PATCH] 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 --- projects/libgit2/Dockerfile | 24 +++ projects/libgit2/build.sh | 35 ++++ .../libgit2/corpora/download_refs/clone.dat | Bin 0 -> 632 bytes projects/libgit2/download_refs_fuzzer.cc | 156 ++++++++++++++++++ projects/libgit2/project.yaml | 4 + 5 files changed, 219 insertions(+) create mode 100644 projects/libgit2/Dockerfile create mode 100755 projects/libgit2/build.sh create mode 100644 projects/libgit2/corpora/download_refs/clone.dat create mode 100644 projects/libgit2/download_refs_fuzzer.cc create mode 100644 projects/libgit2/project.yaml diff --git a/projects/libgit2/Dockerfile b/projects/libgit2/Dockerfile new file mode 100644 index 000000000..368a202a4 --- /dev/null +++ b/projects/libgit2/Dockerfile @@ -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 +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 diff --git a/projects/libgit2/build.sh b/projects/libgit2/build.sh new file mode 100755 index 000000000..acdc815eb --- /dev/null +++ b/projects/libgit2/build.sh @@ -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/* diff --git a/projects/libgit2/corpora/download_refs/clone.dat b/projects/libgit2/corpora/download_refs/clone.dat new file mode 100644 index 0000000000000000000000000000000000000000..f3e56b06b4b160af545c5d688400a52bd0ad7695 GIT binary patch literal 632 zcmXpoFi25WNY2mAP0cGYFi0~pH%LxRGPN{GF*Y(xwJVaP4bDanjaOwLv)$;iypEda5KGgDG^lM?e%5G-9YlWc|jv|`^6{R2U~OzXZlCO3g_u$t+7%$jjF)D9TSSN-Zu{ z0IJO?1zJ#&n63b~Jw7G1Br!856=-E;Zc%EQEy!_JKt{2CMrvY8v3_o1aY<^CLSj15 zm$vDdCHh8shK70uTm}ZlX+--N!#tpNFtG4*^aiqx449nrOY=%H^U@Xald@8iONy-& zjCB-J^7B&lK=MgUA^9bVISR%K8jyf6(9}^VN-Zr0I@|yu22`42$r#}1?9ITyzy!q1 zGr23~%+wLu#{IZZ~Cd;vJ|AemyN6gleyYhH0$Fz(S z3!I*AiJs&g=&75|BfiN@V`j6v?e8h9`zqgB+pO4E)x2`u50xEezj}VJKfg2ITw +#include + +#include +#include +#include + +#include + +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(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(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(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(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(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 : ""); + 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; +} diff --git a/projects/libgit2/project.yaml b/projects/libgit2/project.yaml new file mode 100644 index 000000000..6ccc74d21 --- /dev/null +++ b/projects/libgit2/project.yaml @@ -0,0 +1,4 @@ +homepage: "https://libgit2.github.com/" +auto_ccs: + - "nelhage@nelhage.com" +primary_contact: ""