• Show log

    Commit

  • Hash : c6c6d8af
    Author : Nick Wellnhofer
    Date : 2024-12-11T16:24:23

    fuzz: Mutate fuzz data chunks separately
    
    Implement a custom mutator that takes a list of fixed-size chunks which
    are mutated with a given probability. This makes sure that values like
    parser options or failure position are mutated regularly even as the
    fuzz data grows large. Values can also be adjusted temporarily to make
    the fuzzer focus on failure injection, for example.
    
    Thanks to David Kilzer for the idea.
    

  • README.md

  • libFuzzer instructions for libxml2

    Set compiler and options. Make sure to enable at least basic optimizations to avoid excessive stack usage. Also enable some debug output to get meaningful stack traces.

    export CC=clang
    export CFLAGS=" \
        -O1 -gline-tables-only \
        -fsanitize=fuzzer-no-link,address,undefined \
        -fno-sanitize-recover=all \
        -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"

    Other options that can improve stack traces:

    -fno-omit-frame-pointer
    -fno-inline
    -fno-optimize-sibling-calls (disables tail call optimization)

    Build libxml2 with instrumentation:

    ./configure --without-python
    make

    Run fuzzers:

    make -C fuzz fuzz-xml

    The environment variable XML_FUZZ_OPTIONS can be used to pass additional flags to the fuzzer.

    Malloc failure injection

    Most fuzzers inject malloc failures to cover code paths handling these errors. This can lead to surprises when debugging crashes. You can set the macro XML_FUZZ_MALLOC_ABORT in fuzz/fuzz.c to make the fuzz target abort at the malloc invocation which would fail. This tells you if and where a malloc failure was injected.

    Some fuzzers also test whether malloc failures are reported. To debug failures which aren’t reported, it’s helpful to enable XML_FUZZ_MALLOC_ABORT to see which allocation failed. Debugging failures which are erroneously reported can be harder. If the report goes through xmlRaiseMemoryError, you can abort() there to get a stack trace.