-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Add a fuzzer for config files #4752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for another contribution! I guess having a config fuzzer makes a lot of sense, and it's nice to see our collection of fuzzers being extended :) It's not really all that critical for local configuration, but the parser is also being used to parse the .gitmodules file, which may be remote input.
fuzzers/config_file_fuzzer.c
Outdated
#include <unistd.h> | ||
#include <limits.h> | ||
|
||
int foreach_cb(const git_config_entry *entry, void *payload) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our style is to have the opening brace on its own line
@@ -0,0 +1,41 @@ | |||
#include <git2.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The license header is missing
fuzzers/config_file_fuzzer.c
Outdated
|
||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | ||
{ | ||
static int fd = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you've indented all lines by four spaces, but our style dictates a tab instead (where a tab equals 8 spaces).
fuzzers/config_file_fuzzer.c
Outdated
static int fd = -1; | ||
static char path[] = "/tmp/git.XXXXXX"; | ||
if (fd < 0) { | ||
git_libgit2_init(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should move the initialization of this into LLVMFuzzerInitialize
, which gets called exactly once
fuzzers/config_file_fuzzer.c
Outdated
} | ||
|
||
git_config *cfg; | ||
int err = git_config_open_ondisk(&cfg, path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our project uses the C89 standard, where declarations after statements aren't allowed. You'll have to move all variable declarations to the head of this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not your fault, but it really sucks that libgit2 isn't yet able to open configs from memory. I wanted to refactor that part for a long time already to make it possible, but until now I didn't yet have enough time to do this. I bet that writing a file for each iteration will slow the fuzzer down by quite a bit.
fuzzers/config_file_fuzzer.c
Outdated
#include <limits.h> | ||
|
||
int foreach_cb(const git_config_entry *entry, void *payload) { | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, another thing. You'll have to mark these two function parameters as unused, otherwise the compiler will issue a warning. We usually do this by using GIT__UNUSED(x)
, but we don't have it available here. So you could probably just declare a macro #define UNUSED(x) (void)(x)
after the includes and then use it here.
fuzzers/config_file_fuzzer.c
Outdated
} | ||
if ((size_t)write(fd, data, size) != size) { | ||
abort(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thing. It could very well be that the fuzzer throws huge files at us, in which case it is likely that we abort here due to the write being interrupted. So we'd need a full-blown write loop, like:
size_t total = 0;
while (total < size) {
ssize_t written = write(fd, data, size);
if (written < 0 && errno != EINTR)
abort();
if (written < 0)
continue;
total += written;
}
Thanks, looks good to me now. I've kicked Travis once again as it had some spurious errors. We should probably refactor this code to use our in-memory config backend as soon as #4767 lands. While some code paths are obviously different from the file-based config backend, the parsing logic is actually completely the same. The main advantage would probably be much improved fuzzer performance, as we wouldn't need to write the config file on each pass. |
Awesome, I've subscribed to that PR and once it lands I'll send in a refactor. I'll definitely be glad to ditch the tempfile. |
No description provided.