Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

lhchavez
Copy link
Contributor

@lhchavez lhchavez commented Dec 7, 2017

This change adds support for building a fuzz target for exercising the
packfile parser, as well as documentation. It also runs the fuzzers in
Travis to avoid regressions.

@lhchavez
Copy link
Contributor Author

lhchavez commented Dec 7, 2017

PTAL!

Note that this depends on merging the following three changes, to avoid crashing wildly:

The OSS-Fuzz support will come next. Stay tuned!

Copy link
Member

@pks-t pks-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this. I have no idea how @carlosmn or @ethomson think about this, but eventually I'd like to have a set of fuzzers included in our code base. It would be even nicer if those fuzzers could be submitted to the Google OSS-fuzz infrastructure such that we have continuous fuzzing of some of our code. I'd deem this especially important for all network-facing code.

So thanks a lot for working on this, this crosses off one item from my todo list!

CMakeLists.txt Outdated
@@ -328,6 +329,10 @@ IF (BUILD_EXAMPLES)
ADD_SUBDIRECTORY(examples)
ENDIF ()

IF (BUILD_FUZZERS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though that's not yet documented, we now settled on IF( style, so without spaces in between. We're not being consistent about it right now, but going forward we try to be.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fuzz/README.md Outdated

1. Create a build directory beneath the libgit2 source directory, and change into it: `mkdir build && cd build`
2. Choose which sanitizers to add. For instance, `address,leak`. Note that some sanitizers are mutually incompatible, so you might need several rounds to achieve more coverage.
3. Create the cmake build environment and configure the build with the sanitizers chosen: `CC=/usr/bin/clang-6.0 CFLAGS="-fsanitize=fuzzer-no-link,address,leak -g" cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=fuzzer,address,leak" ..`. Note that `CFLAGS` has `fuzzer-no-link` followed by the chosen sanitizers and `-DCMAKE_EXE_LINKER_FLAGS` has `fuzzer` followed by the chosen sanitizers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of instructing the user to set CC and CFLAGS for himself, you should do it for him in case the user has enabled fuzzing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to automate it as much as possible, but I had trouble getting rid of the CC and linker flags, because OSS-Fuzz require the build system to not assume these things.

I could add an USE_OSS_FUZZ flag to turn off all these things, but I'm not an expert in CMake and couldn't get it to correctly detect a version of clang that was recent enough (especially given that you need to manually install it, and the binary name might change between distros).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a lot better already. Given the clear build instructions I'm fine with this, thanks!

fuzz/README.md Outdated

1. All the prerequisites for [building libgit2](https://github.com/libgit2/libgit2).
2. A recent version of clang. 6.0 is preferred. [pre-build Debian/Ubuntu packages](https://github.com/libgit2/libgit2)
3. (Optional) Symlink the `llvm-symbolizer` binary to get nice stack traces: `sudo ln -s llvm-symbolizer-6.0 /usr/bin/llvm-symbolizer`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't instruct the user to modify his base system, which should only be touched by the package manager.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

fuzz/README.md Outdated

**Run the fuzz targets**

1. `ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzz/fuzz_packfile_raw fuzz/corpora/fuzz_packfile_raw/`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's that "corpora" prefix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, good to know

#include <stdint.h>
#include <stdio.h>

#include <openssl/sha.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using OpenSSL for SHA1, you can just link to libgit2internal, add the include path to the source directory and use for example git_hash_buf to do the hashing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done

static git_odb *odb = NULL;

int LLVMFuzzerInitialize(__attribute__((unused)) int *argc,
__attribute__((unused)) char ***argv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the GIT_UNUSED macro instead of __attribute((unused)).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fprintf(stderr, "Failed to initialize libgit2\n");
abort();
}
if (git_repository_init(&repo, REPOSITORY_PATH, true) < 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of having a repository being created in the current directory, you should instead create a temporary path by using e.g. mkdtemp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about I use git_mempack_new instead? No files except the pack_git_... temporaries which will only be leaked if the process crashes. I also added some code to remove the *.pack and *.idx files that are committed.

The problem with the fuzzers is that they are not designed to clean up the process state when they go down. Even using atexit(3) wasn't enough to clean the mess left.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's even better!

}

git_indexer *indexer;
git_transfer_progress stats = {0, 0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using C90 only, so please no variable declarations after statements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (switching my brain off of C++ is hard)

abort();
}
if (git_indexer_append(indexer, hash, sizeof(hash), &stats) <
0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This linebreak is a bit funny. No need to be too strict with breaking lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit my kernel-style is weak, so I rely on clang-format. Fixed.


cleanup:
git_indexer_free(indexer);
return 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the return value being interpreted by LLVM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required to be zero (for now): http://llvm.org/docs/LibFuzzer.html#fuzz-target

@lhchavez
Copy link
Contributor Author

lhchavez commented Dec 9, 2017

The trigger is ready to be pulled: https://github.com/lhchavez/oss-fuzz/tree/libgit2/projects/libgit2

LMK who needs to be the owner/maintainer for the project in OSS-Fuzz.

@lhchavez
Copy link
Contributor Author

All prerequisites have been merged, so this change is ready to land.

@pks-t
Copy link
Member

pks-t commented Jan 3, 2018

I think from our side I'm the person the most interested in fuzzing, so that might be a natural choice. Any opinions on this @ethomson or @carlosmn? I'll also do a review tomorrow

Copy link
Member

@pks-t pks-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see anything that immediately catched my eyes, only some few things to clear up for myself. I'd welcome it though if you could rebase this PR to get rid of the merge and also try to squash commits together where it makes sense (not in the sense of having one giant commit, but in the sense of getting rid of fixups to just-introduced commits).

Before merging this I'd like to get the opinions of @ethomson and @carlosmn.

Thanks a lot for your work!

fprintf(stderr, "Failed to initialize libgit2\n");
abort();
}
if (git_repository_init(&repo, REPOSITORY_PATH, true) < 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's even better!

* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should definitly be squashed into the commit which created that file ;)

fuzz/README.md Outdated

1. Create a build directory beneath the libgit2 source directory, and change into it: `mkdir build && cd build`
2. Choose which sanitizers to add. For instance, `address,leak`. Note that some sanitizers are mutually incompatible, so you might need several rounds to achieve more coverage.
3. Create the cmake build environment and configure the build with the sanitizers chosen: `CC=/usr/bin/clang-6.0 CFLAGS="-fsanitize=fuzzer-no-link,address,leak -g" cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_FUZZERS=ON -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=fuzzer,address,leak" ..`. Note that `CFLAGS` has `fuzzer-no-link` followed by the chosen sanitizers and `-DCMAKE_EXE_LINKER_FLAGS` has `fuzzer` followed by the chosen sanitizers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a lot better already. Given the clear build instructions I'm fine with this, thanks!

CMakeLists.txt Outdated
# The actual sanitizer link target will be added when linking the fuzz
# targets.
SET(CMAKE_C_FLAGS "-fsanitize=fuzzer-no-link ${CMAKE_C_FLAGS}")
ENDIF ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

fuzz/README.md Outdated

In order to get full coverage, though, you might want to also enable one of the
sanitizers. You might need a recent version of clang to get full support.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitly nice to have. I'm currently stuck on a system without working fuzzers due to problems with musl libc, so I always have to use a VM. At least I can get some feedback with the standalone mode.

goto exit;
}
git_vector_foreach(&corpus_files, i, corpus_filename) {
if (run_one_file(corpus_filename) < 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can only happen in case the corpus file could not be read, right? As in the case of a corpus error, we alwasy abort().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, abort() or segfault.

fuzz_target_name=$(basename "${fuzz_target}")
# TODO: Make this exit on failures once all fixes are in place.
"${fuzz_target}" "../fuzz/corpora/${fuzz_target_name}"
done
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, that's a good thing to have. I guess making it work on AppVeyor wouldn't make any sense at all, would it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe, i can give it a try later :)

@lhchavez
Copy link
Contributor Author

lhchavez commented Jan 4, 2018

Squashed and ready to go!

@pks-t
Copy link
Member

pks-t commented Feb 9, 2018

I'll tackle this PR after the next release, which should hopefully be done soon

This change adds support for building a fuzz target for exercising the
packfile parser, as well as documentation. It also runs the fuzzers in
Travis to avoid regressions.
@lhchavez
Copy link
Contributor Author

lhchavez commented Jul 7, 2018

any progress on the release? i've rebased the squashed change to HEAD.

@pks-t
Copy link
Member

pks-t commented Jul 13, 2018

Sorry @lhchavez for not getting back to this earlier x( I've planned to tackle this issue next week anyway, as we now also have another proposed fuzzer from @nelhage. As both proposed fuzzers test different things (packfiles vs smart protocol), they luckily can both be merged into our code base.

This PR has been lurking around for too long, though. I always wanted to get this merged, but somehow I never found the time to finally follow through.

@lhchavez
Copy link
Contributor Author

all right, let me know if there's a preferred way to split this change to make reviews easier.

@pks-t
Copy link
Member

pks-t commented Jul 19, 2018

Would you be okay with me adopting this PR? I'd obviously retain your commits and start working from them, but adopting the PR would allow me to push this faster and also merge with the other fuzzing target we have by now. Feel free to say "no" in case you want to push this through, though, I wouldn't mind.

@lhchavez
Copy link
Contributor Author

go for it! and thanks for your help.

@pks-t pks-t mentioned this pull request Jul 19, 2018
@ethomson
Copy link
Member

@pks-t You've included all these changes in #4728, correct? Since that's been merged, this PR is now obsolete and can be closed, is that correct?

@pks-t
Copy link
Member

pks-t commented Nov 2, 2018

Correct, fuzzing is implemented now and finding lots of errors, so this can be closed Thanks again, @lhchavez, it has proven to be highly valuable for us!

@pks-t pks-t closed this Nov 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants