test%case(reduc-on(( forccompilerbugs(( -...

48
TestCase Reduc-on for C Compiler Bugs John Regehr, Yang Chen, Pascal Cuoq, Eric Eide, Chucky Ellison, Xuejun Yang

Upload: others

Post on 12-Aug-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

Test-­‐Case  Reduc-on    for  C  Compiler  Bugs    

John  Regehr,  Yang  Chen,  Pascal  Cuoq,    Eric  Eide,  Chucky  Ellison,  Xuejun  Yang  

Page 2: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

2  

Background:  Csmith  [PLDI  2011]  

0

100

200

300

400

500

Jan 2010 Jan 2011 Jan 2012

C c

ompi

ler b

ugs

repo

rted

Page 3: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

•  Csmith’s  bug-­‐finding  power  is  maximized  when  programs  are  ~80  KB  – But  80  KB  test  cases  make  bad  bug  reports  

•  Automated  test  case  reduc-on  is  needed  

3  

Page 4: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

     template<  class  A0  ,  class  A1>  __aYribute__((always_inline))  typename  boost::dispatch::meta::call<tag::shi\_right_(  A0  const&  ,  A1  const&  )>::type  shi\_right  (  A0  const&  a0  ,  A1  const&  a1  )  {  typename  boost::dispatch::make_functor<tag::shi\_right_,  A0>::type  callee;  return  callee(  a0  ,  a1);;  }      template<  class  A0  ,  class  A1>  __aYribute__((always_inline))  typename  boost::dispatch::meta::call<tag::shi\_right_(  A0  const&  ,  A1  const&  )>::type  shr  (  A0  const&  a0  ,  A1  const&  a1  )  {  typename  boost::dispatch::make_functor<tag::shi\_right_,  A0>::type  callee;  return  callee(  a0  ,  a1);;  }  }  }  #  5  "/home/gaunard/build/may_alias/include/boost/simd/toolbox/operator/include/func-ons/shi\_right.hpp"  2  #  1  "/home/gaunard/dev/may_alias/modules/boost/simd/operator/include/boost/simd/toolbox/operator/func-ons/scalar/shi\_right.hpp"  1  #  14  "/home/gaunard/dev/may_alias/modules/boost/simd/operator/include/boost/simd/toolbox/operator/func-ons/scalar/shi\_right.hpp"  namespace  boost  {  namespace  simd  {  namespace  ext  {    }  }  }  namespace  boost  {  namespace  dispatch  {  namespace  meta  {  template<  class  A0  ,  class  A1>  __aYribute__((always_inline))  boost  ::  simd  ::  ext  ::  implement<  boost::simd::tag::shi\_right_(  scalar_<  floa-ng_<A0>  >  ,  scalar_<  integer_<A1>  >)  ,  tag::cpu_  >  dispatching(  boost::simd::tag::shi\_right_,  tag::cpu_  ,  scalar_<  floa-ng_<A0>  >  const  ,  scalar_<  integer_<A1>  >  const  ,  adl_helper  =  adl_helper()  )  {  boost  ::  simd  ::  ext  ::  implement<  boost::simd::tag::shi\_right_(  scalar_<  floa-ng_<A0>  >  ,  scalar_<  integer_<A1>  >  )  ,  tag::cpu_  >  that;  return  that;  }  }  }  }  namespace  boost  {  namespace  simd  {  namespace  ext  {  template<  class  A0  ,  class  A1  ,  class  Dummy  >  struct  implement  <  boost::simd::tag::shi\_right_(  scalar_<  floa-ng_<A0>  >  ,  scalar_<  integer_<A1>  >  )  ,  tag::cpu_,  Dummy  >      {          typedef  A0  result_type;          inline  result_type  operator()(  A0  const&  a0  ,  A1  const&  a1  )  const          {              typedef  typename  dispatch::meta::as_integer<A0,  unsigned>::type  itype;              return  bitwise_cast<result_type>(shi\_right(bitwise_cast<itype>(a0),a1));          }      };  }  }  }  namespace  boost  {  namespace  simd  {  namespace  ext{      }  }  }  namespace  boost  {  namespace  dispatch  {  namespace  meta  {  template<  class  A0  ,  class  A1>  __aYribute__((always_inline))  boost  ::  simd  ::  ext  ::  implement<  boost::simd::tag::shi\_right_(  scalar_<  integer_<A0>  >  ,  scalar_<  integer_<A1>  >)  ,  tag::cpu_  >  dispatching(  boost::simd::tag::shi\_right_,  tag::cpu_  ,  scalar_<  integer_<A0>  >  const  ,  scalar_<  integer_<A1>  >  const  ,  adl_helper  =  adl_helper()  )  {  boost  ::  simd  ::  ext  ::  implement<  boost::simd::tag::shi\_right_(  scalar_<  integer_<A0>  >  ,  scalar_<  integer_<A1>  >  )  ,  tag::cpu_  >  that;  return  that;  }  }  }  }  namespace  boost  {  namespace  simd  {  namespace  ext  {  template<  class  A0  ,  class  A1  ,  class  Dummy  >  struct  implement  <  boost::simd::tag::shi\_right_(  scalar_<  integer_<A0>  >  ,  scalar_<  integer_<A1>  >  )  ,  tag::cpu_,  Dummy  >      {          typedef  A0  result_type;          inline  result_type  operator()(  A0  const&  a0  ,  A1  const&  a1  )  const  {  return  a0  >>  a1;  }      };  }  }  }  #  6  "/home/gaunard/build/may_alias/include/boost/simd/toolbox/operator/include/func-ons/shi\_right.hpp"  2  #  1  "/home/gaunard/dev/may_alias/modules/boost/simd/operator/include/boost/simd/toolbox/operator/func-ons/simd/common/shi\_right.hpp"  1  #  20  "/home/gaunard/dev/may_alias/modules/boost/simd/operator/include/boost/simd/toolbox/operator/func-ons/simd/common/shi\_right.hpp"  namespace  boost  {  namespace  simd  {  namespace  ext  {      

4  

From  GCC  PR  50800:  “Testcase  is  [here]  (couldn't  aYach  it  due  to  bugzilla  size  restric-ons)”  

Next  comment:  “That  you  couldn't  aYach  it  should  tell  you  something…”  Next  comment:  

203  KB  reduced  test  case  aYached  

Page 5: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• Our  goal:  “Beau-ful”  test  cases  for  compiler  bugs  •  A  beau-ful  test  case  is:  – Small  – Obviously  well-­‐defined  

5  

Page 6: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

int  prinu  (const  char  *,  …);      char  f[]  =  {  -­‐9L  };      int  main  (void)  {        prinu  ("%d\n",  255  |  f[0]);    }    

6  

Intel  CC  12.0.5  for  x86-­‐64  is  wrong  at  “-­‐fast  -­‐ipo”  

Page 7: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

int  prinu  (const  char  *,  ...);    const  union  {      short  f1;      int  f2  :  13;  }  a  =  {  30155  };    int  main  (void)  {      prinu  ("%d\n",  a.f1);      prinu  ("%d\n",  a.f2);      return  0;  }  

7  

GCC  4.4.3  from  Ubuntu  10.04  LTS  for  x86-­‐64  is  wrong  at  -­‐O1  

Page 8: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

•  These  test  cases  were  produced  automa-cally  by  our  tool  – They  are  (I  claim)  preYy  close  to  minimal  – Previous  tools  can’t  produce  them  

8  

Page 9: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

•  Prior  art:  Delta  Debugging  – Greedy  search  for  smaller  test  cases  – Deletes  con-guous  chunks  of  the  input  

•  “Delta”  tool  from  UC  Berkeley  – Implements  Delta  Debugging  – Operates  at  line  granularity  – Commonly  used  by  compiler  developers  

9  

Page 10: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• Delta  has  problems  reducing  C/C++    – Delta  makes  localized  changes  – But  escaping  local  minima  requires  coordinated  changes  – Consequently,  Delta  gets  stuck  at  (large)  local  minima  

10  

Page 11: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• Our  goal:  “Beau-ful”  test  cases  for  compiler  bugs  •  A  beau-ful  test  case  is:  – Small  – Obviously  well-­‐defined  

• We  created  3  new  reducers  – I’ll  talk  about  one  of  them:  C-­‐Reduce  

11  

Page 12: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

C-­‐Reduce:  – Based  on  “generalized  Delta  Debugging”  – Transforma-ons  implemented  by  plugins  – Terminates  when  fixpoint  is  found  

12  

Page 13: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

13  

plugin  

current  test  case  

triggers  bug?  

yes  

no  

plugin  plugin  plugin  plugin  plugin  plugin  

Page 14: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; vint **get_depth (void) { return depth; } int fn1 (int inc) { int tmp = 0; if (get_depth() == &b) tmp = inc + **depth; return tmp; }

14  

GCC  4.3.0  for  x86-­‐64  crashes  at  -­‐O3  

Page 15: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; vint **get_depth (void) { return depth; } int fn1 (int inc) { int tmp = 0; if (get_depth() == &b) tmp = inc + **depth; return tmp; }

15  

Page 16: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; return tmp; }

16  

Page 17: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; return tmp; }

17  

Page 18: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; return tmp; }

18  

Page 19: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; void fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

19  

Page 20: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; void fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

20  

Page 21: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; void fn1 (int inc) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

21  

Page 22: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

22  

Page 23: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

23  

Page 24: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

typedef volatile int vint; vint **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

24  

Page 25: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

25  

Page 26: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

26  

Page 27: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) tmp = inc + **depth; }

