Revision 97573c6e6f803a234be18e37648c3399537808fd authored by Volodymyr Kysenko on 27 October 2023, 21:21:26 UTC, committed by GitHub on 27 October 2023, 21:21:26 UTC
* Minimal hoist_storage plumbing

* HoistedStorage placeholder IR node

* Basic hoist_storage test

* Fully plumb through the HoistedStorage node

* IRPrinter for HoistedStorage

* Insert hoisted storage at the correct loop level

* Progress

* Formatted

* Move out common code for creating Allocate node

* Format

* Emit Allocate at the HoistedStorage site

* Collect all dependant vars

* Basic test working

* Progress

* Substitute lets into allocation extents instead of lifting stuff

* Infer bounds for the extends dependant on loop variables

* Update tests

* Remove old code

* Remove old code

* Better tests

* More tests

* Validate schedules with hoist_storage

* Error test

* Fix stupid mistake

* More tests

* Remove debug prints

* Better errors

* Add missing handler for inlined functions

* Format

* Comments

* Format

* Add some missing visit handlers

* New line

* Fix comment

* Luckily we only have two build systems

* Adds hoist_storage_root

* Comment for IR node

* Serialization support for HoistedStorage

* Handle hoist_storage fo tuples

* Handle multiple realize nodes

* Move assert up

* Better error message

* Better loop bounds

* Format

* Updated error message

* Happy clang-tidy happy me

* An error message when compute is inlined, but store is not inlined

* Only mutate lets which are needed

* Update apps to use hoist_storage

Some very minor performance gains, but mostly in the noise.

Also switched the apps makefiles to emit stmt html by default instead of
stmt, to take advantage of the new and improved stmt html.

* Switch to stack of hoisted storages

* Limit scope of lets for expansion

* Break early

* Skip substitute_in_all_lets

* Re-use expanded min/extents

* WebAssembly JIT does not support custom allocators

* Change debug level to get more info about segfault

* More debugging prints

* Let's try aligned malloc

* Revert "Change debug level to get more info about segfault"

This reverts commit a5a689be8c6ad351674f3ced3bbf542335f91d75.

* Revert "More debugging prints"

This reverts commit bb6b8c1313cbdb9f355df20fd203ee02d485042e.

---------

Co-authored-by: Andrew Adams <andrew.b.adams@gmail.com>
1 parent ed357c2
Raw File
README_fuzz_testing.md
# Fuzz testing
Halide has a set of fuzz-testing harnesses that can be used to find those
tricky to find, edge cases and bugs that would otherwise not be caught
by a regular unit-testing suite. At the moment these fuzz-tests are housed
in the `test/fuzz` directory. The fuzz testing suite use the common,
[libfuzzer](https://www.llvm.org/docs/LibFuzzer.html) interface for fuzz-tests.

## Building fuzz tests
Fuzz testing requires specific instrumentation across the entire build;
to do this we make use of a fuzzing-specific-toolchain/preset. e.g.

```
cmake -B build --preset linux-x64-fuzzer -DLLVM_ROOT=/path/to/llvminstall
cmake --build ./build -j$(nproc)
```

Note that the LLVM install that you use must be built with
`-D LLVM_ENABLE_RUNTIMES="compiler-rt"` set if you want to build the fuzzer
tests (failing to do so will fail at configure time); not all prebuilt LLVM
installs include this, so you may need to build LLVM from source to run the
fuzz tests locally.

## Using the fuzz-harnesses
Fuzz-testing harnesses are a little different to a more traditional unit-test
and don't have a definitive end of test. In other words, a fuzz test will
run:
- for an infinite amount of time (the default),
- for a user specified maximum amount of time,
- until the fuzzer finds a bug and crashes,
- you manually kill the process e.g. (ctrl-C).

Once you have built the fuzz testing suite using the commands listed above you
can list the fuzz testing harnesses using the command:

```
ls ./build/test/fuzz/fuzz_*
```

To run a fuzzer simply run the fuzz-testing harness with no arguments. e.g.

`./build/test/fuzz/fuzz_simplify`

By default this will run the fuzz test on a single core and discard whatever.
temporary corpus is created.

To reuse a given corpus (recommended) create a new directory to store the
corpus generated by your fuzz testing harness and pass that directory into
your fuzzer e.g.

```
mkdir fuzz_simplify_corpus -p
./build/test/fuzz/fuzz_simplify fuzz_simplify_corpus
```

This will save the state of the fuzzer between runs, this way any progress
that your fuzzer makes improving code-coverage will remain persistent on
your disk.

Up until this point the fuzzer has only been running on a single core. To
speed things up a little, let's run the fuzzer in parallel across all
available cores on our machine.

```
./build/test/fuzz/fuzz_simplify fuzz_simplify_corpus -fork=$(nproc)
```

## Reproducing crashes
An important part of fuzz testing is reproducing the crashing input. To
handle this, a libfuzzer-based fuzz harness will create a crash file
whenever the fuzzer exits unexpectedly. This will look something like:

`crash-<some_random_hash>`

To reproduce a crash we simply rerun our fuzz harness with our crash
file as the first argument.

`./build/test/fuzz/fuzz_simplify crash-<some_random_hash>`

So long as your fuzz harness and library are deterministic this should
reproduce the original crash.

## Adding new fuzz tests
A bare-bones fuzzer will look something like the following:
```cpp
#include <stdint.h>
#include <stddef.h>
#include <my_library.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  // Randomly throw data at our function and hope it doesn't crash.
  foo(data, size);
  return 0;
}
```

This assumes that our function foo takes in a buffer and the size of said
buffer. But in many cases we would like to make use of more structured data.
e.g. a string or a vector of integers etc. Thankfully libfuzzer provides
a handy helper to convert a raw buffer into common structured data types,
the [FuzzedDataProvider class](https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/fuzzer/FuzzedDataProvider.h).
For examples on how to use this class see `test/fuzz/simplify.cpp`.

## Other useful materials
- [The official libfuzzer docs](https://www.llvm.org/docs/LibFuzzer.html)
- [The libfuzzer tutorial](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md)
back to top