C言語静的解析ツールと Ruby 1.9 trunk
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 3,293 views

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

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

Statistics

Views

Total Views
3,293
Views on SlideShare
2,964
Embed Views
329

Actions

Likes
2
Downloads
6
Comments
0

6 Embeds 329

http://sovmoess.tumblr.com 321
http://www.hanrss.com 3
http://us-w1.rockmelt.com 2
http://paper.li 1
http://webcache.googleusercontent.com 1
http://www.google.co.jp 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • C Ruby 1.9 trunk @ikegami_ _
  • @ikegami_ _• 2003• 2003-2010 • Haskell • C • 10/27 - 11/10 2• Ruby/Mathematica, Ruby/Ming, RushCheck, Karatsuba
  • 1/2• C++ • BLAST • Frama-C • • • • CIL GCC
  • 2/2• ←• • cppcheck C C++ • Emacs + Flymake • Vim + • Vim + QuickFix + errormaker
  • Emacs + Flymake + cppcheck →
  • • • cppcheck • splint• • BLAST • Frama-C
  • • -Wall• • • ••
  • • division by zero • assert• unroll • assertion• if••• Call flow graph•
  • cppcheck• written in C++• C/C++ • • Tokenize • Run all checks - pattern matching of the tokens http://sourceforge.net/apps/trac/cppcheck/
  • 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•
  • 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
  • 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
  • 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
  • splint• written in C•• annotation• cppcheck• • cont.c gc.c random.c thread_pthread.h http://www.splint.org/
  • splint hash.c• ruby-1.9 trunk revision 33685 (2011-11-09 )• 397• header • Solaris Solaris configure • cppcheck hash.c x86
  • splint regcomp.c• ruby-1.9 trunk revision 33685 (2011-11-09 )• 737 • •
  • 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 }
  • 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;
  • 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 }
  • false positive
  • BLAST • with CIL OCaml • • assert() • • asserthttp://mtc.epfl.ch/software-tools/blast/index-epfl.php
  • escape
  • #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 :-)
  • #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 :-)
  • ruby 1.9 trunk• for while• if •• • •
  • Frama-C• with CIL OCaml•C • • • value plug-in ← • users plug-in http://frama-c.com/
  • 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;}
  • 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;
  • 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
  • Frama-C users plug-in• callee •
  • 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 ==========
  • ruby string.ccalleehttp://sovmoess.tumblr.com/post/12364993205/frama-c-ruby-1-9-string-c-callee @ikegami_ _
  • • • false positive • • CPU• annotation • annotation • Frama-C + jessie plug-in → Coq
  • •2 C • ruby-1.9 trunk revision 33685• cppcheck/splint • escape• BLAST/Frama-C •