I'm experimenting with libFuzzer of the LLVM project trying to generate inputs for an audio signal processing library.
For the sake of simplicity I started with a constant-zero 64kb PCM as initial corpus, using -max_len=65536. Memory consumption per library call is about 200kB, which should be freed as expected.
What I'm wondering about is the memory consumption shown as rss in the fuzzer log:
#1024 pulse cov: 26153 ft: 40811 corp: 783/33Mb exec/s: 7 rss: 541Mb
#2048 pulse cov: 26154 ft: 40811 corp: 783/33Mb exec/s: 8 rss: 573Mb
#4096 pulse cov: 26154 ft: 40811 corp: 783/33Mb exec/s: 8 rss: 574Mb
#4895 NEW cov: 26156 ft: 40815 corp: 784/33Mb exec/s: 8 rss: 576Mb L: 26935 MS: 1 InsertRepeatedBytes-
#8192 pulse cov: 26157 ft: 40815 corp: 784/33Mb exec/s: 8 rss: 578Mb
#11875 NEW cov: 26157 ft: 40816 corp: 785/33Mb exec/s: 8 rss: 579Mb L: 59394 MS: 1 InsertByte-
#12862 NEW cov: 26157 ft: 40817 corp: 786/33Mb exec/s: 8 rss: 579Mb L: 51404 MS: 3 EraseBytes-EraseBytes-CopyPart-
#15357 NEW cov: 26157 ft: 40818 corp: 787/33Mb exec/s: 8 rss: 579Mb L: 64536 MS: 3 CopyPart-ChangeBit-InsertRepeatedBytes-
#16384 pulse cov: 26157 ft: 40818 corp: 787/33Mb exec/s: 8 rss: 579Mb
#23171 NEW cov: 26157 ft: 40820 corp: 788/33Mb exec/s: 8 rss: 579Mb L: 49412 MS: 2 InsertRepeatedBytes-CMP- DE: "\x00\x00\x00\x00\x00\x00\x00\x00"-
#25426 NEW cov: 26158 ft: 40825 corp: 789/33Mb exec/s: 8 rss: 579Mb L: 64443 MS: 2 CMP-CMP- DE: "\x00\x00\x00\x00"-"\xff\xff"-
Why is the rss metric increasing steadily?
Note that the increase seems to converge (similar to the cov and ft quantities), so memory isn't leaked per fuzzer target invocation.
Is it a setup problem or a leak, which causes rss memory to increase?
If not, what is the rationale of having an -rss_limit_mb option available to the fuzzer, if the memory consumption isn't set back after each fuzzer target invocation?
Some reasons for memory increase are:
ASan's "quarantine": ASan keeps freed memory in quarantine to detect use-after-free errors. When fuzzing without a quarantine size limit, memory growth is unbounded. Try to change the ASan should limit the quarantine size by default these days.quarantine_size_mb
ASan option to a different value than -1 which means unlimited.
Internal data structures of libFuzzer but these should stop growing at some point.
Memory allocated by your code that isn't returned to the OS after being freed. The RSS value will often reflect the maximum used by any of the test inputs and won't go down after that. All freed memory is available to subsequent allocations, of course.
Another explanation is that your code really has a memory leak. Many leaks are detected with the detect_leaks
option which is on by default. But it's also possible that a global data structure like a cache is growing constantly which can't be detected when fuzzing.
With the quarantine_size_mb
option, RSS should converge eventually.