git: Combine multiple git command fuzzer to one (#8579)

List of git commands covered
        GIT_ADD
        GIT_BRANCH
        GIT_COMMIT
        GIT_CONFIG
        GIT_DIFF
        GIT_DIFF_FILES
        GIT_DIFF_INDEX
        GIT_DIFF_TREE
        GIT_LS_FILES
        GIT_LS_TREE
        GIT_MV
	GIT_RERERE
      	GIT_STATUS
        GIT_VERSION
This commit is contained in:
Arthur Chan 2022-09-23 19:26:32 +01:00 committed by GitHub
parent 551ad63712
commit 39a4c95af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 334 additions and 7 deletions

View File

@ -1,24 +1,25 @@
diff --git a/Makefile b/Makefile
index 924b864ae8..bd68d0f05a 100644
index 924b864ae8..3f0e004a5e 100644
--- a/Makefile
+++ b/Makefile
@@ -689,9 +689,12 @@ SCRIPTS = $(SCRIPT_SH_GEN) \
@@ -689,9 +689,13 @@ SCRIPTS = $(SCRIPT_SH_GEN) \
ETAGS_TARGET = TAGS
-FUZZ_OBJS += fuzz-commit-graph.o
-FUZZ_OBJS += fuzz-pack-headers.o
-FUZZ_OBJS += fuzz-pack-idx.o
+FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
+FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
+FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
+FUZZ_OBJS += oss-fuzz/fuzz-command.o
+FUZZ_OBJS += oss-fuzz/fuzz-cmd-status.o
+FUZZ_OBJS += oss-fuzz/fuzz-cmd-version.o
+FUZZ_OBJS += oss-fuzz/fuzz-cmd-diff.o
.PHONY: fuzz-objs
fuzz-objs: $(FUZZ_OBJS)
@@ -1012,6 +1015,7 @@ LIB_OBJS += oid-array.o
@@ -1012,6 +1016,7 @@ LIB_OBJS += oid-array.o
LIB_OBJS += oidmap.o
LIB_OBJS += oidset.o
LIB_OBJS += oidtree.o

View File

@ -22,6 +22,7 @@ make -j$(nproc) CC=$CC CXX=$CXX CFLAGS="$CFLAGS" \
FUZZERS="fuzz-pack-headers fuzz-pack-idx fuzz-commit-graph"
FUZZERS="$FUZZERS fuzz-cmd-status fuzz-cmd-version fuzz-cmd-diff"
FUZZERS="$FUZZERS fuzz-command"
# copy fuzzers
for fuzzer in $FUZZERS ; do

View File

@ -131,7 +131,8 @@ void generate_commit_in_branch(char *data, int size, char *branch_name)
strbuf_addf(&push_cmd, "git push origin %s", branch_name);
if (system("git add TEMP-*-TEMP") ||
system("git commit -m\"New Commit\""))
system("git commit -m\"New Commit\"") ||
system(push_cmd.buf))
{
// Just skip the commit if fails
strbuf_release(&push_cmd);

View File

@ -15,6 +15,23 @@ limitations under the License.
#define HASH_SIZE 20
#define HASH_HEX_SIZE 40
#define INT_SIZE 4
#define GIT_COMMAND_COUNT 12
typedef enum git_command {
GIT_STATUS = 0,
GIT_ADD_COMMIT = 1,
GIT_VERSION = 2,
GIT_CONFIG_RERERE = 3,
GIT_DIFF = 4,
GIT_DIFF_FILES = 5,
GIT_DIFF_TREE = 6,
GIT_DIFF_INDEX = 7,
GIT_BRANCH = 8,
GIT_MV = 9,
GIT_LS_FILES = 10,
GIT_LS_TREE = 11
} git_command_t;
int randomize_git_file(char *dir, char *name, char *data, int size);
void randomize_git_files(char *dir, char *name_set[],

307
projects/git/fuzz-command.c Normal file
View File

@ -0,0 +1,307 @@
/* Copyright 2022 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "builtin.h"
#include "repository.h"
#include "fuzz-cmd-base.h"
int cmd_add(int argc, const char **argv, const char *prefix);
int cmd_branch(int argc, const char **argv, const char *prefix);
int cmd_commit(int argc, const char **argv, const char *prefix);
int cmd_config(int argc, const char **argv, const char *prefix);
int cmd_diff(int argc, const char **argv, const char *prefix);
int cmd_diff_files(int argc, const char **argv, const char *prefix);
int cmd_diff_index(int argc, const char **argv, const char *prefix);
int cmd_diff_tree(int argc, const char **argv, const char *prefix);
int cmd_ls_files(int argc, const char **argv, const char *prefix);
int cmd_ls_tree(int argc, const char **argv, const char *prefix);
int cmd_mv(int argc, const char **argv, const char *prefix);
int cmd_rerere(int argc, const char **argv, const char *prefix);
int cmd_status(int argc, const char **argv, const char *prefix);
int cmd_version(int argc, const char **argv, const char *prefix);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
int i;
int argc;
int no_of_commit;
int max_commit_count;
char *argv[6];
char *data_chunk;
char *basedir = "./.git";
git_command_t choice;
struct strbuf name = STRBUF_INIT;
/*
* Initialize the repository
*/
initialize_the_repository();
/*
* End this round of fuzzing if the data is not large enough
*/
if (size <= (HASH_HEX_SIZE * 4 + HASH_SIZE + INT_SIZE * 2))
{
repo_clear(the_repository);
return 0;
}
reset_git_folder();
/*
* Generate random commit
*/
max_commit_count = get_max_commit_count(size, 0,
HASH_HEX_SIZE * 2 + HASH_SIZE + INT_SIZE * 2);
no_of_commit = (*((int *)data)) % max_commit_count + 1;
data += 4;
size -= 4;
choice = (*((int *)data)) % GIT_COMMAND_COUNT;
data += 4;
size -= 4;
data_chunk = xmallocz_gently(HASH_HEX_SIZE);
if (!data_chunk)
{
repo_clear(the_repository);
return 0;
}
for (i = 0; i < no_of_commit; i++)
{
memcpy(data_chunk, data, HASH_HEX_SIZE);
generate_commit(data_chunk, HASH_SIZE);
data += HASH_HEX_SIZE;
size -= HASH_HEX_SIZE;
}
free(data_chunk);
/*
* Final preparing of the repository settings
*/
repo_clear(the_repository);
if (repo_init(the_repository, basedir, "."))
{
return 0;
}
/*
* Alter content of TEMP_1 and TEMP_2
*/
data_chunk = xmallocz_gently(HASH_SIZE);
memcpy(data_chunk, data, HASH_SIZE);
randomize_git_file(".", "TEMP_1", data_chunk, HASH_SIZE);
memcpy(data_chunk, data + HASH_SIZE, HASH_SIZE);
randomize_git_file(".", "TEMP_2", data_chunk, HASH_SIZE);
data += (HASH_SIZE * 2);
size -= (HASH_SIZE * 2);
free(data_chunk);
/*
* Generate random name for different usage
*/
data_chunk = xmallocz_gently(HASH_SIZE);
memcpy(data_chunk, data, HASH_SIZE);
strbuf_addf(&name, "name-%s-name", hash_to_hex((unsigned char *)data_chunk));
data += HASH_SIZE;
size -= HASH_SIZE;
free(data_chunk);
switch(choice) {
case GIT_STATUS: default:
argv[0] = "status";
argv[1] = "-v";
argv[2] = NULL;
cmd_status(2, (const char **)argv, (const char *)"");
break;
case GIT_ADD_COMMIT:
argv[0] = "add";
argv[1] = "-u";
argv[2] = NULL;
cmd_add(2, (const char **)argv, (const char *)"");
argv[0] = "commit";
argv[1] = "-m";
argv[2] = "\"New Commit\"";
argv[3] = NULL;
cmd_commit(3, (const char **)argv, (const char *)"");
break;
case GIT_VERSION:
argv[0] = "version";
argv[1] = NULL;
cmd_version(1, (const char **)argv, (const char *)"");
argv[1] = "--build-options";
argv[2] = NULL;
cmd_version(2, (const char **)argv, (const char *)"");
break;
case GIT_CONFIG_RERERE:
argv[0] = "config";
argv[1] = "--global";
argv[2] = "rerere.enabled";
argv[3] = "true";
argv[4] = NULL;
cmd_config(4, (const char **)argv, (const char *)"");
argv[0] = "rerere";
argv[1] = NULL;
cmd_rerere(1, (const char **)argv, (const char *)"");
argv[1] = "clear";
argv[2] = NULL;
cmd_rerere(2, (const char **)argv, (const char *)"");
argv[1] = "diff";
cmd_rerere(2, (const char **)argv, (const char *)"");
argv[1] = "remaining";
cmd_rerere(2, (const char **)argv, (const char *)"");
argv[1] = "status";
cmd_rerere(2, (const char **)argv, (const char *)"");
argv[1] = "gc";
cmd_rerere(2, (const char **)argv, (const char *)"");
break;
case GIT_DIFF:
argv[0] = "diff";
argv[1] = NULL;
cmd_diff(1, (const char **)argv, (const char *)"");
argv[1] = "TEMP_1";
argv[2] = NULL;
cmd_diff(2, (const char **)argv, (const char *)"");
argv[2] = "TEMP_2";
argv[3] = NULL;
cmd_diff(3, (const char **)argv, (const char *)"");
break;
case GIT_DIFF_FILES:
argv[0] = "diff-files";
argv[1] = NULL;
cmd_diff_files(1, (const char **)argv, (const char *)"");
argv[1] = "TEMP_1";
argv[2] = NULL;
cmd_diff_files(2, (const char **)argv, (const char *)"");
argv[2] = "TEMP_2";
argv[3] = NULL;
cmd_diff_files(3, (const char **)argv, (const char *)"");
break;
case GIT_DIFF_TREE:
argv[0] = "diff-tree";
argv[1] = "master";
argv[2] = "--";
argv[3] = NULL;
cmd_diff_tree(3, (const char **)argv, (const char *)"");
break;
case GIT_DIFF_INDEX:
argv[0] = "diff-index";
argv[1] = "master";
argv[2] = "--";
argv[3] = NULL;
cmd_diff_index(3, (const char **)argv, (const char *)"");
argv[2] = "--";
argv[3] = "TEMP_1";
argv[4] = NULL;
cmd_diff_index(4, (const char **)argv, (const char *)"");
argv[2] = "--";
argv[3] = "TEMP_1";
argv[4] = "TEMP_2";
argv[5] = NULL;
cmd_diff_index(5, (const char **)argv, (const char *)"");
break;
case GIT_BRANCH:
argv[0] = "branch";
argv[1] = name.buf;
argv[2] = NULL;
cmd_branch(2, (const char **)argv, (const char *)"");
argv[1] = "-d";
argv[2] = name.buf;
argv[3] = NULL;
cmd_branch(3, (const char **)argv, (const char *)"");
break;
case GIT_MV:
argv[0] = "mv";
argv[1] = "-k";
argv[2] = "TEMP_1";
argv[3] = name.buf;
argv[4] = NULL;
cmd_mv(4, (const char **)argv, (const char *)"");
argv[1] = "-k";
argv[2] = name.buf;
argv[3] = "TEMP_1";
argv[4] = NULL;
cmd_mv(4, (const char **)argv, (const char *)"");
break;
case GIT_LS_FILES:
argv[0] = "ls-files";
argv[1] = NULL;
cmd_ls_files(1, (const char **)argv, (const char *)"");
argv[1] = "TEMP";
argv[2] = NULL;
cmd_ls_files(2, (const char **)argv, (const char *)"");
argv[1] = "-m";
argv[2] = NULL;
cmd_ls_files(2, (const char **)argv, (const char *)"");
argv[1] = name.buf;
argv[2] = NULL;
cmd_ls_files(2, (const char **)argv, (const char *)"");
break;
case GIT_LS_TREE:
argv[0] = "ls-tree";
argv[1] = "master";
argv[2] = NULL;
cmd_ls_tree(2, (const char **)argv, (const char *)"");
break;
}
strbuf_release(&name);
repo_clear(the_repository);
return 0;
}