27  

Page 28: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) **depth; }

28  

Page 29: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) **depth; }

29  

Page 30: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **depth; int *b; int inc; void fn1 ( ) { int tmp = 0; if (depth == &b) **depth; }

30  

Page 31: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **a ; int *b; int inc; void fn1 ( ) { int tmp = 0; if (a == &b) **a ; }

31  

Page 32: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **a ; int *b; int inc; void fn1 ( ) { int tmp = 0; if (a == &b) **a ; }

32  

Page 33: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

volatile int **a; int *b; void fn1() { if (a == &b) **a; }

33  

GCC  4.3.0  for  x86-­‐64  crashes  at  -­‐O3  

Page 34: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

65  plugins  including…  •  C-­‐specific  peephole  passes:  – 0xfeedbeefULL    è  1  – x  ^=  y  è  x  =  y    – (x  +  1)  è  x  +  1  – while  (…)  è  if  (…)  – x  ?  y  :  z  è  y  

•  Remove  chunks  of  text,  like  Delta  •  Some  non-­‐local  transforma-ons  

34  

Page 35: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

•  41  C/C++-­‐specific  plugins  including:  – Inline  a  func-on  call  – Scalar  replacement  of  aggregates  – Un-­‐nest  nested  func-on  calls  – Remove  dead  arguments  – Make  func-on  return  void  – Reduce  array  dimension  or  pointer  level  – Shorten  iden-fier  name  

