]> git.proxmox.com Git - libgit2.git/blob - fuzzers/download_refs_fuzzer.c
c5726cba186afb34e4525a8be33264e558199211
[libgit2.git] / fuzzers / download_refs_fuzzer.c
1 /*
2 * libgit2 raw packfile fuzz target.
3 *
4 * Copyright (C) the libgit2 contributors. All rights reserved.
5 *
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.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "git2.h"
15 #include "git2/sys/transport.h"
16 #include "futils.h"
17
18 #define UNUSED(x) (void)(x)
19
20 struct fuzzer_buffer {
21 const unsigned char *data;
22 size_t size;
23 };
24
25 struct fuzzer_stream {
26 git_smart_subtransport_stream base;
27 const unsigned char *readp;
28 const unsigned char *endp;
29 };
30
31 struct fuzzer_subtransport {
32 git_smart_subtransport base;
33 git_transport *owner;
34 struct fuzzer_buffer data;
35 };
36
37 static git_repository *repo;
38
39 static int fuzzer_stream_read(git_smart_subtransport_stream *stream,
40 char *buffer,
41 size_t buf_size,
42 size_t *bytes_read)
43 {
44 struct fuzzer_stream *fs = (struct fuzzer_stream *) stream;
45 size_t avail = fs->endp - fs->readp;
46
47 *bytes_read = (buf_size > avail) ? avail : buf_size;
48 memcpy(buffer, fs->readp, *bytes_read);
49 fs->readp += *bytes_read;
50
51 return 0;
52 }
53
54 static int fuzzer_stream_write(git_smart_subtransport_stream *stream,
55 const char *buffer, size_t len)
56 {
57 UNUSED(stream);
58 UNUSED(buffer);
59 UNUSED(len);
60 return 0;
61 }
62
63 static void fuzzer_stream_free(git_smart_subtransport_stream *stream)
64 {
65 free(stream);
66 }
67
68 static int fuzzer_stream_new(
69 struct fuzzer_stream **out,
70 const struct fuzzer_buffer *data)
71 {
72 struct fuzzer_stream *stream = malloc(sizeof(*stream));
73 if (!stream)
74 return -1;
75
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;
81
82 *out = stream;
83
84 return 0;
85 }
86
87 static int fuzzer_subtransport_action(
88 git_smart_subtransport_stream **out,
89 git_smart_subtransport *transport,
90 const char *url,
91 git_smart_service_t action)
92 {
93 struct fuzzer_subtransport *ft = (struct fuzzer_subtransport *) transport;
94
95 UNUSED(url);
96 UNUSED(action);
97
98 return fuzzer_stream_new((struct fuzzer_stream **) out, &ft->data);
99 }
100
101 static int fuzzer_subtransport_close(git_smart_subtransport *transport)
102 {
103 UNUSED(transport);
104 return 0;
105 }
106
107 static void fuzzer_subtransport_free(git_smart_subtransport *transport)
108 {
109 free(transport);
110 }
111
112 static int fuzzer_subtransport_new(
113 struct fuzzer_subtransport **out,
114 git_transport *owner,
115 const struct fuzzer_buffer *data)
116 {
117 struct fuzzer_subtransport *sub = malloc(sizeof(*sub));
118 if (!sub)
119 return -1;
120
121 sub->owner = owner;
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;
127
128 *out = sub;
129
130 return 0;
131 }
132
133 int fuzzer_subtransport_cb(
134 git_smart_subtransport **out,
135 git_transport *owner,
136 void *payload)
137 {
138 struct fuzzer_buffer *buf = (struct fuzzer_buffer *) payload;
139 struct fuzzer_subtransport *sub;
140
141 if (fuzzer_subtransport_new(&sub, owner, buf) < 0)
142 return -1;
143
144 *out = &sub->base;
145 return 0;
146 }
147
148 int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
149 {
150 git_smart_subtransport_definition def = {
151 fuzzer_subtransport_cb,
152 1,
153 param
154 };
155 return git_transport_smart(out, owner, &def);
156 }
157
158 void fuzzer_git_abort(const char *op)
159 {
160 const git_error *err = git_error_last();
161 fprintf(stderr, "unexpected libgit error: %s: %s\n",
162 op, err ? err->message : "<none>");
163 abort();
164 }
165
166 int LLVMFuzzerInitialize(int *argc, char ***argv)
167 {
168 #if defined(_WIN32)
169 char tmpdir[MAX_PATH], path[MAX_PATH];
170
171 if (GetTempPath((DWORD)sizeof(tmpdir), tmpdir) == 0)
172 abort();
173
174 if (GetTempFileName(tmpdir, "lg2", 1, path) == 0)
175 abort();
176
177 if (git_futils_mkdir(path, 0700, 0) < 0)
178 abort();
179 #else
180 char path[] = "/tmp/git2.XXXXXX";
181
182 if (mkdtemp(path) != path)
183 abort();
184 #endif
185
186 if (git_libgit2_init() < 0)
187 abort();
188
189 if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS, 10000000) < 0)
190 abort();
191
192 UNUSED(argc);
193 UNUSED(argv);
194
195 if (git_repository_init(&repo, path, 1) < 0)
196 fuzzer_git_abort("git_repository_init");
197
198 return 0;
199 }
200
201 int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
202 {
203 struct fuzzer_buffer buffer = { data, size };
204 git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
205 git_remote *remote;
206
207 if (git_remote_create_anonymous(&remote, repo, "fuzzer://remote-url") < 0)
208 fuzzer_git_abort("git_remote_create");
209
210 callbacks.transport = fuzzer_transport_cb;
211 callbacks.payload = &buffer;
212
213 if (git_remote_connect(remote, GIT_DIRECTION_FETCH,
214 &callbacks, NULL, NULL) < 0)
215 goto out;
216
217 git_remote_download(remote, NULL, NULL);
218
219 out:
220 git_remote_free(remote);
221
222 return 0;
223 }