C言語静的解析ツールと Ruby 1.9 trunk

3,477
-1

Published on

Ruby 1.9 trunk のソースコードに、既存の静的解析ツール(cppcheck, splint, BLAST, Frama-C)を適用した/適用しようと試みた実験の紹介です。

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,477
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
12
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

C言語静的解析ツールと Ruby 1.9 trunk

  1. 1. C Ruby 1.9 trunk @ikegami_ _
  2. 2. @ikegami_ _• 2003• 2003-2010 • Haskell • C • 10/27 - 11/10 2• Ruby/Mathematica, Ruby/Ming, RushCheck, Karatsuba
  3. 3. 1/2• C++ • BLAST • Frama-C • • • • CIL GCC
  4. 4. 2/2• ←• • cppcheck C C++ • Emacs + Flymake • Vim + • Vim + QuickFix + errormaker
  5. 5. Emacs + Flymake + cppcheck →
  6. 6. • • cppcheck • splint• • BLAST • Frama-C
  7. 7. • -Wall• • • ••
  8. 8. • division by zero • assert• unroll • assertion• if••• Call flow graph•
  9. 9. cppcheck• written in C++• C/C++ • • Tokenize • Run all checks - pattern matching of the tokens http://sourceforge.net/apps/trac/cppcheck/
  10. 10. cppcheck ruby• ruby-1.9 trunk revision 33685 (2011-11-09 ) • compile.c 77 files 2:01:02.55 • error 6 • compile.c 54:46.94s•
  11. 11. cppcheck Ruby 6[hash.c:2351]: (error) Memory leak: str[io.c:5264]: (error) fflush() called on input stream "stdin" mayresult in undefined behaviour[regcomp.c:5524]: (error) Memory leak: new_reg[vm_dump.c:831]: (error) Possible null pointer dereference: vm -otherwise it is redundant to check if vm is null at line 778[vm_dump.c:834]: (error) Possible null pointer dereference: vm -otherwise it is redundant to check if vm is null at line 778[vm_dump.c:835]: (error) Possible null pointer dereference: vm -otherwise it is redundant to check if vm is null at line 778
  12. 12. hash.c [hash.c:2351]: (error) Memory leak: str2351 } /* ruby_setenv */2303 str = malloc(len += strlen(value) + 2); str free 2287 #elif defined __sun Solaris
  13. 13. io.c [io.c:5264]: (error) fflush() called on input stream "stdin" may result in undefined behaviour5264 fflush(stdin); /* is it really needed? */Q. How can I flush pending input so that a userstypeahead isnt read at the next prompt? Willfflush(stdin) work?A. fflush is defined only for output streams. (omit) comp.lang.c FAQ list · Question 12.26a
  14. 14. splint• written in C•• annotation• cppcheck• • cont.c gc.c random.c thread_pthread.h http://www.splint.org/
  15. 15. splint hash.c• ruby-1.9 trunk revision 33685 (2011-11-09 )• 397• header • Solaris Solaris configure • cppcheck hash.c x86
  16. 16. splint regcomp.c• ruby-1.9 trunk revision 33685 (2011-11-09 )• 737 • •
  17. 17. splint regcomp.cregcomp.c:180:10: Only storage uslist->us->target(type struct _Node *) derived from released storage is notreleased (memory leak): uslist->us(omit) 176 static void 177 unset_addr_list_end(UnsetAddrList* uslist) 178 { 179 if (IS_NOT_NULL(uslist->us)) 180 xfree(uslist->us); 181 }
  18. 18. 176 static void177 unset_addr_list_end(UnsetAddrList* uslist)178 {179 if (IS_NOT_NULL(uslist->us))180 xfree(uslist->us); typedef struct {181 } int offset; struct _Node* target; } UnsetAddr; uslist->us->target typedef struct { free int num; int alloc; UnsetAddr* us; } UnsetAddrList;
  19. 19. 183 static int184 unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node)185 {186 UnsetAddr* p;187 int size;188189 if (uslist->num >= uslist->alloc) {190 size = uslist->alloc * 2;191 p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size);192 CHECK_NULL_RETURN_MEMERR(p);193 uslist->alloc = size;194 uslist->us = p;195 }196197 uslist->us[uslist->num].offset = offset;198 uslist->us[uslist->num].target = node;199 uslist->num++;200 return 0; ↑ free201 }
  20. 20. false positive
  21. 21. BLAST • with CIL OCaml • • assert() • • asserthttp://mtc.epfl.ch/software-tools/blast/index-epfl.php
  22. 22. escape
  23. 23. #include <assert.h>int watched; /* a global variable */void foo(int i) { watched = i; } ←void bar(){  int j;  foo(j);  assert(j == watched);  /* assert(j != watched); */} % gcc -E -I ${BLAST_INCLUDE} -main bar target.c % pblast.opt target.i -main bar :-)
  24. 24. #include <assert.h>int *watched;void foo(int *p) { watched = p; }void bar(){  int i, *j;  i = 1;  j = &i;  foo(j);  assert(j == watched);  /* assert(j != watched); */} % gcc -E -I ${BLAST_INCLUDE} -main bar target.c % pblast.opt target.i -main bar :-)
  25. 25. ruby 1.9 trunk• for while• if •• • •
  26. 26. Frama-C• with CIL OCaml•C • • • value plug-in ← • users plug-in http://frama-c.com/
  27. 27. division by zerovoid foo(int x, int y){ int z = x / y; /* y should not be zero */ return;}int main(int argc, char **argv){ int x = 1, y = 0; foo(x, y); return 0;}
  28. 28. Frama-C value plug-in% frama-c -val foo.c[value] Analyzing a complete application starting at mainfoo.c:3:[kernel] warning: division by zero: assert y ≢ 0;
  29. 29. division by zero • ruby trunk revision no. 33685 • bignum.c • 1044 ds[k] = (BDIGIT)(num / hbase); • util.c • • 331 n = (r - l + size) / size;Frama-C value plugin
  30. 30. Frama-C users plug-in• callee •
  31. 31. void foo(void) {}void bar(void) {foo();}int main(void){ bar(); return 0;} % frama-c -users foo.c [kernel] preprocessing with "gcc -C -E -I. foo.c" [users] ====== DISPLAYING USERS ====== bar: foo main: foo bar ====== END OF USERS ==========
  32. 32. ruby string.ccalleehttp://sovmoess.tumblr.com/post/12364993205/frama-c-ruby-1-9-string-c-callee @ikegami_ _
  33. 33. • • false positive • • CPU• annotation • annotation • Frama-C + jessie plug-in → Coq
  34. 34. •2 C • ruby-1.9 trunk revision 33685• cppcheck/splint • escape• BLAST/Frama-C •
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×