KEMBAR78
Address/Thread/Memory Sanitizer | PDF
Address/Thread/MemorySanitizer
Slaughtering C++ bugs
Dmitry Vyukov, Google
dvyukov@
Feb 2015 @C++ User Group, Russia
● AddressSanitizer (aka ASan)
○ detects use-after-free and buffer overflows (C++)
● ThreadSanitizer (aka TSan)
○ detects data races (C++ & Go)
● MemorySanitizer (aka MSan)
○ detects uses of uninitialized memory (C++)
Agenda
AddressSanitizer
addressability bugs
AddressSanitizer overview
● Finds
○ buffer overflows (stack, heap, globals)
○ heap-use-after-free, stack-use-after-return
○ some more
● Compiler module (clang, gcc)
○ instruments all loads/stores
○ inserts redzones around stack and global variables
● Run-time library
○ malloc replacement (redzones, quarantine)
○ Bookkeeping for error messages
int main(int argc, char **argv) {
int stack_array[100];
stack_array[1] = 0;
return stack_array[argc + 100]; // BOOM
}
% clang++ -O1 -fsanitize=address a.cc; ./a.out
ERROR: AddressSanitizer stack-buffer-overflow
READ of size 4 at 0x7f5620d981b4 thread T0
#0 0x4024e8 in main a.cc:4
Address 0x7f5620d981b4 is located at offset 436 in frame
<main> of T0's stack:
This frame has 1 object(s):
[32, 432) 'stack_array'
ASan report example: stack-buffer-overflow
int main(int argc, char **argv) {
int *array = new int[100];
int res = array[argc + 100]; // BOOM
delete [] array;
return res;
}
% clang++ -O1 -fsanitize=address a.cc; ./a.out
ERROR: AddressSanitizer heap-buffer-overflow
READ of size 4 at 0x7fe4b0c76214 thread T0
#0 0x40246f in main a.cc:3
0x7fe4b0c76214 is located 4 bytes to the right of 400-
byte region [0x7fe..., 0x7fe...)
allocated by thread T0 here:
#0 0x402c36 in operator new[](unsigned long)
#1 0x402422 in main a.cc:2
ASan report example: heap-buffer-overflow
ASan report example: use-after-free
int main(int argc, char **argv) {
int *array = new int[100];
delete [] array;
return array[argc]; // BOOM
}
% clang++ -O1 -fsanitize=address a.cc && ./a.out
ERROR: AddressSanitizer heap-use-after-free
READ of size 4 at 0x7faa07fce084 thread T0
#0 0x40433c in main a.cc:4
0x7faa07fce084 is located 4 bytes inside of 400-byte region
freed by thread T0 here:
#0 0x4058fd in operator delete[](void*) _asan_rtl_
#1 0x404303 in main a.cc:3
previously allocated by thread T0 here:
#0 0x405579 in operator new[](unsigned long) _asan_rtl_
#1 0x4042f3 in main a.cc:2
Any aligned 8 bytes may have 9 states:
N good bytes and 8 - N bad (0<=N<=8)
0
7
6
5
4
3
2
1
-1
Good byte
Bad byte
Shadow value
ASan shadow byte
ASan virtual address space
0xffffffff
0x20000000
0x1fffffff
0x04000000
0x03ffffff
0x00000000
Application
Shadow
mprotect-ed
Shadow = Addr >> 3
ASan instrumentation: 8-byte access
char *shadow = a >> 3;
if (*shadow)
ReportError(a);
*a = ...
*a = ...
ASan instrumentation: N-byte access (1, 2, 4)
char *shadow = a >> 3;
if (*shadow &&
*shadow <= ((a&7)+N-1))
ReportError(a);
*a = ...
*a = ...
Instrumentation example (x86_64)
mov %rdi,%rax
shr $0x3,%rax # shift by 3
cmpb $0x0,(%rax) # load shadow
je 1f <foo+0x1f>
ud2a # generate SIGILL*
movq $0x1234,(%rdi) # original store
* May use call instead of UD2
Instrumenting stack frames
void foo() {
char a[328];
<------------- CODE ------------->
}
Instrumenting stack frames
void foo() {
char rz1[32]; // 32-byte aligned
char a[328];
char rz2[24];
char rz3[32];
int *shadow = &rz1 >> 3;
shadow[0] = 0xffffffff; // poison rz1
shadow[11] = 0xffffff00; // poison rz2
shadow[12] = 0xffffffff; // poison rz3
<------------- CODE ------------->
shadow[0] = shadow[11] = shadow[12] = 0;
}
Instrumenting globals
int a;
struct {
int original;
char redzone[60];
} a; // 32-aligned
Malloc replacement
● Insert redzones around every allocation
○ poison redzones on malloc
● Delay the reuse of freed memory
○ poison entire memory region on free
● Collect stack traces for every malloc/free
● 2x slowdown (Valgrind: 20x and more)
● 1.5x-3x memory overhead
● 3000+ bugs found in Chrome in 3 years
● 3000+ bugs found in Google server software
● 1000+ bugs everywhere else
○ Firefox, FreeType, FFmpeg, WebRTC, libjpeg-turbo,
Perl, Vim, LLVM, GCC, MySQL
ASan marketing slide
ThreadSanitizer
data races
What is a data race?
A data race happens when two threads access
the same variable concurrently, and at least
one of the accesses is a write.
This is undefined behavior in C and C++.
ThreadSanitizer
● Compile-time instrumentation (clang, gcc)
○ Intercepts all reads/writes
○ Function entry/exit
○ Atomic operations
● Run-time library
○ Malloc replacement
○ Intercepts all synchronization and thread mgmt
○ Handles reads/writes
TSan report example: data race
void Thread1() { Global = 42; }
int main() {
pthread_create(&t, 0, Thread1, 0);
Global = 43;
...
% clang -fsanitize=thread -g a.c && ./a.out
WARNING: ThreadSanitizer: data race (pid=20373)
Write of size 4 at 0x7f... by thread 1:
#0 Thread1 a.c:1
Previous write of size 4 at 0x7f... by main thread:
#0 main a.c:4
Thread 1 (tid=20374, running) created at:
#0 pthread_create ??:0
#1 main a.c:3
Compiler instrumentation
void foo(int *p) {
*p = 42;
}
void foo(int *p) {
__tsan_func_entry(__builtin_return_address(0));
__tsan_write4(p);
*p = 42;
__tsan_func_exit()
}
Compiler instrumentation
a.compare_exchange_strong(cmp, xchg)
__tsan_atomic32_compare_exchange(
&a, &cmp, xchg, seq_cst, seq_cst)
Direct shadow mapping (64-bit Linux)
Application
0x7fffffffffff
0x7f0000000000
Protected
0x7effffffffff
0x200000000000
Shadow
0x1fffffffffff
0x180000000000
Protected
0x17ffffffffff
0x000000000000
Shadow = 4 * (Addr & kMask);
Shadow cell
An 8-byte shadow cell represents one memory
access:
○ ~16 bits: TID (thread ID)
○ ~42 bits: Epoch (scalar clock)
○ 5 bits: position/size in 8-byte word
○ 1 bit: IsWrite
Full information (no more dereferences)
TID
Epo
Pos
IsW
4 shadow cells per 8 app. bytes
TID
Epo
Pos
IsW
TID
Epo
Pos
IsW
TID
Epo
Pos
IsW
TID
Epo
Pos
IsW
Example: first access
T1
E1
0:2
W
Write in thread T1
Example: second access
T1
E1
0:2
W
T2
E2
4:8
R
Read in thread T2
Example: third access
T1
E1
0:2
W
T3
E3
0:4
R
T2
E2
4:8
R
Read in thread T3
Example: race?
T1
E1
0:2
W
T3
E3
0:4
R
T2
E2
4:8
R
- overlap?
- different threads?
- one write?
- happens-before?
Fast happens-before
Previous access by T1 at TS1 (from shadow).
Current access by T3.
T3->vclock[T1] > TS1 -> no race
T3->vclock[T1] < TS1 -> RACE
Constant-time operation: 1 local load + 1
comparison.
Stack trace for previous access
● Important to understand the report
● Per-thread cyclic buffer of events
○ 64 bits per event (type + PC)
○ Events: memory access, function entry/exit
○ Information will be lost after some time
○ Buffer size is configurable
● Replay the event buffer on report
○ Unlimited number of frames
TSan overhead
● CPU: 4x-10x
● RAM: 5x-8x
Trophies
● 3000+ races in Google server-side C++ code
○ Scales to huge apps
● 500+ races in Go code
○ 60+ bugs in Go stdlib
● 200+ races in Chromium
1000+ races everywhere: Firefox, WebRTC,
OpenSSL, libgomp, llvm, gcc,
Key advantages
● Speed
○ > 10+x faster than other tools
● Native support for atomics
○ Hard or impossible to implement with binary
translation (Helgrind, Intel Inspector)
MemorySanitizer
uses of uninitialized memory (UUM)
MSan report example: UMR
int main(int argc, char **argv) {
int x[10];
x[0] = 1;
if (x[argc]) return 1;
...
% clang -fsanitize=memory -fPIE -pie a.c -g; ./a.out
WARNING: MemorySanitizer: UMR (uninitialized-memory-read)
#0 0x7ff6b05d9ca7 in main stack_umr.c:4
ORIGIN: stack allocation: x@main
Shadow memory
● Bit to bit shadow mapping
○ 1 means 'poisoned' (uninitialized)
● Uninitialized memory:
○ Returned by malloc
○ Local stack objects
● Initialized memory:
○ Constants
○ Executable and modules (.text, .data, .bss)
○ IO/Syscalls (read)
Shadow propagation
Reporting every load of uninitialized data is too noisy.
struct {
char x;
// 3-byte padding
int y;
}
It's OK to copy uninitialized data around.
Uninit calculations are OK, too, as long as the result is not
used. Programs do it. A lot!
Shadow propagation
A = B << C: A' = B' << C
A = B & C: A' = (B' & C') | (B & C') | (B' & C)
A = B + C: A' = B' | C' (approx.)
Report errors only on some uses: conditional
branch, dereference, syscall argument (visible
side-effect).
Tracking origins
Secondary shadow
○ Origin-ID is 4 bytes, 1:1 mapping
○ 1.5x additional slowdown
Remember origin on malloc/local allocation.
Propagate origin along with uninit value.
Tracking origins
WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7fa14df37e1d in main test.c:19:10
Uninitialized value was stored to memory at
#0 0x7fa14df37a57 in pop() test.c:8:3
#1 0x7fa14df37dd5 in main test.c:19:10
Uninitialized value was stored to memory at
#0 0x7fa14df37733 in shift() test.c:2:16
#1 0x7fa14df37dbb in main test.c:18:3
Uninitialized value was stored to memory at
#0 0x7fa14df3793f in push(int*) test.c:5:3
#1 0x7fa14df37b2f in func1() test.c:14:3
#2 0x7fa14df37db6 in main test.c:17:3
Uninitialized value was created by an allocation of
’local_var’ in the stack frame of function ’func1’
#0 0x7fa14df37ad0 in func1() test.c:12
Shadow mapping
Application
0x7fffffffffff
0x600000000000
Origin
0x5fffffffffff
0x400000000000
Shadow
0x3fffffffffff
0x200000000000
Protected
0x1fffffffffff
0x000000000000
Shadow = Addr - 0x400000000000;
Origin = Addr - 0x200000000000;
● Without origins:
○ CPU: 2.5x
○ RAM: 2x
● With origins:
○ CPU: 4x
○ RAM: 3x
MSan overhead
Tricky part :(
Missing any write causes false reports.
● Libc
○ Solution: function wrappers
● Inline assembly
○ Openssl, libjpeg_turbo, etc
● JITs (e.g. V8)
MSan Trophies
● 1200+ bugs in Google server-size code
● 300+ in Chromium
● 30+ in clang
● hundreds of bugs elsewhere
What’s next?
You can help
Faster
● Use hardware features
○ Or even create them (!)
● Static analysis: eliminate redundant checks
○ Many attempts were made; not trivial!
○ How to test it??
More bugs
● Instrument assembler & binaries
○ SyzyASAN: instruments binaries statically, Win32
● Instrument JIT-ed code & JIT’s heap
● More types of bugs
○ Intra-object overflows
○ Annotations in STL, e.g. std::vector<>
● Other languages (e.g. races in Java)
More environments
● Microsoft Windows
● Mobile, embedded
● OS Kernel (Linux and others)
Q&A
http://code.google.com/p/address-sanitizer/
http://code.google.com/p/thread-sanitizer/
http://code.google.com/p/memory-sanitizer/
Dmitry Vyukov, Google, dvyukov@
● AddressSanitizer (memory corruption)
○ Linux, FreeBSD, OSX, CrOS, Android, iOS
○ i386, x86_64, ARM, PowerPC
○ WIP: Windows, *BSD (?)
○ Clang 3.1+ and GCC 4.8+
● ThreadSanitizer (data races)
○ A "must use" if you have threads (C++, Go)
○ Only x86_64 Linux/FreeBSD; Clang 3.2+ and GCC
4.8+
● MemorySanitizer (uses of uninitialized data)
○ Only x86_64 Linux; Clang 3.3
○ WIP: MIPS64, FreeBSD
Supported platforms
ASan/MSan vs Valgrind (Memcheck)
Valgrind ASan MSan
Heap out-of-bounds YES YES NO
Stack out-of-bounds NO YES NO
Global out-of-bounds NO YES NO
Use-after-free YES YES NO
Use-after-return NO Sometimes NO
Uninitialized reads YES NO YES
CPU Overhead 10x-300x 1.5x-3x 3x
● Slowdowns will add up
○ Bad for interactive or network apps
● Memory overheads will multiply
○ ASan redzone vs TSan/MSan large shadow
● Not trivial to implement
Why not a single tool?

Address/Thread/Memory Sanitizer

  • 1.
    Address/Thread/MemorySanitizer Slaughtering C++ bugs DmitryVyukov, Google dvyukov@ Feb 2015 @C++ User Group, Russia
  • 2.
    ● AddressSanitizer (akaASan) ○ detects use-after-free and buffer overflows (C++) ● ThreadSanitizer (aka TSan) ○ detects data races (C++ & Go) ● MemorySanitizer (aka MSan) ○ detects uses of uninitialized memory (C++) Agenda
  • 3.
  • 4.
    AddressSanitizer overview ● Finds ○buffer overflows (stack, heap, globals) ○ heap-use-after-free, stack-use-after-return ○ some more ● Compiler module (clang, gcc) ○ instruments all loads/stores ○ inserts redzones around stack and global variables ● Run-time library ○ malloc replacement (redzones, quarantine) ○ Bookkeeping for error messages
  • 5.
    int main(int argc,char **argv) { int stack_array[100]; stack_array[1] = 0; return stack_array[argc + 100]; // BOOM } % clang++ -O1 -fsanitize=address a.cc; ./a.out ERROR: AddressSanitizer stack-buffer-overflow READ of size 4 at 0x7f5620d981b4 thread T0 #0 0x4024e8 in main a.cc:4 Address 0x7f5620d981b4 is located at offset 436 in frame <main> of T0's stack: This frame has 1 object(s): [32, 432) 'stack_array' ASan report example: stack-buffer-overflow
  • 6.
    int main(int argc,char **argv) { int *array = new int[100]; int res = array[argc + 100]; // BOOM delete [] array; return res; } % clang++ -O1 -fsanitize=address a.cc; ./a.out ERROR: AddressSanitizer heap-buffer-overflow READ of size 4 at 0x7fe4b0c76214 thread T0 #0 0x40246f in main a.cc:3 0x7fe4b0c76214 is located 4 bytes to the right of 400- byte region [0x7fe..., 0x7fe...) allocated by thread T0 here: #0 0x402c36 in operator new[](unsigned long) #1 0x402422 in main a.cc:2 ASan report example: heap-buffer-overflow
  • 7.
    ASan report example:use-after-free int main(int argc, char **argv) { int *array = new int[100]; delete [] array; return array[argc]; // BOOM } % clang++ -O1 -fsanitize=address a.cc && ./a.out ERROR: AddressSanitizer heap-use-after-free READ of size 4 at 0x7faa07fce084 thread T0 #0 0x40433c in main a.cc:4 0x7faa07fce084 is located 4 bytes inside of 400-byte region freed by thread T0 here: #0 0x4058fd in operator delete[](void*) _asan_rtl_ #1 0x404303 in main a.cc:3 previously allocated by thread T0 here: #0 0x405579 in operator new[](unsigned long) _asan_rtl_ #1 0x4042f3 in main a.cc:2
  • 8.
    Any aligned 8bytes may have 9 states: N good bytes and 8 - N bad (0<=N<=8) 0 7 6 5 4 3 2 1 -1 Good byte Bad byte Shadow value ASan shadow byte
  • 9.
    ASan virtual addressspace 0xffffffff 0x20000000 0x1fffffff 0x04000000 0x03ffffff 0x00000000 Application Shadow mprotect-ed Shadow = Addr >> 3
  • 10.
    ASan instrumentation: 8-byteaccess char *shadow = a >> 3; if (*shadow) ReportError(a); *a = ... *a = ...
  • 11.
    ASan instrumentation: N-byteaccess (1, 2, 4) char *shadow = a >> 3; if (*shadow && *shadow <= ((a&7)+N-1)) ReportError(a); *a = ... *a = ...
  • 12.
    Instrumentation example (x86_64) mov%rdi,%rax shr $0x3,%rax # shift by 3 cmpb $0x0,(%rax) # load shadow je 1f <foo+0x1f> ud2a # generate SIGILL* movq $0x1234,(%rdi) # original store * May use call instead of UD2
  • 13.
    Instrumenting stack frames voidfoo() { char a[328]; <------------- CODE -------------> }
  • 14.
    Instrumenting stack frames voidfoo() { char rz1[32]; // 32-byte aligned char a[328]; char rz2[24]; char rz3[32]; int *shadow = &rz1 >> 3; shadow[0] = 0xffffffff; // poison rz1 shadow[11] = 0xffffff00; // poison rz2 shadow[12] = 0xffffffff; // poison rz3 <------------- CODE -------------> shadow[0] = shadow[11] = shadow[12] = 0; }
  • 15.
    Instrumenting globals int a; struct{ int original; char redzone[60]; } a; // 32-aligned
  • 16.
    Malloc replacement ● Insertredzones around every allocation ○ poison redzones on malloc ● Delay the reuse of freed memory ○ poison entire memory region on free ● Collect stack traces for every malloc/free
  • 17.
    ● 2x slowdown(Valgrind: 20x and more) ● 1.5x-3x memory overhead ● 3000+ bugs found in Chrome in 3 years ● 3000+ bugs found in Google server software ● 1000+ bugs everywhere else ○ Firefox, FreeType, FFmpeg, WebRTC, libjpeg-turbo, Perl, Vim, LLVM, GCC, MySQL ASan marketing slide
  • 18.
  • 19.
    What is adata race? A data race happens when two threads access the same variable concurrently, and at least one of the accesses is a write. This is undefined behavior in C and C++.
  • 20.
    ThreadSanitizer ● Compile-time instrumentation(clang, gcc) ○ Intercepts all reads/writes ○ Function entry/exit ○ Atomic operations ● Run-time library ○ Malloc replacement ○ Intercepts all synchronization and thread mgmt ○ Handles reads/writes
  • 21.
    TSan report example:data race void Thread1() { Global = 42; } int main() { pthread_create(&t, 0, Thread1, 0); Global = 43; ... % clang -fsanitize=thread -g a.c && ./a.out WARNING: ThreadSanitizer: data race (pid=20373) Write of size 4 at 0x7f... by thread 1: #0 Thread1 a.c:1 Previous write of size 4 at 0x7f... by main thread: #0 main a.c:4 Thread 1 (tid=20374, running) created at: #0 pthread_create ??:0 #1 main a.c:3
  • 22.
    Compiler instrumentation void foo(int*p) { *p = 42; } void foo(int *p) { __tsan_func_entry(__builtin_return_address(0)); __tsan_write4(p); *p = 42; __tsan_func_exit() }
  • 23.
  • 24.
    Direct shadow mapping(64-bit Linux) Application 0x7fffffffffff 0x7f0000000000 Protected 0x7effffffffff 0x200000000000 Shadow 0x1fffffffffff 0x180000000000 Protected 0x17ffffffffff 0x000000000000 Shadow = 4 * (Addr & kMask);
  • 25.
    Shadow cell An 8-byteshadow cell represents one memory access: ○ ~16 bits: TID (thread ID) ○ ~42 bits: Epoch (scalar clock) ○ 5 bits: position/size in 8-byte word ○ 1 bit: IsWrite Full information (no more dereferences) TID Epo Pos IsW
  • 26.
    4 shadow cellsper 8 app. bytes TID Epo Pos IsW TID Epo Pos IsW TID Epo Pos IsW TID Epo Pos IsW
  • 27.
  • 28.
  • 29.
  • 30.
    Example: race? T1 E1 0:2 W T3 E3 0:4 R T2 E2 4:8 R - overlap? -different threads? - one write? - happens-before?
  • 31.
    Fast happens-before Previous accessby T1 at TS1 (from shadow). Current access by T3. T3->vclock[T1] > TS1 -> no race T3->vclock[T1] < TS1 -> RACE Constant-time operation: 1 local load + 1 comparison.
  • 32.
    Stack trace forprevious access ● Important to understand the report ● Per-thread cyclic buffer of events ○ 64 bits per event (type + PC) ○ Events: memory access, function entry/exit ○ Information will be lost after some time ○ Buffer size is configurable ● Replay the event buffer on report ○ Unlimited number of frames
  • 33.
    TSan overhead ● CPU:4x-10x ● RAM: 5x-8x
  • 34.
    Trophies ● 3000+ racesin Google server-side C++ code ○ Scales to huge apps ● 500+ races in Go code ○ 60+ bugs in Go stdlib ● 200+ races in Chromium 1000+ races everywhere: Firefox, WebRTC, OpenSSL, libgomp, llvm, gcc,
  • 35.
    Key advantages ● Speed ○> 10+x faster than other tools ● Native support for atomics ○ Hard or impossible to implement with binary translation (Helgrind, Intel Inspector)
  • 36.
  • 37.
    MSan report example:UMR int main(int argc, char **argv) { int x[10]; x[0] = 1; if (x[argc]) return 1; ... % clang -fsanitize=memory -fPIE -pie a.c -g; ./a.out WARNING: MemorySanitizer: UMR (uninitialized-memory-read) #0 0x7ff6b05d9ca7 in main stack_umr.c:4 ORIGIN: stack allocation: x@main
  • 38.
    Shadow memory ● Bitto bit shadow mapping ○ 1 means 'poisoned' (uninitialized) ● Uninitialized memory: ○ Returned by malloc ○ Local stack objects ● Initialized memory: ○ Constants ○ Executable and modules (.text, .data, .bss) ○ IO/Syscalls (read)
  • 39.
    Shadow propagation Reporting everyload of uninitialized data is too noisy. struct { char x; // 3-byte padding int y; } It's OK to copy uninitialized data around. Uninit calculations are OK, too, as long as the result is not used. Programs do it. A lot!
  • 40.
    Shadow propagation A =B << C: A' = B' << C A = B & C: A' = (B' & C') | (B & C') | (B' & C) A = B + C: A' = B' | C' (approx.) Report errors only on some uses: conditional branch, dereference, syscall argument (visible side-effect).
  • 41.
    Tracking origins Secondary shadow ○Origin-ID is 4 bytes, 1:1 mapping ○ 1.5x additional slowdown Remember origin on malloc/local allocation. Propagate origin along with uninit value.
  • 42.
    Tracking origins WARNING: MemorySanitizer:use-of-uninitialized-value #0 0x7fa14df37e1d in main test.c:19:10 Uninitialized value was stored to memory at #0 0x7fa14df37a57 in pop() test.c:8:3 #1 0x7fa14df37dd5 in main test.c:19:10 Uninitialized value was stored to memory at #0 0x7fa14df37733 in shift() test.c:2:16 #1 0x7fa14df37dbb in main test.c:18:3 Uninitialized value was stored to memory at #0 0x7fa14df3793f in push(int*) test.c:5:3 #1 0x7fa14df37b2f in func1() test.c:14:3 #2 0x7fa14df37db6 in main test.c:17:3 Uninitialized value was created by an allocation of ’local_var’ in the stack frame of function ’func1’ #0 0x7fa14df37ad0 in func1() test.c:12
  • 43.
  • 44.
    ● Without origins: ○CPU: 2.5x ○ RAM: 2x ● With origins: ○ CPU: 4x ○ RAM: 3x MSan overhead
  • 45.
    Tricky part :( Missingany write causes false reports. ● Libc ○ Solution: function wrappers ● Inline assembly ○ Openssl, libjpeg_turbo, etc ● JITs (e.g. V8)
  • 46.
    MSan Trophies ● 1200+bugs in Google server-size code ● 300+ in Chromium ● 30+ in clang ● hundreds of bugs elsewhere
  • 47.
  • 48.
    Faster ● Use hardwarefeatures ○ Or even create them (!) ● Static analysis: eliminate redundant checks ○ Many attempts were made; not trivial! ○ How to test it??
  • 49.
    More bugs ● Instrumentassembler & binaries ○ SyzyASAN: instruments binaries statically, Win32 ● Instrument JIT-ed code & JIT’s heap ● More types of bugs ○ Intra-object overflows ○ Annotations in STL, e.g. std::vector<> ● Other languages (e.g. races in Java)
  • 50.
    More environments ● MicrosoftWindows ● Mobile, embedded ● OS Kernel (Linux and others)
  • 51.
  • 52.
    ● AddressSanitizer (memorycorruption) ○ Linux, FreeBSD, OSX, CrOS, Android, iOS ○ i386, x86_64, ARM, PowerPC ○ WIP: Windows, *BSD (?) ○ Clang 3.1+ and GCC 4.8+ ● ThreadSanitizer (data races) ○ A "must use" if you have threads (C++, Go) ○ Only x86_64 Linux/FreeBSD; Clang 3.2+ and GCC 4.8+ ● MemorySanitizer (uses of uninitialized data) ○ Only x86_64 Linux; Clang 3.3 ○ WIP: MIPS64, FreeBSD Supported platforms
  • 53.
    ASan/MSan vs Valgrind(Memcheck) Valgrind ASan MSan Heap out-of-bounds YES YES NO Stack out-of-bounds NO YES NO Global out-of-bounds NO YES NO Use-after-free YES YES NO Use-after-return NO Sometimes NO Uninitialized reads YES NO YES CPU Overhead 10x-300x 1.5x-3x 3x
  • 54.
    ● Slowdowns willadd up ○ Bad for interactive or network apps ● Memory overheads will multiply ○ ASan redzone vs TSan/MSan large shadow ● Not trivial to implement Why not a single tool?