Commit 5db64e2f1b05df6620c99073a7798f9f4feabd09

Patrick Steinhardt 2018-07-19T14:52:02

fuzzers: convert download_refs fuzzer to C Convert the "download_refs" fuzzer from C++ to C. Rename the source file to have it be picked up by our build system.

diff --git a/fuzzers/download_refs_fuzzer.c b/fuzzers/download_refs_fuzzer.c
new file mode 100644
index 0000000..fd10409
--- /dev/null
+++ b/fuzzers/download_refs_fuzzer.c
@@ -0,0 +1,208 @@
+/*
+ * libgit2 raw packfile fuzz 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 <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "git2.h"
+#include "git2/sys/transport.h"
+
+#define UNUSED(x) (void)(x)
+
+struct fuzzer_buffer {
+	const unsigned char *data;
+	size_t size;
+};
+
+struct fuzzer_stream {
+	git_smart_subtransport_stream base;
+	const unsigned char *readp;
+	const unsigned char *endp;
+};
+
+struct fuzzer_subtransport {
+	git_smart_subtransport base;
+	git_transport *owner;
+	struct fuzzer_buffer data;
+};
+
+static git_repository *repo;
+
+static int fuzzer_stream_read(git_smart_subtransport_stream *stream,
+	char *buffer,
+	size_t buf_size,
+	size_t *bytes_read)
+{
+	struct fuzzer_stream *fs = (struct fuzzer_stream *) stream;
+	size_t avail = fs->endp - fs->readp;
+
+	*bytes_read = (buf_size > avail) ? avail : buf_size;
+	memcpy(buffer, fs->readp, *bytes_read);
+	fs->readp += *bytes_read;
+
+	return 0;
+}
+
+static int fuzzer_stream_write(git_smart_subtransport_stream *stream,
+	  const char *buffer, size_t len)
+{
+	UNUSED(stream);
+	UNUSED(buffer);
+	UNUSED(len);
+	return 0;
+}
+
+static void fuzzer_stream_free(git_smart_subtransport_stream *stream)
+{
+	free(stream);
+}
+
+static int fuzzer_stream_new(
+	struct fuzzer_stream **out,
+	const struct fuzzer_buffer *data)
+{
+	struct fuzzer_stream *stream = malloc(sizeof(*stream));
+	if (!stream)
+		return -1;
+
+	stream->readp = data->data;
+	stream->endp = data->data + data->size;
+	stream->base.read = fuzzer_stream_read;
+	stream->base.write = fuzzer_stream_write;
+	stream->base.free = fuzzer_stream_free;
+
+	*out = stream;
+
+	return 0;
+}
+
+static int fuzzer_subtransport_action(
+	git_smart_subtransport_stream **out,
+	git_smart_subtransport *transport,
+	const char *url,
+	git_smart_service_t action)
+{
+	struct fuzzer_subtransport *ft = (struct fuzzer_subtransport *) transport;
+
+	UNUSED(url);
+	UNUSED(action);
+
+	return fuzzer_stream_new((struct fuzzer_stream **) out, &ft->data);
+}
+
+static int fuzzer_subtransport_close(git_smart_subtransport *transport)
+{
+	UNUSED(transport);
+	return 0;
+}
+
+static void fuzzer_subtransport_free(git_smart_subtransport *transport)
+{
+	free(transport);
+}
+
+static int fuzzer_subtransport_new(
+	struct fuzzer_subtransport **out,
+	git_transport *owner,
+	const struct fuzzer_buffer *data)
+{
+	struct fuzzer_subtransport *sub = malloc(sizeof(*sub));
+	if (!sub)
+		return -1;
+
+	sub->owner = owner;
+	sub->data.data = data->data;
+	sub->data.size = data->size;
+	sub->base.action = fuzzer_subtransport_action;
+	sub->base.close = fuzzer_subtransport_close;
+	sub->base.free = fuzzer_subtransport_free;
+
+	*out = sub;
+
+	return 0;
+}
+
+int fuzzer_subtransport_cb(
+	git_smart_subtransport **out,
+	git_transport *owner,
+	void *payload)
+{
+	struct fuzzer_buffer *buf = (struct fuzzer_buffer *) payload;
+	struct fuzzer_subtransport *sub;
+
+	if (fuzzer_subtransport_new(&sub, owner, buf) < 0)
+		return -1;
+
+	*out = &sub->base;
+	return 0;
+}
+
+int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
+{
+	git_smart_subtransport_definition def = {
+		fuzzer_subtransport_cb,
+		1,
+		param
+	};
+	return git_transport_smart(out, owner, &def);
+}
+
+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();
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+	char tmp[] = "/tmp/git2.XXXXXX";
+
+	UNUSED(argc);
+	UNUSED(argv);
+
+	if (git_libgit2_init() < 0)
+		abort();
+
+	if (mkdtemp(tmp) != tmp)
+		abort();
+
+	if (git_repository_init(&repo, tmp, 1) < 0)
+		fuzzer_git_abort("git_repository_init");
+
+	return 0;
+}
+
+int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
+{
+	struct fuzzer_buffer buffer = { data, size };
+	git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+	git_remote *remote;
+
+	if (git_remote_create_anonymous(&remote, repo, "fuzzer://remote-url") < 0)
+		fuzzer_git_abort("git_remote_create");
+
+	callbacks.transport = fuzzer_transport_cb;
+	callbacks.payload = &buffer;
+
+	if (git_remote_connect(remote, GIT_DIRECTION_FETCH,
+	    &callbacks, NULL, NULL) < 0)
+		goto out;
+
+	git_remote_download(remote, NULL, NULL);
+
+    out:
+	git_remote_free(remote);
+
+	return 0;
+}
diff --git a/fuzzers/download_refs_fuzzer.cc b/fuzzers/download_refs_fuzzer.cc
deleted file mode 100644
index 939e67f..0000000
--- a/fuzzers/download_refs_fuzzer.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-#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;
-}