Google's Address-sanitizer: a fast memory error detector (10x valgrind)
code.google.com
code.google.com
The tool does not detect uninitialized memory reads, and memory leaks are not in yet. However, if they claims about speed (only 2x slowdown) are true, this is huge.
http://code.google.com/p/address-sanitizer/wiki/ComparisonOf...
I bet they used llvm to do this? it would be childs play to do this in llvm ...
the downside to this technique is that you can only instrument / inspect code that you compile, so if you have any third party code that you link against, and that code results in memory errors, you have problems. you always do have third party code, like the C runtime. you can get around this though by having the source for the runtime and recompiling it with your instrumentation added.
you CAN recompile the runtime on windows (they ship it to you in a ready-to-build way as part of visual studio), but there are a lot of other libraries that they don't do that for (advapi, com, rpc, etc). I guess it's fortunate for chromium that they can run these tests on the linux codebase and have the windows codebase/build pick up the improvements made for free ...
also, if you're willing to insert some annotations into the code that you are instrumenting you can perform race condition detection with lower overhead. but konstantin already wrote a DBI extension that does race condition detection without requiring annotations (ahem, most of the time) so I guess that is low on his to-do list...
I don't really see the disadvantage of not being able to debug within in the runtime. The class of errors this analyzer is meant to adress is stuff like use after free, out of bounds access, and use after return. If your runtime is doing those then a) you have bigger problems, b) you wouldn't be able to fix it anyway without the source.
and as I understand their implementation, this won't be found because they instrument loads and stores in code that their clang compiles. the compiled code will look like: push off a push 0 push 100 call memset
there are two options that I see: 1. compile the runtime with the instrumentation 2. assemble a massive list of functions which you know to de-reference pointers they take as arguments and then hope that list is somewhat representative / comprehensive
About a month ago the infrastructure team also added an ASAN bot to the waterfall, and I think the stability team was experimenting with it before the rest of us. So, ASAN has had a pretty big uptake in the Chromium project.
Have you guys started isolating any patterns to the bugs you missed pre-ASAN? What were your fuzzers (for instance) failing to do? Are there specific kinds of code paths (things buried in specific state transitions, things that were timing specific) that you couldn't catch without this level of instrumentation?
If you knew then what you knew now, short of implementing ASAN, how would you change your fuzzing cluster?
In terms of process, our scaled out fuzzing is rapidly evolving anyway. So, I think it was early enough that our approach wouldn't have changed too much. It's more that ASAN has enabled us to move faster, with fewer resources. And the improved turnaround time has significantly reduced the number of bugs that get past trunk.
If you want, I can put you in touch with the guys on my team doing the real work on the fuzzing cluster (I've been assisting in only an advisory capacity). They're also planning on doing a Chromium blog post on the project soon, so you could wait for that if you prefer.
Also its just another version of electric fence which existed ever since I started debugging code. Correct me if I am wrong.
I was about to say the same thing (though comparing it to Mungwall and Enforcer on AmigaOS), but then I read through it in more detail. There are significant differences:
Electric Fence/Mungwall/Enforcer type systems rely on one or both of poisoning and using the MMU to trap accesses. But the MMU approach only works fast if you only trap access to unallocated pages, not if you try to trap every access. That's where the comparison to Valgrind comes in - Valgrind checks every memory access precisely. But it's ridiculously slow.
So you get immediate feedback for accesses to unallocated pages from the simpler tools, and very quickly, since it's no slower than any other memory access through the MMU, except when there's a hit. Tools like this may or may not try to be more precise by trapping accesses to partially allocated pages, but if they do, performance drops dramatically.
Then they can trap writes to poisoned areas where they don't trap reads by running checks for magic values at specific times - typically at least on free() and program exit. The problem with this is that it won't pinpoint where the write happened, and it won't catch reads of unallocated memory.
But this tool inlines code during compilation that checks every dereferencing of every pointer, as far as I understand, by maintaining a lookup table that says whether or not a specific byte is allocated or not. The upside is that they can be as precise as Valgrind.
As for the electric fence comparison, ASANs strengths are that it provides more detailed reports and detects more types of errors, but is still very fast. For example, ASAN will detect stack and global boundary violations, whereas electric fence will not.
He works at Google's Moscow office:
http://blog.1024cores.net/2011/08/relacy-race-detector-24-an...