google/fuzzing

fuzz_me.cc no error with -O1

pobv opened this issue · 1 comments

pobv commented

Compiling the simple example from the tutorial

bool fuzz_me(const uint8_t* data, size_t len) {
  return len >= 3 && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z' && data[3] == 'Z';
}

as suggested works fine. However, when compiling with -O1 (as is suggested elsewhere in the guide),

clang++ -g -std=c++14 -Wall -pedantic -O1 fuzz.cpp -o fuzz.exe -fsanitize=address,fuzzer

there is no error triggered. godbolting with -O1 gives

fuzz_me(unsigned char const*, unsigned long):  
        cmp     rsi, 3
        jb      .LBB0_5
        cmp     byte ptr [rdi], 70
        jne     .LBB0_5
        cmp     byte ptr [rdi + 1], 85
        jne     .LBB0_5
        cmp     byte ptr [rdi + 2], 90
        jne     .LBB0_5
        cmp     byte ptr [rdi + 3], 90
        sete    al
        ret
.LBB0_5:
        xor     eax, eax
        ret

which to my uninitiated eye looks fine, as I see the rdi+3.
Effect on clang 10.0.0-4ubuntu1, ubuntu 20.04 as well as clang 7.0.1-8, debian 10.
Did I do something wrong? Do we need to try always with several optimization levels?

kcc commented

This test is too simple to work with -O1.
If you look at the code for LLVMFuzzerTestOneInput in godbolt (or objdump), you will see

0000000000561eb0 <LLVMFuzzerTestOneInput>:
  561eb0:       80 05 af b0 05 00 01    addb   $0x1,0x5b0af(%rip)        # 5bcf66 <__TMC_END__+0x6>
  561eb7:       31 c0                   xor    %eax,%eax
  561eb9:       c3                      retq   

i.e. FuzzMe was inlined into LLVMFuzzerTestOneInput and disappeared.

Do we need to try always with several optimization levels?

We try to make -O1/-O2 generally usable for fuzzing, although I have seen some cases where -O0 may give better results, despite being much slower.