•  Built  using  Clang  (LLVM  C  frontend)  35  

Page 36: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

36  

plugin  

current  test  case  

triggers  bug?  

yes  

no  

plugin  plugin  plugin  plugin  plugin  plugin  

Page 37: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• Our  goal:  “Beau-ful”  test  cases  for  compiler  bugs  •  A  beau-ful  test  case  is:  – Small  – Obviously  well-­‐defined  

37  

Page 38: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

#include  <iostream>  using  namespace  std;  int  r[3],  x[3],  y[3];  int  main()  {      int  xa=2,ya=5,xb=4,yb=2,n=3;      x[0]  =  3;  x[1]  =  5;  x[2]  =  1;      y[0]  =  1;  y[1]  =  3;  y[2]  =  3;      r[0]  =  2;  r[1]  =  1;  r[2]  =  2;      int  tcount  =  0;      for  (int  k=min(xa,xb);  k<=max(xa,xb);  k++)  {          bool  found1,found2  =  false;          for  (int  j=0;  j<n;  j++)  {              if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐ya)*(y[j]-­‐ya))<=r[j]*r[j])  {  found1  =  true;  }                if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐yb)*(y[j]-­‐yb))<=r[j]*r[j])  {  found2  =  true;  }              if  (found1  &&  found2)  break;          }          if  (!found1)  tcount++;  if  (!found2)  tcount++;        }      cout  <<  tcount  <<  endl;  return  0;    }  

38  

GCC  PR  51962  

Page 39: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

#include  <iostream>  using  namespace  std;  int  r[3],  x[3],  y[3];  int  main()  {      int  xa=2,ya=5,xb=4,yb=2,n=3;      x[0]  =  3;  x[1]  =  5;  x[2]  =  1;      y[0]  =  1;  y[1]  =  3;  y[2]  =  3;      r[0]  =  2;  r[1]  =  1;  r[2]  =  2;      int  tcount  =  0;      for  (int  k=min(xa,xb);  k<=max(xa,xb);  k++)  {          bool  found1,found2  =  false;          for  (int  j=0;  j<n;  j++)  {              if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐ya)*(y[j]-­‐ya))<=r[j]*r[j])  {  found1  =  true;  }                if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐yb)*(y[j]-­‐yb))<=r[j]*r[j])  {  found2  =  true;  }              if  (found1  &&  found2)  break;          }          if  (!found1)  tcount++;  if  (!found2)  tcount++;        }      cout  <<  tcount  <<  endl;  return  0;    }  

39  

GCC  PR  51962  

Bug  report  says:    “Compile  the  following  simple  code  without  -­‐O3,  and  run.    Now  compile  it  with  -­‐O3  op-on  (for  op-miza-on),  run  again.    Surprisingly  2  different  outputs  appear.”  

Page 40: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

