1  /* Copyright (C) 2004, 2005  Free Software Foundation.
       2  
       3     Ensure builtin __memset_chk performs correctly.  */
       4  
       5  extern void abort (void);
       6  typedef __SIZE_TYPE__ size_t;
       7  extern size_t strlen(const char *);
       8  extern void *memcpy (void *, const void *, size_t);
       9  extern void *memset (void *, int, size_t);
      10  extern int memcmp (const void *, const void *, size_t);
      11  
      12  #include "chk.h"
      13  
      14  char buffer[32];
      15  int argc = 1;
      16  volatile size_t l1 = 1;  /* prevent constant propagation to happen when whole program assumptions are made.  */
      17  volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made.  */
      18  char *s4;
      19  
      20  void
      21  __attribute__((noinline))
      22  test1 (void)
      23  {
      24    memset_disallowed = 1;
      25    chk_calls = 0;
      26    memset (buffer, argc, 0);
      27    memset (buffer, argc, 1);
      28    memset (buffer, argc, 2);
      29    memset (buffer, argc, 3);
      30    memset (buffer, argc, 4);
      31    memset (buffer, argc, 5);
      32    memset (buffer, argc, 6);
      33    memset (buffer, argc, 7);
      34    memset (buffer, argc, 8);
      35    memset (buffer, argc, 9);
      36    memset (buffer, argc, 10);
      37    memset (buffer, argc, 11);
      38    memset (buffer, argc, 12);
      39    memset (buffer, argc, 13);
      40    memset (buffer, argc, 14);
      41    memset (buffer, argc, 15);
      42    memset (buffer, argc, 16);
      43    memset (buffer, argc, 17);
      44    memset_disallowed = 0;
      45    if (chk_calls)
      46      abort ();
      47  }
      48  
      49  /* Test whether compile time checking is done where it should
      50     and so is runtime object size checking.  */
      51  void
      52  __attribute__((noinline))
      53  test2 (void)
      54  {
      55    struct A { char buf1[10]; char buf2[10]; } a;
      56    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
      57    char buf3[20];
      58    int i;
      59    size_t l;
      60  
      61    /* The following calls should do runtime checking
      62       - length is not known, but destination is.  */
      63    chk_calls = 0;
      64    memset (a.buf1 + 2, 'a', l1);
      65    memset (r, '\0', l1 + 1);
      66    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
      67    memset (r, argc, l1 + 2);
      68    memset (r + 2, 'Q', l1);
      69    r = buf3;
      70    for (i = 0; i < 4; ++i)
      71      {
      72        if (i == l1 - 1)
      73  	r = &a.buf1[1];
      74        else if (i == l1)
      75  	r = &a.buf2[7];
      76        else if (i == l1 + 1)
      77  	r = &buf3[5];
      78        else if (i == l1 + 2)
      79  	r = &a.buf1[9];
      80      }
      81    memset (r, '\0', l1);
      82    if (chk_calls != 5)
      83      abort ();
      84  
      85    /* Following have known destination and known length,
      86       so if optimizing certainly shouldn't result in the checking
      87       variants.  */
      88    chk_calls = 0;
      89    memset (a.buf1 + 2, '\0', 1);
      90    memset (r, argc, 2);
      91    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
      92    memset (r, 'N', 3);
      93    r = buf3;
      94    l = 4;
      95    for (i = 0; i < 4; ++i)
      96      {
      97        if (i == l1 - 1)
      98  	r = &a.buf1[1], l = 2;
      99        else if (i == l1)
     100  	r = &a.buf2[7], l = 3;
     101        else if (i == l1 + 1)
     102  	r = &buf3[5], l = 4;
     103        else if (i == l1 + 2)
     104  	r = &a.buf1[9], l = 1;
     105      }
     106    memset (r, 'H', 1);
     107    /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
     108       is 4, so this doesn't need runtime checking.  */
     109    memset (&buf3[16], 'd', l);
     110    /* Neither length nor destination known.  Doesn't need runtime checking.  */
     111    memset (s4, 'a', l1);
     112    memset (s4 + 2, '\0', l1 + 2);
     113    /* Destination unknown.  */
     114    memset (s4 + 4, 'b', 2);
     115    memset (s4 + 6, '\0', 4);
     116    if (chk_calls)
     117      abort ();
     118    chk_calls = 0;
     119  }
     120  
     121  /* Test whether runtime and/or compile time checking catches
     122     buffer overflows.  */
     123  void
     124  __attribute__((noinline))
     125  test3 (void)
     126  {
     127    struct A { char buf1[10]; char buf2[10]; } a;
     128    char buf3[20];
     129  
     130    chk_fail_allowed = 1;
     131    /* Runtime checks.  */
     132    if (__builtin_setjmp (chk_fail_buf) == 0)
     133      {
     134        memset (&a.buf2[9], '\0', l1 + 1);
     135        abort ();
     136      }
     137    if (__builtin_setjmp (chk_fail_buf) == 0)
     138      {
     139        memset (&a.buf2[7], 'T', strlen (s3) + 1);
     140        abort ();
     141      }
     142    /* This should be detectable at compile time already.  */
     143    if (__builtin_setjmp (chk_fail_buf) == 0)
     144      {
     145        memset (&buf3[19], 'b', 2);
     146        abort ();
     147      }
     148    chk_fail_allowed = 0;
     149  }
     150  
     151  #ifndef MAX_OFFSET
     152  #define MAX_OFFSET (sizeof (long long))
     153  #endif
     154  
     155  #ifndef MAX_COPY
     156  #define MAX_COPY (10 * sizeof (long long))
     157  #define MAX_COPY2 15
     158  #else
     159  #define MAX_COPY2 MAX_COPY
     160  #endif
     161  
     162  #ifndef MAX_EXTRA
     163  #define MAX_EXTRA (sizeof (long long))
     164  #endif
     165  
     166  #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
     167  #define MAX_LENGTH2 (MAX_OFFSET + MAX_COPY2 + MAX_EXTRA)
     168  
     169  static union {
     170    char buf[MAX_LENGTH];
     171    long long align_int;
     172    long double align_fp;
     173  } u;
     174  
     175  char A = 'A';
     176  
     177  void
     178  __attribute__((noinline))
     179  test4 (void)
     180  {
     181    int off, len, i;
     182    char *p, *q;
     183  
     184    for (off = 0; off < MAX_OFFSET; off++)
     185      for (len = 1; len < MAX_COPY; len++)
     186        {
     187  	for (i = 0; i < MAX_LENGTH; i++)
     188  	  u.buf[i] = 'a';
     189  
     190  	p = memset (u.buf + off, '\0', len);
     191  	if (p != u.buf + off)
     192  	  abort ();
     193  
     194  	q = u.buf;
     195  	for (i = 0; i < off; i++, q++)
     196  	  if (*q != 'a')
     197  	    abort ();
     198  
     199  	for (i = 0; i < len; i++, q++)
     200  	  if (*q != '\0')
     201  	    abort ();
     202  
     203  	for (i = 0; i < MAX_EXTRA; i++, q++)
     204  	  if (*q != 'a')
     205  	    abort ();
     206  
     207  	p = memset (u.buf + off, A, len);
     208  	if (p != u.buf + off)
     209  	  abort ();
     210  
     211  	q = u.buf;
     212  	for (i = 0; i < off; i++, q++)
     213  	  if (*q != 'a')
     214  	    abort ();
     215  
     216  	for (i = 0; i < len; i++, q++)
     217  	  if (*q != 'A')
     218  	    abort ();
     219  
     220  	for (i = 0; i < MAX_EXTRA; i++, q++)
     221  	  if (*q != 'a')
     222  	    abort ();
     223  
     224  	p = memset (u.buf + off, 'B', len);
     225  	if (p != u.buf + off)
     226  	  abort ();
     227  
     228  	q = u.buf;
     229  	for (i = 0; i < off; i++, q++)
     230  	  if (*q != 'a')
     231  	    abort ();
     232  
     233  	for (i = 0; i < len; i++, q++)
     234  	  if (*q != 'B')
     235  	    abort ();
     236  
     237  	for (i = 0; i < MAX_EXTRA; i++, q++)
     238  	  if (*q != 'a')
     239  	    abort ();
     240        }
     241  }
     242  
     243  static union {
     244    char buf[MAX_LENGTH2];
     245    long long align_int;
     246    long double align_fp;
     247  } u2;
     248  
     249  void reset ()
     250  {
     251    int i;
     252  
     253    for (i = 0; i < MAX_LENGTH2; i++)
     254      u2.buf[i] = 'a';
     255  }
     256  
     257  void check (int off, int len, int ch)
     258  {
     259    char *q;
     260    int i;
     261  
     262    q = u2.buf;
     263    for (i = 0; i < off; i++, q++)
     264      if (*q != 'a')
     265        abort ();
     266  
     267    for (i = 0; i < len; i++, q++)
     268      if (*q != ch)
     269        abort ();
     270  
     271    for (i = 0; i < MAX_EXTRA; i++, q++)
     272      if (*q != 'a')
     273        abort ();
     274  }
     275  
     276  void
     277  __attribute__((noinline))
     278  test5 (void)
     279  {
     280    int off;
     281    char *p;
     282  
     283    /* len == 1 */
     284    for (off = 0; off < MAX_OFFSET; off++)
     285      {
     286        reset ();
     287  
     288        p = memset (u2.buf + off, '\0', 1);
     289        if (p != u2.buf + off) abort ();
     290        check (off, 1, '\0');
     291  
     292        p = memset (u2.buf + off, A, 1);
     293        if (p != u2.buf + off) abort ();
     294        check (off, 1, 'A');
     295  
     296        p = memset (u2.buf + off, 'B', 1);
     297        if (p != u2.buf + off) abort ();
     298        check (off, 1, 'B');
     299      }
     300  
     301    /* len == 2 */
     302    for (off = 0; off < MAX_OFFSET; off++)
     303      {
     304        reset ();
     305  
     306        p = memset (u2.buf + off, '\0', 2);
     307        if (p != u2.buf + off) abort ();
     308        check (off, 2, '\0');
     309  
     310        p = memset (u2.buf + off, A, 2);
     311        if (p != u2.buf + off) abort ();
     312        check (off, 2, 'A');
     313  
     314        p = memset (u2.buf + off, 'B', 2);
     315        if (p != u2.buf + off) abort ();
     316        check (off, 2, 'B');
     317      }
     318  
     319    /* len == 3 */
     320    for (off = 0; off < MAX_OFFSET; off++)
     321      {
     322        reset ();
     323  
     324        p = memset (u2.buf + off, '\0', 3);
     325        if (p != u2.buf + off) abort ();
     326        check (off, 3, '\0');
     327  
     328        p = memset (u2.buf + off, A, 3);
     329        if (p != u2.buf + off) abort ();
     330        check (off, 3, 'A');
     331  
     332        p = memset (u2.buf + off, 'B', 3);
     333        if (p != u2.buf + off) abort ();
     334        check (off, 3, 'B');
     335      }
     336  
     337    /* len == 4 */
     338    for (off = 0; off < MAX_OFFSET; off++)
     339      {
     340        reset ();
     341  
     342        p = memset (u2.buf + off, '\0', 4);
     343        if (p != u2.buf + off) abort ();
     344        check (off, 4, '\0');
     345  
     346        p = memset (u2.buf + off, A, 4);
     347        if (p != u2.buf + off) abort ();
     348        check (off, 4, 'A');
     349  
     350        p = memset (u2.buf + off, 'B', 4);
     351        if (p != u2.buf + off) abort ();
     352        check (off, 4, 'B');
     353      }
     354  
     355    /* len == 5 */
     356    for (off = 0; off < MAX_OFFSET; off++)
     357      {
     358        reset ();
     359  
     360        p = memset (u2.buf + off, '\0', 5);
     361        if (p != u2.buf + off) abort ();
     362        check (off, 5, '\0');
     363  
     364        p = memset (u2.buf + off, A, 5);
     365        if (p != u2.buf + off) abort ();
     366        check (off, 5, 'A');
     367  
     368        p = memset (u2.buf + off, 'B', 5);
     369        if (p != u2.buf + off) abort ();
     370        check (off, 5, 'B');
     371      }
     372  
     373    /* len == 6 */
     374    for (off = 0; off < MAX_OFFSET; off++)
     375      {
     376        reset ();
     377  
     378        p = memset (u2.buf + off, '\0', 6);
     379        if (p != u2.buf + off) abort ();
     380        check (off, 6, '\0');
     381  
     382        p = memset (u2.buf + off, A, 6);
     383        if (p != u2.buf + off) abort ();
     384        check (off, 6, 'A');
     385  
     386        p = memset (u2.buf + off, 'B', 6);
     387        if (p != u2.buf + off) abort ();
     388        check (off, 6, 'B');
     389      }
     390  
     391    /* len == 7 */
     392    for (off = 0; off < MAX_OFFSET; off++)
     393      {
     394        reset ();
     395  
     396        p = memset (u2.buf + off, '\0', 7);
     397        if (p != u2.buf + off) abort ();
     398        check (off, 7, '\0');
     399  
     400        p = memset (u2.buf + off, A, 7);
     401        if (p != u2.buf + off) abort ();
     402        check (off, 7, 'A');
     403  
     404        p = memset (u2.buf + off, 'B', 7);
     405        if (p != u2.buf + off) abort ();
     406        check (off, 7, 'B');
     407      }
     408  
     409    /* len == 8 */
     410    for (off = 0; off < MAX_OFFSET; off++)
     411      {
     412        reset ();
     413  
     414        p = memset (u2.buf + off, '\0', 8);
     415        if (p != u2.buf + off) abort ();
     416        check (off, 8, '\0');
     417  
     418        p = memset (u2.buf + off, A, 8);
     419        if (p != u2.buf + off) abort ();
     420        check (off, 8, 'A');
     421  
     422        p = memset (u2.buf + off, 'B', 8);
     423        if (p != u2.buf + off) abort ();
     424        check (off, 8, 'B');
     425      }
     426  
     427    /* len == 9 */
     428    for (off = 0; off < MAX_OFFSET; off++)
     429      {
     430        reset ();
     431  
     432        p = memset (u2.buf + off, '\0', 9);
     433        if (p != u2.buf + off) abort ();
     434        check (off, 9, '\0');
     435  
     436        p = memset (u2.buf + off, A, 9);
     437        if (p != u2.buf + off) abort ();
     438        check (off, 9, 'A');
     439  
     440        p = memset (u2.buf + off, 'B', 9);
     441        if (p != u2.buf + off) abort ();
     442        check (off, 9, 'B');
     443      }
     444  
     445    /* len == 10 */
     446    for (off = 0; off < MAX_OFFSET; off++)
     447      {
     448        reset ();
     449  
     450        p = memset (u2.buf + off, '\0', 10);
     451        if (p != u2.buf + off) abort ();
     452        check (off, 10, '\0');
     453  
     454        p = memset (u2.buf + off, A, 10);
     455        if (p != u2.buf + off) abort ();
     456        check (off, 10, 'A');
     457  
     458        p = memset (u2.buf + off, 'B', 10);
     459        if (p != u2.buf + off) abort ();
     460        check (off, 10, 'B');
     461      }
     462  
     463    /* len == 11 */
     464    for (off = 0; off < MAX_OFFSET; off++)
     465      {
     466        reset ();
     467  
     468        p = memset (u2.buf + off, '\0', 11);
     469        if (p != u2.buf + off) abort ();
     470        check (off, 11, '\0');
     471  
     472        p = memset (u2.buf + off, A, 11);
     473        if (p != u2.buf + off) abort ();
     474        check (off, 11, 'A');
     475  
     476        p = memset (u2.buf + off, 'B', 11);
     477        if (p != u2.buf + off) abort ();
     478        check (off, 11, 'B');
     479      }
     480  
     481    /* len == 12 */
     482    for (off = 0; off < MAX_OFFSET; off++)
     483      {
     484        reset ();
     485  
     486        p = memset (u2.buf + off, '\0', 12);
     487        if (p != u2.buf + off) abort ();
     488        check (off, 12, '\0');
     489  
     490        p = memset (u2.buf + off, A, 12);
     491        if (p != u2.buf + off) abort ();
     492        check (off, 12, 'A');
     493  
     494        p = memset (u2.buf + off, 'B', 12);
     495        if (p != u2.buf + off) abort ();
     496        check (off, 12, 'B');
     497      }
     498  
     499    /* len == 13 */
     500    for (off = 0; off < MAX_OFFSET; off++)
     501      {
     502        reset ();
     503  
     504        p = memset (u2.buf + off, '\0', 13);
     505        if (p != u2.buf + off) abort ();
     506        check (off, 13, '\0');
     507  
     508        p = memset (u2.buf + off, A, 13);
     509        if (p != u2.buf + off) abort ();
     510        check (off, 13, 'A');
     511  
     512        p = memset (u2.buf + off, 'B', 13);
     513        if (p != u2.buf + off) abort ();
     514        check (off, 13, 'B');
     515      }
     516  
     517    /* len == 14 */
     518    for (off = 0; off < MAX_OFFSET; off++)
     519      {
     520        reset ();
     521  
     522        p = memset (u2.buf + off, '\0', 14);
     523        if (p != u2.buf + off) abort ();
     524        check (off, 14, '\0');
     525  
     526        p = memset (u2.buf + off, A, 14);
     527        if (p != u2.buf + off) abort ();
     528        check (off, 14, 'A');
     529  
     530        p = memset (u2.buf + off, 'B', 14);
     531        if (p != u2.buf + off) abort ();
     532        check (off, 14, 'B');
     533      }
     534  
     535    /* len == 15 */
     536    for (off = 0; off < MAX_OFFSET; off++)
     537      {
     538        reset ();
     539  
     540        p = memset (u2.buf + off, '\0', 15);
     541        if (p != u2.buf + off) abort ();
     542        check (off, 15, '\0');
     543  
     544        p = memset (u2.buf + off, A, 15);
     545        if (p != u2.buf + off) abort ();
     546        check (off, 15, 'A');
     547  
     548        p = memset (u2.buf + off, 'B', 15);
     549        if (p != u2.buf + off) abort ();
     550        check (off, 15, 'B');
     551      }
     552  }
     553  
     554  void
     555  __attribute__((noinline))
     556  test6 (void)
     557  {
     558    int len;
     559    char *p;
     560  
     561    /* off == 0 */
     562    for (len = 0; len < MAX_COPY2; len++)
     563      {
     564        reset ();
     565  
     566        p = memset (u2.buf, '\0', len);
     567        if (p != u2.buf) abort ();
     568        check (0, len, '\0');
     569  
     570        p = memset (u2.buf, A, len);
     571        if (p != u2.buf) abort ();
     572        check (0, len, 'A');
     573  
     574        p = memset (u2.buf, 'B', len);
     575        if (p != u2.buf) abort ();
     576        check (0, len, 'B');
     577      }
     578  
     579    /* off == 1 */
     580    for (len = 0; len < MAX_COPY2; len++)
     581      {
     582        reset ();
     583  
     584        p = memset (u2.buf+1, '\0', len);
     585        if (p != u2.buf+1) abort ();
     586        check (1, len, '\0');
     587  
     588        p = memset (u2.buf+1, A, len);
     589        if (p != u2.buf+1) abort ();
     590        check (1, len, 'A');
     591  
     592        p = memset (u2.buf+1, 'B', len);
     593        if (p != u2.buf+1) abort ();
     594        check (1, len, 'B');
     595      }
     596  
     597    /* off == 2 */
     598    for (len = 0; len < MAX_COPY2; len++)
     599      {
     600        reset ();
     601  
     602        p = memset (u2.buf+2, '\0', len);
     603        if (p != u2.buf+2) abort ();
     604        check (2, len, '\0');
     605  
     606        p = memset (u2.buf+2, A, len);
     607        if (p != u2.buf+2) abort ();
     608        check (2, len, 'A');
     609  
     610        p = memset (u2.buf+2, 'B', len);
     611        if (p != u2.buf+2) abort ();
     612        check (2, len, 'B');
     613      }
     614  
     615    /* off == 3 */
     616    for (len = 0; len < MAX_COPY2; len++)
     617      {
     618        reset ();
     619  
     620        p = memset (u2.buf+3, '\0', len);
     621        if (p != u2.buf+3) abort ();
     622        check (3, len, '\0');
     623  
     624        p = memset (u2.buf+3, A, len);
     625        if (p != u2.buf+3) abort ();
     626        check (3, len, 'A');
     627  
     628        p = memset (u2.buf+3, 'B', len);
     629        if (p != u2.buf+3) abort ();
     630        check (3, len, 'B');
     631      }
     632  
     633    /* off == 4 */
     634    for (len = 0; len < MAX_COPY2; len++)
     635      {
     636        reset ();
     637  
     638        p = memset (u2.buf+4, '\0', len);
     639        if (p != u2.buf+4) abort ();
     640        check (4, len, '\0');
     641  
     642        p = memset (u2.buf+4, A, len);
     643        if (p != u2.buf+4) abort ();
     644        check (4, len, 'A');
     645  
     646        p = memset (u2.buf+4, 'B', len);
     647        if (p != u2.buf+4) abort ();
     648        check (4, len, 'B');
     649      }
     650  
     651    /* off == 5 */
     652    for (len = 0; len < MAX_COPY2; len++)
     653      {
     654        reset ();
     655  
     656        p = memset (u2.buf+5, '\0', len);
     657        if (p != u2.buf+5) abort ();
     658        check (5, len, '\0');
     659  
     660        p = memset (u2.buf+5, A, len);
     661        if (p != u2.buf+5) abort ();
     662        check (5, len, 'A');
     663  
     664        p = memset (u2.buf+5, 'B', len);
     665        if (p != u2.buf+5) abort ();
     666        check (5, len, 'B');
     667      }
     668  
     669    /* off == 6 */
     670    for (len = 0; len < MAX_COPY2; len++)
     671      {
     672        reset ();
     673  
     674        p = memset (u2.buf+6, '\0', len);
     675        if (p != u2.buf+6) abort ();
     676        check (6, len, '\0');
     677  
     678        p = memset (u2.buf+6, A, len);
     679        if (p != u2.buf+6) abort ();
     680        check (6, len, 'A');
     681  
     682        p = memset (u2.buf+6, 'B', len);
     683        if (p != u2.buf+6) abort ();
     684        check (6, len, 'B');
     685      }
     686  
     687    /* off == 7 */
     688    for (len = 0; len < MAX_COPY2; len++)
     689      {
     690        reset ();
     691  
     692        p = memset (u2.buf+7, '\0', len);
     693        if (p != u2.buf+7) abort ();
     694        check (7, len, '\0');
     695  
     696        p = memset (u2.buf+7, A, len);
     697        if (p != u2.buf+7) abort ();
     698        check (7, len, 'A');
     699  
     700        p = memset (u2.buf+7, 'B', len);
     701        if (p != u2.buf+7) abort ();
     702        check (7, len, 'B');
     703      }
     704  }
     705  
     706  void
     707  main_test (void)
     708  {
     709  #ifndef __OPTIMIZE__
     710    /* Object size checking is only intended for -O[s123].  */
     711    return;
     712  #endif
     713    __asm ("" : "=r" (l1) : "0" (l1));
     714    s4 = buffer;
     715    test1 ();
     716    test2 ();
     717    test3 ();
     718    test4 ();
     719    test5 ();
     720    test6 ();
     721  }