Commit 5db64e2f by Patrick Steinhardt

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.
parent 730c0edb
/*
* 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;
}
#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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment