Coverage Report

Created: 2025-06-20 06:37

/src/libgit2/fuzzers/download_refs_fuzzer.c
Line
Count
Source (jump to first uncovered line)
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
#include "fuzzer_utils.h"
20
21
38.3k
#define UNUSED(x) (void)(x)
22
23
struct fuzzer_buffer {
24
  const unsigned char *data;
25
  size_t size;
26
};
27
28
struct fuzzer_stream {
29
  git_smart_subtransport_stream base;
30
  const unsigned char *readp;
31
  const unsigned char *endp;
32
};
33
34
struct fuzzer_subtransport {
35
  git_smart_subtransport base;
36
  git_transport *owner;
37
  struct fuzzer_buffer data;
38
};
39
40
static git_repository *repo;
41
42
static int fuzzer_stream_read(git_smart_subtransport_stream *stream,
43
  char *buffer,
44
  size_t buf_size,
45
  size_t *bytes_read)
46
9.71k
{
47
9.71k
  struct fuzzer_stream *fs = (struct fuzzer_stream *) stream;
48
9.71k
  size_t avail = fs->endp - fs->readp;
49
50
9.71k
  *bytes_read = (buf_size > avail) ? avail : buf_size;
51
9.71k
  memcpy(buffer, fs->readp, *bytes_read);
52
9.71k
  fs->readp += *bytes_read;
53
54
9.71k
  return 0;
55
9.71k
}
56
57
static int fuzzer_stream_write(git_smart_subtransport_stream *stream,
58
    const char *buffer, size_t len)
59
3.12k
{
60
3.12k
  UNUSED(stream);
61
3.12k
  UNUSED(buffer);
62
3.12k
  UNUSED(len);
63
3.12k
  return 0;
64
3.12k
}
65
66
static void fuzzer_stream_free(git_smart_subtransport_stream *stream)
67
7.85k
{
68
7.85k
  free(stream);
69
7.85k
}
70
71
static int fuzzer_stream_new(
72
  struct fuzzer_stream **out,
73
  const struct fuzzer_buffer *data)
74
7.85k
{
75
7.85k
  struct fuzzer_stream *stream = malloc(sizeof(*stream));
76
7.85k
  if (!stream)
77
0
    return -1;
78
79
7.85k
  stream->readp = data->data;
80
7.85k
  stream->endp = data->data + data->size;
81
7.85k
  stream->base.read = fuzzer_stream_read;
82
7.85k
  stream->base.write = fuzzer_stream_write;
83
7.85k
  stream->base.free = fuzzer_stream_free;
84
85
7.85k
  *out = stream;
86
87
7.85k
  return 0;
88
7.85k
}
89
90
static int fuzzer_subtransport_action(
91
  git_smart_subtransport_stream **out,
92
  git_smart_subtransport *transport,
93
  const char *url,
94
  git_smart_service_t action)
95
7.85k
{
96
7.85k
  struct fuzzer_subtransport *ft = (struct fuzzer_subtransport *) transport;
97
98
7.85k
  UNUSED(url);
99
7.85k
  UNUSED(action);
100
101
7.85k
  return fuzzer_stream_new((struct fuzzer_stream **) out, &ft->data);
102
7.85k
}
103
104
static int fuzzer_subtransport_close(git_smart_subtransport *transport)
105
13.2k
{
106
13.2k
  UNUSED(transport);
107
13.2k
  return 0;
108
13.2k
}
109
110
static void fuzzer_subtransport_free(git_smart_subtransport *transport)
111
4.72k
{
112
4.72k
  free(transport);
113
4.72k
}
114
115
static int fuzzer_subtransport_new(
116
  struct fuzzer_subtransport **out,
117
  git_transport *owner,
118
  const struct fuzzer_buffer *data)
119
4.72k
{
120
4.72k
  struct fuzzer_subtransport *sub = malloc(sizeof(*sub));
121
4.72k
  if (!sub)
122
0
    return -1;
123
124
4.72k
  sub->owner = owner;
125
4.72k
  sub->data.data = data->data;
126
4.72k
  sub->data.size = data->size;
127
4.72k
  sub->base.action = fuzzer_subtransport_action;
128
4.72k
  sub->base.close = fuzzer_subtransport_close;
129
4.72k
  sub->base.free = fuzzer_subtransport_free;
130
131
4.72k
  *out = sub;
132
133
4.72k
  return 0;
134
4.72k
}
135
136
static int fuzzer_subtransport_cb(
137
  git_smart_subtransport **out,
138
  git_transport *owner,
139
  void *payload)
140
4.72k
{
141
4.72k
  struct fuzzer_buffer *buf = (struct fuzzer_buffer *) payload;
142
4.72k
  struct fuzzer_subtransport *sub;
143
144
4.72k
  if (fuzzer_subtransport_new(&sub, owner, buf) < 0)
145
0
    return -1;
146
147
4.72k
  *out = &sub->base;
148
4.72k
  return 0;
149
4.72k
}
150
151
static int fuzzer_transport_cb(git_transport **out, git_remote *owner, void *param)
152
4.72k
{
153
4.72k
  git_smart_subtransport_definition def = {
154
4.72k
    fuzzer_subtransport_cb,
155
4.72k
    1,
156
4.72k
    param
157
4.72k
  };
158
4.72k
  return git_transport_smart(out, owner, &def);
159
4.72k
}
160
161
int LLVMFuzzerInitialize(int *argc, char ***argv)
162
4
{
163
4
  UNUSED(argc);
164
4
  UNUSED(argv);
165
166
4
  if (git_libgit2_init() < 0)
167
0
    abort();
168
169
4
  if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS, 10000000) < 0)
170
0
    abort();
171
172
4
  repo = fuzzer_repo_init();
173
4
  return 0;
174
4
}
175
176
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
177
4.72k
{
178
4.72k
  struct fuzzer_buffer buffer = { data, size };
179
4.72k
  git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
180
4.72k
  git_remote *remote;
181
182
4.72k
  if (git_remote_create_anonymous(&remote, repo, "fuzzer://remote-url") < 0)
183
0
    fuzzer_git_abort("git_remote_create");
184
185
4.72k
  callbacks.transport = fuzzer_transport_cb;
186
4.72k
  callbacks.payload = &buffer;
187
188
4.72k
  if (git_remote_connect(remote, GIT_DIRECTION_FETCH,
189
4.72k
      &callbacks, NULL, NULL) < 0)
190
912
    goto out;
191
192
3.81k
  git_remote_download(remote, NULL, NULL);
193
194
4.72k
    out:
195
4.72k
  git_remote_free(remote);
196
197
4.72k
  return 0;
198
3.81k
}