Closed smoelius closed 4 years ago
I would prefer not to do this. It looks like this introduces quite a bit of new complexity in Lazy::get.
Can you suggest any other ways to get better fuzzing in programs with a lazy_static?
Can you suggest any other ways to get better fuzzing in programs with a lazy_static?
You can abandon AFL persistent mode, of course. But then you give up on the advantages that it provides (e.g., avoiding fork).
Another alternative may be to maintain a "resettable-lazy-static" fork and keep it in sync with the main repository, so that a person can patch-it-in when fuzzing. lazy-static
appears to be pretty stable, so this may be a workable solution.
I will take the issue up with the afl.rs maintainers and see what they say.
I understand your position. Thanks a lot for your time.
This PR adds a function
reset
that puts alllazy_static
variables back in their original, uninitialized states. Such a function facilitates fuzzing with AFL in persistent mode.In persistent mode, AFL does not launch a new process for each fuzzing run. Rather, the process loops, repeatedly executing the function under test with new fuzzing inputs. This can cause problems for programs that use
lazy_static
variables in at least two ways:AFL can give incorrectly low stability reports. Roughly speaking, stability is the fraction of instructions that are executed the same number of times across different runs of the program with the same input. Because a
lazy_static
variable's initializer is executed only on the variable's first use, the initializer's instructions are counted against stability, causing it to be low.AFL can fail to report timeouts. Suppose that a fuzzing input X causes a program to use a large number of
lazy_static
variables, each of which has an expensive initializer. If each of those variables was used for an earlier fuzzing input, then those variables' intializers will not be run on input X, causing the program to take less time than it otherwise would on input X.Returning each
lazy_static
variable to its uninitialized state at the end of each fuzzing iteration addresses these problems. This causes eachlazy_static
variable's initializer to be executed for each fuzzing input that uses that variable. Thus, the initializer's instructions are not counted against stability. On the other hand, the time taken to execute the initializer is counted against each input that uses that variable.Conceptually, this PR does two things:
It collects all initialized
lazy_static
variables in a linked list.It wraps each
lazy_static
variable'sOnce
instance in aCell
.The function
reset
walks the linked list in order to set the initializedlazy_static
variables back to their uninitialized states, assigningONCE_INIT
to eachCell<Once>
in the process.A program demonstrating the problems described above can be found here. The program further demonstrates that adding a call to
reset
at the end of each fuzzing iteration addresses these problems.