/src/libgit2/fuzzers/packfile_fuzzer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libgit2 packfile fuzzer 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 | | |
12 | | #include "git2.h" |
13 | | #include "git2/sys/mempack.h" |
14 | | #include "common.h" |
15 | | #include "str.h" |
16 | | |
17 | | #include "standalone_driver.h" |
18 | | |
19 | | static git_odb *odb = NULL; |
20 | | static git_odb_backend *mempack = NULL; |
21 | | |
22 | | /* Arbitrary object to seed the ODB. */ |
23 | | static const unsigned char base_obj[] = { 07, 076 }; |
24 | | static const unsigned int base_obj_len = 2; |
25 | | |
26 | | int LLVMFuzzerInitialize(int *argc, char ***argv) |
27 | 2 | { |
28 | 2 | GIT_UNUSED(argc); |
29 | 2 | GIT_UNUSED(argv); |
30 | | |
31 | 2 | if (git_libgit2_init() < 0) { |
32 | 0 | fprintf(stderr, "Failed to initialize libgit2\n"); |
33 | 0 | abort(); |
34 | 0 | } |
35 | 2 | if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS, 10000000) < 0) { |
36 | 0 | fprintf(stderr, "Failed to limit maximum pack object count\n"); |
37 | 0 | abort(); |
38 | 0 | } |
39 | | |
40 | 2 | if (git_odb_new(&odb) < 0) { |
41 | 0 | fprintf(stderr, "Failed to create the odb\n"); |
42 | 0 | abort(); |
43 | 0 | } |
44 | | |
45 | 2 | if (git_mempack_new(&mempack) < 0) { |
46 | 0 | fprintf(stderr, "Failed to create the mempack\n"); |
47 | 0 | abort(); |
48 | 0 | } |
49 | 2 | if (git_odb_add_backend(odb, mempack, 999) < 0) { |
50 | 0 | fprintf(stderr, "Failed to add the mempack\n"); |
51 | 0 | abort(); |
52 | 0 | } |
53 | 2 | return 0; |
54 | 2 | } |
55 | | |
56 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
57 | 2.99k | { |
58 | 2.99k | git_indexer_progress stats = {0, 0}; |
59 | 2.99k | git_indexer *indexer = NULL; |
60 | 2.99k | git_str path = GIT_STR_INIT; |
61 | 2.99k | git_oid oid; |
62 | 2.99k | bool append_hash = false; |
63 | 2.99k | int error; |
64 | | |
65 | 2.99k | if (size == 0) |
66 | 0 | return 0; |
67 | | |
68 | 2.99k | if (!odb || !mempack) { |
69 | 0 | fprintf(stderr, "Global state not initialized\n"); |
70 | 0 | abort(); |
71 | 0 | } |
72 | 2.99k | git_mempack_reset(mempack); |
73 | | |
74 | 2.99k | if (git_odb_write(&oid, odb, base_obj, base_obj_len, GIT_OBJECT_BLOB) < 0) { |
75 | 0 | fprintf(stderr, "Failed to add an object to the odb\n"); |
76 | 0 | abort(); |
77 | 0 | } |
78 | | |
79 | | #ifdef GIT_EXPERIMENTAL_SHA256 |
80 | | error = git_indexer_new(&indexer, ".", NULL); |
81 | | #else |
82 | 2.99k | error = git_indexer_new(&indexer, ".", 0, odb, NULL); |
83 | 2.99k | #endif |
84 | | |
85 | 2.99k | if (error < 0) { |
86 | 0 | fprintf(stderr, "Failed to create the indexer: %s\n", |
87 | 0 | git_error_last()->message); |
88 | 0 | abort(); |
89 | 0 | } |
90 | | |
91 | | /* |
92 | | * If the first byte in the stream has the high bit set, append the |
93 | | * SHA1 hash so that the packfile is somewhat valid. |
94 | | */ |
95 | 2.99k | append_hash = *data & 0x80; |
96 | 2.99k | ++data; |
97 | 2.99k | --size; |
98 | | |
99 | 2.99k | if (git_indexer_append(indexer, data, size, &stats) < 0) |
100 | 350 | goto cleanup; |
101 | 2.64k | if (append_hash) { |
102 | | #ifdef GIT_EXPERIMENTAL_SHA256 |
103 | | if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB, GIT_OID_SHA1) < 0) { |
104 | | fprintf(stderr, "Failed to compute the SHA1 hash\n"); |
105 | | abort(); |
106 | | } |
107 | | #else |
108 | 2.46k | if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB) < 0) { |
109 | 0 | fprintf(stderr, "Failed to compute the SHA1 hash\n"); |
110 | 0 | abort(); |
111 | 0 | } |
112 | 2.46k | #endif |
113 | | |
114 | 2.46k | if (git_indexer_append(indexer, &oid.id, GIT_OID_SHA1_SIZE, &stats) < 0) { |
115 | 955 | goto cleanup; |
116 | 955 | } |
117 | 2.46k | } |
118 | 1.68k | if (git_indexer_commit(indexer, &stats) < 0) |
119 | 1.68k | goto cleanup; |
120 | | |
121 | 1 | if (git_str_printf(&path, "pack-%s.idx", git_indexer_name(indexer)) < 0) |
122 | 0 | goto cleanup; |
123 | 1 | p_unlink(git_str_cstr(&path)); |
124 | | |
125 | 1 | git_str_clear(&path); |
126 | | |
127 | 1 | if (git_str_printf(&path, "pack-%s.pack", git_indexer_name(indexer)) < 0) |
128 | 0 | goto cleanup; |
129 | 1 | p_unlink(git_str_cstr(&path)); |
130 | | |
131 | 2.99k | cleanup: |
132 | 2.99k | git_mempack_reset(mempack); |
133 | 2.99k | git_indexer_free(indexer); |
134 | 2.99k | git_str_dispose(&path); |
135 | 2.99k | return 0; |
136 | 1 | } |