Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Memory sanitizer

1.912 visualizaciones

Publicado el

Publicado en: Tecnología
  • Sé el primero en comentar

Memory sanitizer

  1. 1. MemorySanitizer: fast detector of uninitialized memory use in C++ 2015/7/8 光成滋生
  2. 2. C/C++の未初期化メモリ実行時チェックツール http://research.google.com/pubs/pub43308.html の紹介 動作速度のコストは2.5x, メモリ使用量は2x程度 Clangに組み込まれていて-fsanitize=memoryで利用可能 未初期化メモリ(UUM : Use of Uninitialized Memory)の トラッキングも可能 実際にGoogleのたくさんの開発で利用されている 2/11 MemorySanitizer(以下MSan)
  3. 3. valgrind(Memcheck) UUM、ヒープオーバーフロー、free後の利用の検出 1byteに2bitの情報 addressable+init, not addr, addr+uninit, addr+partially init false positiveが0に近い 20x遅い(マルチスレッドでもっと遅い) Dr. Memory Memcheckの2xほど マルチスレッドでちょっとfalse positive Intel Inspector XE 遅い 3/11 Related work
  4. 4. 各1bitに1bit割り当てる(0:init/defined, 1:not) Shadow = App & (~0x4000|032) Originはトラッキングのときに使う どちらもMAP_NORESERVEをつける(Swap対象としない) 4/11 Shadow memory Application Origin Shadow Protected 0x0000|032 0x2000|032 0x4000|032 0x6000|032 0x7fff|132
  5. 5. UM(未初期化メモリ)は伝達する C++11では未初期化objectのlvalueからrvalueへの変 換は未定義だった C++14でindeterminate valueに緩和される struct A { char x; int y; };を8byteのmemcpyに最適化さ れてもエラーを出さないように UMにしたがって条件分岐、システムコールの呼び出 し、ポインタdereferenceしたときにエラーを出力 5/11 Shadow propagation
  6. 6. false positiveを出さない方針 その条件の元でできるだけfalse negativeを減らす 記号 : A = B op C(オリジナル), A', B', C':shadow 6/11 Shadow propagation rule 命令 ルール A = load P check P', load (P & shadowMask) *P = A check P', *(P & shadowMask) = A' A = const A' = 0 A = undef A' = 0xff A = B & C A' = (B'&C')|(B&C')|(B'&C) A = B | C A' = (B'&C')|(~B&C')|(B'&~C) A = B ^ C A' = B' | C' A = B << C A' = (sign extend(C'!=0))|(B'<<C)
  7. 7. A = B * (C * (1 << D)) A' = B' << Dで代用(一般はA' = B'| C') bitwiseにやってるとfalse positiveになる例 clangはこれを *(unsigned char*)s > 7と最適化する X : unsigned, X':対応するshadowのとき Xのとり得る範囲は[VMin(X, X'), VMax(X, X')] VMin(X, X') = X & (~X') VMax(X, X') = X | X' 正確だがベンチマークで50%の速度低下 7/11 複雑なパターン(1/2) struct S { int a:3; int b:5; }; bool f(S* s) { return s->b; }
  8. 8. 等号比較 A = B == Cを D = B ^ C, A = D == 0に変換 D' = B'|C', A'=(!(D & ~D')) && (D' != 0) 条件演算子 A = B ? C : D BがundefでもCとDが同じでdefならAはdefになる A' = B' ? ((C ^ D) | C' | D') : (B ? C' : D') 8/11 複雑なパターン(2/2)
  9. 9. vector instruction 同じ数だけ並べる thread safety global lockは遅いので別のやりかたで CAS, RMWは以前の値は全てinitializedと仮定 function calls va_listの扱いが大変 run-time library 300ほどの関数をintercept 9/11 その他
  10. 10. valgrindの10倍ぐらい速い 10/11 performance
  11. 11. 未初期化参照が分かってもそれがどこにあった か分からないと辛い 源流を保持する 11/11 origin tracking #include <stdio.h> int arr[2]; void shift() { arr[1] = arr[0]; } void push(int *p) { shift(); arr[0] = *p; } int pop() { int x = arr[1]; shift(); return x; } void func1() { int local_var; push(&local_var); } int main() { func1(); shift(); return pop(); } clang-3.5 -fsanitize-memory-track-origins=2 -g -fsanitize=memory t.c && ./a.out ==22068== WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x7f87ee79de13 (/home/shigeo/a.out+0x8ee13) #1 0x7f87ed600ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4) #2 0x7f87ee79d7bc (/home/shigeo/a.out+0x8e7bc) ... Uninitialized value was created by an allocation of 'local_var' in the stack frame of function 'func1' #0 0x7f87ee79dce0 (/home/shigeo/a.out+0x8ece0) SUMMARY: MemorySanitizer: use-of-uninitialized-value ??:0 ?? ちなみにgcc t.c -Wall –Wextraでは警告は何もでない。 % valgrind --track-origins=yes ./a.out ==22149== Syscall param exit_group(status) contains uninitialised byte(s) ==22149== at 0x4EF8309: _Exit (_exit.c:32) ==22149== by 0x4E7321A: __run_exit_handlers (exit.c:97) ==22149== by 0x4E732A4: exit (exit.c:104) ==22149== by 0x4E58ECB: (below main) (libc-start.c:321) ==22149== Uninitialised value was created by a stack allocation ==22149== at 0x400560: func1 (t.c:13)

×