2 * libgit2 raw packfile fuzz target.
4 * Copyright (C) the libgit2 contributors. All rights reserved.
6 * This file is part of libgit2, distributed under the GNU GPL v2 with
7 * a Linking Exception. For full terms see the included COPYING file.
15 #include "git2/sys/transport.h"
18 #define UNUSED(x) (void)(x)
20 struct fuzzer_buffer
{
21 const unsigned char *data
;
25 struct fuzzer_stream
{
26 git_smart_subtransport_stream base
;
27 const unsigned char *readp
;
28 const unsigned char *endp
;
31 struct fuzzer_subtransport
{
32 git_smart_subtransport base
;
34 struct fuzzer_buffer data
;
37 static git_repository
*repo
;
39 static int fuzzer_stream_read(git_smart_subtransport_stream
*stream
,
44 struct fuzzer_stream
*fs
= (struct fuzzer_stream
*) stream
;
45 size_t avail
= fs
->endp
- fs
->readp
;
47 *bytes_read
= (buf_size
> avail
) ? avail
: buf_size
;
48 memcpy(buffer
, fs
->readp
, *bytes_read
);
49 fs
->readp
+= *bytes_read
;
54 static int fuzzer_stream_write(git_smart_subtransport_stream
*stream
,
55 const char *buffer
, size_t len
)
63 static void fuzzer_stream_free(git_smart_subtransport_stream
*stream
)
68 static int fuzzer_stream_new(
69 struct fuzzer_stream
**out
,
70 const struct fuzzer_buffer
*data
)
72 struct fuzzer_stream
*stream
= malloc(sizeof(*stream
));
76 stream
->readp
= data
->data
;
77 stream
->endp
= data
->data
+ data
->size
;
78 stream
->base
.read
= fuzzer_stream_read
;
79 stream
->base
.write
= fuzzer_stream_write
;
80 stream
->base
.free
= fuzzer_stream_free
;
87 static int fuzzer_subtransport_action(
88 git_smart_subtransport_stream
**out
,
89 git_smart_subtransport
*transport
,
91 git_smart_service_t action
)
93 struct fuzzer_subtransport
*ft
= (struct fuzzer_subtransport
*) transport
;
98 return fuzzer_stream_new((struct fuzzer_stream
**) out
, &ft
->data
);
101 static int fuzzer_subtransport_close(git_smart_subtransport
*transport
)
107 static void fuzzer_subtransport_free(git_smart_subtransport
*transport
)
112 static int fuzzer_subtransport_new(
113 struct fuzzer_subtransport
**out
,
114 git_transport
*owner
,
115 const struct fuzzer_buffer
*data
)
117 struct fuzzer_subtransport
*sub
= malloc(sizeof(*sub
));
122 sub
->data
.data
= data
->data
;
123 sub
->data
.size
= data
->size
;
124 sub
->base
.action
= fuzzer_subtransport_action
;
125 sub
->base
.close
= fuzzer_subtransport_close
;
126 sub
->base
.free
= fuzzer_subtransport_free
;
133 int fuzzer_subtransport_cb(
134 git_smart_subtransport
**out
,
135 git_transport
*owner
,
138 struct fuzzer_buffer
*buf
= (struct fuzzer_buffer
*) payload
;
139 struct fuzzer_subtransport
*sub
;
141 if (fuzzer_subtransport_new(&sub
, owner
, buf
) < 0)
148 int fuzzer_transport_cb(git_transport
**out
, git_remote
*owner
, void *param
)
150 git_smart_subtransport_definition def
= {
151 fuzzer_subtransport_cb
,
155 return git_transport_smart(out
, owner
, &def
);
158 void fuzzer_git_abort(const char *op
)
160 const git_error
*err
= git_error_last();
161 fprintf(stderr
, "unexpected libgit error: %s: %s\n",
162 op
, err
? err
->message
: "<none>");
166 int LLVMFuzzerInitialize(int *argc
, char ***argv
)
169 char tmpdir
[MAX_PATH
], path
[MAX_PATH
];
171 if (GetTempPath((DWORD
)sizeof(tmpdir
), tmpdir
) == 0)
174 if (GetTempFileName(tmpdir
, "lg2", 1, path
) == 0)
177 if (git_futils_mkdir(path
, 0700, 0) < 0)
180 char path
[] = "/tmp/git2.XXXXXX";
182 if (mkdtemp(path
) != path
)
186 if (git_libgit2_init() < 0)
189 if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS
, 10000000) < 0)
195 if (git_repository_init(&repo
, path
, 1) < 0)
196 fuzzer_git_abort("git_repository_init");
201 int LLVMFuzzerTestOneInput(const unsigned char *data
, size_t size
)
203 struct fuzzer_buffer buffer
= { data
, size
};
204 git_remote_callbacks callbacks
= GIT_REMOTE_CALLBACKS_INIT
;
207 if (git_remote_create_anonymous(&remote
, repo
, "fuzzer://remote-url") < 0)
208 fuzzer_git_abort("git_remote_create");
210 callbacks
.transport
= fuzzer_transport_cb
;
211 callbacks
.payload
= &buffer
;
213 if (git_remote_connect(remote
, GIT_DIRECTION_FETCH
,
214 &callbacks
, NULL
, NULL
) < 0)
217 git_remote_download(remote
, NULL
, NULL
);
220 git_remote_free(remote
);