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