<div dir="ltr">More replies below. <div><br></div><div>If you feel some of your questions left unanswered, please ping or file a bug. </div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 5, 2015 at 5:50 AM, Greg Stark via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=llvm-dev@lists.llvm.org&cc=&bcc=&su=&body=','_blank');return false;">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">HI think I have a fairly nicely integrated Libfuzzer based fuzzer in<br>
Postgres now. I can run things like:<br>
<br>
SELECT fuzz(100000,'select regexp_matches(''foo/bar/baz'',$1,''g'')')<br>
<br>
Which makes it convenient to fuzz arbitrary public functions available<br>
in SQL. (I haven't figured out what interface to make for fuzzing<br>
internal functions which take char buffers that can have nuls. The SQL<br>
interface will only be able to handle valid utf8 encoded strings which<br>
contain no nuls.)<br>
<br>
<br>
I have some feedback of things that are a bit awkard or that I miss<br>
from AFL. Some of this may actually be there but I'm just not using it<br>
right?<br>
<br>
1) One minor things, it's a bit of a pain to construct the argv when<br>
you're not invoking it on the command line. </blockquote><div><br></div><div>So, you want the code Fuzzer::FuzzingOptions (FuzzerInternal.h) to be accessible to a user? </div><div>I thought about it and may do it one day. </div><div>File a bug if you want to track it. </div><div>(Not my first priority though). </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Not a big deal but it<br>
would be nice to bypass that and just allow the caller to set the<br>
variables directly. Some of the parameters are not entirely clear<br>
either -- I'm not clear what the distinction is between -runs and<br>
-iterations </blockquote><div><br></div><div>-iterations is an artifact from the past. </div><div>removed in 247030.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">and I'm not clear whether the timeout is for the whole run<br>
or individual tests</blockquote><div><br></div><div> individual tests</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> (it's not doing anything in my case which is<br>
probably due to Postgres having its own ALRM handler).<br></blockquote><div><br></div><div>Yea, probably. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
2) I've caught a bug which causes enormous stack growth. AFL enforces<br>
strict memory and time limits on the tests which is awfully<br>
convenient. I can implement those myself in my fuzzer function (and in<br>
fact in the Postgres context it would be best if I did) but some<br>
simple AFL-style protection would be appreciated, as it is it takes a<br>
*looong* time to fail and doesn't leave behind the crashing test.</blockquote><div><br></div><div>That's strange.</div><div>Most likely this is the same problem as above: Postgres redefines the ALRM handler? </div><div>libFuzzer should be able to detect a long running test and report it. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> It<br>
would be nice if Libfuzzer took a page out of the sanitize code's<br>
tricks and kept an mmapped file where it wrote the current test being<br>
run. If the file is never synced then it shouldn't cause any syscalls<br>
or I/O until the program crashes and the file descriptor is closed.<br></blockquote><div>Let's resolve the above problem first, maybe this will not be needed.  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
My thinking is I need to set an RLIMIT_STACK setting and then install<br>
a SEGV handler which will longjmp back to the top level and return to<br>
the fuzzer. That will be risky since it's in theory impossible to<br>
restore any state the SEGV caused but in practice if it's always<br>
caused by a stack overflow might be safe. I would also like to have an<br>
ALRM handler but that requires calling alarm() on every call and I'm<br>
not sure if the setitimer in Libfuzzer can be disabled or if it'll<br>
interfere with that. Maybe there's a better approach, I could call<br>
setitimer and if I see more than n ALRMs during the execution decide<br>
it's a fault. Again it would be nice if Libfuzzer provided that<br>
itself.<br></blockquote><div><br></div><div>I am confused.  Libfuzzer does set an alarm. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
3) When it writes the minimal test corpus it seems to keep older tests<br>
around too. I guess the intent is to pass two directories, </blockquote><div><br></div><div>correct.  </div><div>If you want to minimize the corpus do it like this: </div><div>./fuzzer NEW_EMPTY_DIR OLD_CORPUS<br></div><div>The docs were a bit vague, I've tried to improve them in 247033.. <br></div><div><br></div><div>I rarely use this option myself because libFuzzer does corpus minimization at startup. <br></div><div>It may still be useful if you want e.g. to commit the corpus to test repository </div><div>or to share the corpus with other fuzzers. </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">one which<br>
starts empty and is intended to receive the results and one which is<br>
maintained as the working tree? I'm not sure how to use this mode.<br>
<br>
4) The actually fuzzing seems to be less effective than AFL at finding<br>
good cases.</blockquote><div><br></div><div>That's not entirely unexpected, AFL is extremely algorithmically advanced. </div><div>We are trying to catch up :)</div><div><br></div><div>Note that I've just added support for AFL-style dictionaries, </div><div>which may help in your case. </div><div><a href="http://llvm.org/docs/LibFuzzer.html#dictionaries">http://llvm.org/docs/LibFuzzer.html#dictionaries</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> In particular I've found I have to use only_ascii mode or<br>
else it spends all the time looking at encoding errors on random<br>
binary inputs. Even in only_ascii mode it seems insistent on putting a<br>
^L in a *lot* of tests even when the function being tested always ends<br>
with the same error if one is present.<br></blockquote><div><br></div><div>Hmm.. I simply rely on isspace/isprint</div><div>I may of course change it to not emit ^L in ascii mode, </div><div>but another way for you is to replace ^L with a space in your target function. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
I'm hoping to try DFA mode and hoping it will help with this but all<br>
the "experimental" warnings in the docs scare me. Is it just that<br>
there's room for improvement or is there any downside to running in<br>
that mode?<br></blockquote><div><br></div><div>You mean, the data flow feedback mode enabled by -use_traces=1 (and -fsanitize-coverage=trace-cmp)?</div><div>This is really a prototypish thing so far. </div><div>I've seen several cases in the wild where it breaks though a wall (where the regular mode does not find new coverage for days),</div><div>but it's not anywhere near to be complete. </div><div>By all means, try it as one of the strategies, but don't solely rely on it. </div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Another thing I'm not clear whether it's not implemented yet or<br>
there's just no feedback yet is the test for variable coverage. AFL<br>
runs the same test repeatedly to test whether the coverage is<br>
repeatable which can be an important thing to know whether your<br>
testing is actually well implemented or whether you're failing to<br>
clean up state sufficiently between runs.<br></blockquote><div><br></div><div>Hmm.. Interesting. I don't think we have anything to check </div><div>if the target function produces stable coverage. </div><div>You probably can run the fuzzer 100 times with -runs=0 -seed=1 and see if it produces the same INITED coverage.</div><div>Is that what you need? </div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
5) I'm currently running 1M iterations per call then calling it again<br>
(in a new process). It would be convenient if I could call it again in<br>
the same process and in fact it would be most convenient if I could<br>
make my code call the fuzzer repeatedly for, say, 1k invocations. I<br>
could check for C-c once ever 1k calls and do any other cleanup,<br>
checking for memory leaks, etc at that time.<br></blockquote><div><br></div><div>I'll need more explanations here. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
It would also be nice to be able to ask for the minimal corpus back in<br>
memory along with meta information like coverage, runtime, etc so I<br>
could, say, store them in the database :)<br></blockquote><div><br></div><div>All this is doable, just not my priority for now. </div><div>If you come up with a simple patch -- you are more than welcome. </div><div><br></div><div>(For large/complex patches now is not the best time though)</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
6) The crashing and slow tests are written to the current directory.<br>
It would be nice to be able to provide a directory for them to go<br>
into.</blockquote><div><br></div><div>In my todo, file a separate bug if you want to track it. </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> Also, it would be nice to provide a callback or some other way<br>
to override this. I could generate the whole SQL reproduction instead<br>
of just having the binary data to pass and have to remember what<br>
function I was testing.<br></blockquote><div>A bit more involved, but doable, of course. </div><div>You can probably also do it on your side and let us know how it works. </div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
In general the feedback is a bit unclear. It seems to print binary<br>
strings in several different escape styles, sometimes using \x (though<br>
it's not clear how many hex digits follow) sometimes using 0x and<br>
sometimes using base64:<br>
<br>
#755 NEW    cov: 14667 bits: 476 units: 6 exec/s: 20 L: 4 \xa\x5\xcb*<br>
0xa,0x5,0xcb,0x2a,<br>
<br>
Test unit written to crash-b0f4bc53c8f72fd53ef0a6c1f46115bd7bd8fe50<br>
Base64: IZqM9rA71To7KDonOlb8pCEoJ3Mn2sAnO1I3XwYoITtxO0exSjwo7u4nKZ8hnilHeQo6GDshTI4pKipWLa8KXg==<br>
<br>
Of these only the base64 is convenient for writing reproductions<br>
(though a callback would be most convenient) but it's not so<br>
convenient for watching the progress. And for many lines it seems to<br>
print no test data which is definitely not helpful for watching<br>
progress:<br>
<br>
#2028804 NEW    cov: 15330 bits: 6511 units: 127 exec/s: 5880 L: 39<br>
#2045447 NEW    cov: 15330 bits: 6512 units: 128 exec/s: 5877 L: 47<br></blockquote><div><br></div><div><br></div><div>That's a trade of between more output and fewer output. </div><div>You can watch the corpus itself if you want to see all cases. </div><div><br></div><div>The output like "0xa,0x5,0xcb,0x2a," is useful if you want to paste this data back to a C program as a char array. </div><div>base64 is the simplest way to have a file repro. </div><div>Escaped text is printed only for very small units, just FYI. </div><div>Making things nicer in in my TODO, but someone will always dislike the style </div><div>and I really don't want to spend time (at this point) making the output more customizable. </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Also, all this feedback is currently going into the server log. I<br>
would like to capture it and report it to the client. I'm currently<br>
basically just doing my own progress feedback this way but it's<br>
missing the information about coverage and number of units found. It<br>
can only show the number of tests done and things like memory usage<br>
etc.<br>
<br>
7) If I open up the corpus files in emacs and accidentally hit any key<br>
then emacs saves an autosave file but then deletes it when I undo the<br>
accidental edit -- which causes Libfuzzer to pretty much immediately<br>
crash with:<br>
<br>
Can not stat: /var/tmp/corpus/.#16813d894b330e26fdf4520793501dfffc830eb9;<br>
exiting<br></blockquote><div><br></div><div>I've seen a similar problem too (not with emacs). </div><div>I'll try to fix it. </div><div>Again, file a bug if you want to track this. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
I would suggest ignoring auto-save and backup files (.#* and *~) but<br>
in any case this doesn't seem like it should be a fatal error. Just<br>
warn about the disappearing file and move on to the next one.<br>
<span class=""><font color="#888888"><br>
--<br>
greg<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=llvm-dev@lists.llvm.org&cc=&bcc=&su=&body=','_blank');return false;">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</font></span></blockquote></div><br></div></div>