#include  <iostream>  using  namespace  std;  int  r[3],  x[3],  y[3];  int  main()  {      int  xa=2,ya=5,xb=4,yb=2,n=3;      x[0]  =  3;  x[1]  =  5;  x[2]  =  1;      y[0]  =  1;  y[1]  =  3;  y[2]  =  3;      r[0]  =  2;  r[1]  =  1;  r[2]  =  2;      int  tcount  =  0;      for  (int  k=min(xa,xb);  k<=max(xa,xb);  k++)  {          bool  found1,found2  =  false;          for  (int  j=0;  j<n;  j++)  {              if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐ya)*(y[j]-­‐ya))<=r[j]*r[j])  {  found1  =  true;  }                if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐yb)*(y[j]-­‐yb))<=r[j]*r[j])  {  found2  =  true;  }              if  (found1  &&  found2)  break;          }          if  (!found1)  tcount++;  if  (!found2)  tcount++;        }      cout  <<  tcount  <<  endl;  return  0;    }  

40  

GCC  PR  51962  

Bug  report  says:    “Compile  the  following  simple  code  without  -­‐O3,  and  run.    Now  compile  it  with  -­‐O3  op-on  (for  op-miza-on),  run  again.    Surprisingly  2  different  outputs  appear.”  

GCC  developer  responds:    “You  do  not  ini-alise  found1.”    PR  51962  is  RESOLVED  INVALID    And  this  person  may  have  a  hard  -me  ge�ng  someone  to  read  his  next  bug  report  

Page 41: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

#include  <iostream>  using  namespace  std;  int  r[3],  x[3],  y[3];  int  main()  {      int  xa=2,ya=5,xb=4,yb=2,n=3;      x[0]  =  3;  x[1]  =  5;  x[2]  =  1;      y[0]  =  1;  y[1]  =  3;  y[2]  =  3;      r[0]  =  2;  r[1]  =  1;  r[2]  =  2;      int  tcount  =  0;      for  (int  k=min(xa,xb);  k<=max(xa,xb);  k++)  {          bool  found1,found2  =  false;          for  (int  j=0;  j<n;  j++)  {              if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐ya)*(y[j]-­‐ya))<=r[j]*r[j])  {  found1  =  true;  }                if  (((k-­‐x[j])*(k-­‐x[j])+(y[j]-­‐yb)*(y[j]-­‐yb))<=r[j]*r[j])  {  found2  =  true;  }              if  (found1  &&  found2)  break;          }          if  (!found1)  tcount++;  if  (!found2)  tcount++;        }      cout  <<  tcount  <<  endl;  return  0;    }  

41  

GCC  PR  51962  

Page 42: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

•  C99  has    – 191  kinds  of  undefined  behavior  – 52  kinds  of  unspecified  behavior  

•  Code  in  a  bug  report  must  not  execute  these  behaviors  – Though  some-mes  this  rule  may  be  relaxed  for  compiler  crash  bugs  

•  Test-­‐case  reducers  tend  to  introduce  these  behaviors  

42  

Page 43: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

Solu-ons:  1.   Teach  the  reducer  to  avoid  

undefined  behavior  –  Two  of  our  reducers  do  this  by  reusing  

Csmith’s  logic  –  But  they  can  only  reduce  Csmith  output  

2.   Call  an  external  validity  checker  –  C-­‐Reduce  does  this  

43  

Page 44: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

44  

plugin  

current  test  case  

triggers  bug?  

yes  

no  

plugin  plugin  plugin  plugin  plugin  plugin  

defined?  no  

yes  

Page 45: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• Dynamic  validity  checkers  for  C  – KCC:  executable  seman-cs  for  C99  – Frama-­‐C:  sta-c  analyzer  that  supports  an  interpreter  mode  

•  Result:  C-­‐Reduce’s  output  is  free  from  undefined  /  unspecified  behaviors  

45  

Page 46: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

Median  size  output  from  reducers:  

•  57  compiler-­‐crash  bugs  – Delta:    8,600  bytes  – C-­‐Reduce:        120  bytes  

•  41  wrong-­‐code  bugs  – Delta:      6,500  bytes  – C-­‐Reduce:        200  bytes  

• Median  reduc-on  -mes  are  <10  minutes  

46  

Page 47: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

• What  about  reducing  other  languages?  •  C++  is  preYy  easy  – We  recently  added  10  transforma-ons  • Collapse  namespace,  collapse  class  hierarchy,  …  

– Problem:  No  validity  checker  for  C++  

•  Should  be  preYy  easy  to  support  addi-onal  languages  

47  

Page 48: Test%Case(Reduc-on(( forCCompilerBugs(( - embed.cs.utah.eduembed.cs.utah.edu/creduce/pldi12_talk.pdf · 2 Background:(Csmith([PLDI(2011](0 100 200 300 400 500 Jan 2010 Jan 2011 Jan

C-­‐Reduce  is…  •  Almost  as  good  as  the  best  human  test  case  reducers  •  Extensible  via  plugins  • Open  source:  

hYp://embed.cs.utah.edu/creduce/  

•  Being  used  

48