Using Libfuzzer on a library - linking the library to the fuzz target

I am working of using libfuzzer and asan to test out a third-party library.
As demonstrated in the tutorial, I wrote a fuzz target to fuzz a specific function in the library. The fuzz target is then linked to the library and compiles clean and I do see some tests generated by the fuzzer. However, I have some questions regarding the “right” way to go about doing this. I have doubts that the fuzzer taking coverage feedback from the fuzztarget and not the library functions (not sure though). Suppose the function in the library being tested is called - apifunc(). The libfuzzer log has a line which says - apifunc() resp=0x7ff38f83ac20 uninitialized, fixing it. I am not sure what this means. Also, I can see that the apifunc is called and it runs but it does not show up in the NEW_FUNC[x/xxx]: log lines in the libfuzzer output.

To enable fuzzing. First I build the library with the following libfuzzer flags.
-fsanitize=fuzzer-no-link,address -fsanitize-coverage=edge,indirect-calls

I also had to make a blacklist to avoid some buffer overflow and use after free error during this build.

After this, I link the fuzz target with the library and use the following libfuzzer options.
-fsanitize=fuzzer,address

I am looking for some guidance and feedback if this is the right way to go about fuzzing the library and the meaning of uninitialized fixing it line in the log.

Hi Shikhar,

You don’t need to build the library with -fsanitize-coverage=..., using -fsanitize=fuzzer-no-link,address should be sufficient. Without being able to inspect, it seems like you’re building the library/fuzz target in a sane manner (although you can actually build object files/shared libraries with -fsanitize=fuzzer, and the libFuzzer main won’t be linked, if this makes your build process easier).

I’ve run a quick grep and can’t find anything that would match “apifunc() resp=0x7ff38f83ac20 uninitialized, fixing it.” in libFuzzer (or compiler-rt). What version of compiler-rt/llvm/clang are you trying this with?

Have you tried visualising the coverage that the fuzz target is generating? It may give you an insight as to why your desired function under test isn’t being hit.

  • Mitch

Hi Mitch,

Thank you for the response.

  1. You don’t need to build the library with -fsanitize-coverage=..., using -fsanitize=fuzzer-no-link,address should be sufficient. - Acknowledged

  2. (although you can actually build object files/shared libraries with -fsanitize=fuzzer, and the libFuzzer main won’t be linked, if this makes your build process easier). - with just the fuzzer flag, it looks for the LLVMFuzzerTestOneInput.

  3. I’ve run a quick grep and can’t find anything that would match “apifunc() resp=0x7ff38f83ac20 uninitialized, fixing it.” in libFuzzer (or compiler-rt). What version of compiler-rt/llvm/clang are you trying this with? - This was an oversight on my part, it was a log dump from the library and somehow I mistook it be from libfuzzer. (I am using Clang 9 btw).

  4. Have you tried visualising the coverage that the fuzz target is generating? It may give you an insight as to why your desired function under test isn’t being hit. - Yes, I am using lcov for coverage and do see the relevant methods being exercised.

I am wondering if there is a reason I am not seeing the function in the NEW_FUNC[x/xxx]: log lines.
To iterate my steps -

First I build the library with fuzzer-no-link,address flags. I don’t compile the fuzz_target (the file containing the LLVMFuzzerTestOneInput function) with the library.
Then I build the fuzz target and link it with the library.

clang++ -g -O1 -fsanitize=fuzzer,address -Iinclude -Ibuild/include … fuzztarget.c -Lbuild/lib -llib1 -llib2
and then finally ./a.out -detect_leaks=0 corpus/

I appreciate your help with this.

I am wondering if there is a reason I am not seeing the function in the NEW_FUNC[x/xxx]: log lines.

I can think of a couple of reasons why this might be happening.

  1. The function __sanitizer_symbolize_pc is missing in your binary (you can check easily with nm <binary> | grep sanitizer_symbolize_pc)

  2. Symbolizer support is missing (either llvm-symbolizer is not in your path or in ASAN_OPTIONS=symoblizer_path, the internal symbolizer fails, or something else goes wrong).
    Do you see any outputs of NEW_FUNC[]? Is just the apifunc() line missing?

  1. __sanitizer_symbolize_pc is present
  2. Symbolizer support is missing (either llvm-symbolizer is not in your path or in ASAN_OPTIONS=symoblizer_path, the internal symbolizer fails, or something else goes wrong) - verified and re-ran this.

Do you see any outputs of NEW_FUNC[]? Is just the apifunc() line missing? - I do see other functions and its just the apifunc that is missing along with any subsequent functions called by apifunc.

Hmm, thanks for the info. I can’t think of a good reason why this is happening top of mind - is it possible you can minify to a testcase?