modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.c (about)

     1  /* Copyright (C) 2004, 2005  Free Software Foundation.
     2  
     3     Ensure builtin __memcpy_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 int memcmp (const void *, const void *, size_t);
    10  
    11  #include "chk.h"
    12  
    13  const char s1[] = "123";
    14  char p[32] = "";
    15  volatile char *s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made.  */
    16  volatile char *s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made.  */
    17  volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made.  */
    18  
    19  void
    20  __attribute__((noinline))
    21  test1 (void)
    22  {
    23    int i;
    24  
    25  #if defined __i386__ || defined __x86_64__
    26    /* The functions below might not be optimized into direct stores on all
    27       arches.  It depends on how many instructions would be generated and
    28       what limits the architecture chooses in STORE_BY_PIECES_P.  */
    29    memcpy_disallowed = 1;
    30  #endif
    31  
    32    /* All the memcpy calls in this routine except last have fixed length, so
    33       object size checking should be done at compile time if optimizing.  */
    34    chk_calls = 0;
    35  
    36    if (memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
    37      abort ();
    38    if (memcpy (p + 16, "VWX" + 1, 2) != p + 16
    39        || memcmp (p + 16, "WX\0\0", 5))
    40      abort ();
    41    if (memcpy (p + 1, "", 1) != p + 1 || memcmp (p, "A\0CDE", 6))
    42      abort ();
    43    if (memcpy (p + 3, "FGHI", 4) != p + 3 || memcmp (p, "A\0CFGHI", 8))
    44      abort ();
    45  
    46    i = 8;
    47    memcpy (p + 20, "qrstu", 6);
    48    memcpy (p + 25, "QRSTU", 6);
    49    if (memcpy (p + 25 + 1, s1, 3) != p + 25 + 1
    50        || memcmp (p + 25, "Q123U", 6))
    51      abort ();
    52  
    53    if (memcpy (memcpy (p, "abcdEFG", 4) + 4, "efg", 4) != p + 4
    54        || memcmp (p, "abcdefg", 8))
    55      abort();
    56  
    57    /* Test at least one instance of the __builtin_ style.  We do this
    58       to ensure that it works and that the prototype is correct.  */
    59    if (__builtin_memcpy (p, "ABCDE", 6) != p || memcmp (p, "ABCDE", 6))
    60      abort ();
    61  
    62    memcpy (p + 5, s3, 1);
    63    if (memcmp (p, "ABCDEFg", 8))
    64      abort ();
    65  
    66    memcpy_disallowed = 0;
    67    if (chk_calls)
    68      abort ();
    69    chk_calls = 0;
    70  
    71    memcpy (p + 6, s1 + 1, l1);
    72    if (memcmp (p, "ABCDEF2", 8))
    73      abort ();
    74  
    75    /* The above memcpy copies into an object with known size, but
    76       unknown length, so it should be a __memcpy_chk call.  */
    77    if (chk_calls != 1)
    78      abort ();
    79  }
    80  
    81  long buf1[64];
    82  char *buf2 = (char *) (buf1 + 32);
    83  long buf5[20];
    84  char buf7[20];
    85  
    86  void
    87  __attribute__((noinline))
    88  test2_sub (long *buf3, char *buf4, char *buf6, int n)
    89  {
    90    int i = 0;
    91  
    92    /* All the memcpy/__builtin_memcpy/__builtin___memcpy_chk
    93       calls in this routine are either fixed length, or have
    94       side-effects in __builtin_object_size arguments, or
    95       dst doesn't point into a known object.  */
    96    chk_calls = 0;
    97  
    98    /* These should probably be handled by store_by_pieces on most arches.  */
    99    if (memcpy (buf1, "ABCDEFGHI", 9) != (char *) buf1
   100        || memcmp (buf1, "ABCDEFGHI\0", 11))
   101      abort ();
   102  
   103    if (memcpy (buf1, "abcdefghijklmnopq", 17) != (char *) buf1
   104        || memcmp (buf1, "abcdefghijklmnopq\0", 19))
   105      abort ();
   106  
   107    if (__builtin_memcpy (buf3, "ABCDEF", 6) != (char *) buf1
   108        || memcmp (buf1, "ABCDEFghijklmnopq\0", 19))
   109      abort ();
   110  
   111    if (__builtin_memcpy (buf3, "a", 1) != (char *) buf1
   112        || memcmp (buf1, "aBCDEFghijklmnopq\0", 19))
   113      abort ();
   114  
   115    if (memcpy ((char *) buf3 + 2, "bcd" + ++i, 2) != (char *) buf1 + 2
   116        || memcmp (buf1, "aBcdEFghijklmnopq\0", 19)
   117        || i != 1)
   118      abort ();
   119  
   120    /* These should probably be handled by move_by_pieces on most arches.  */
   121    if (memcpy ((char *) buf3 + 4, buf5, 6) != (char *) buf1 + 4
   122        || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
   123      abort ();
   124  
   125    if (__builtin_memcpy ((char *) buf1 + ++i + 8, (char *) buf5 + 1, 1)
   126        != (char *) buf1 + 10
   127        || memcmp (buf1, "aBcdRSTUVWSlmnopq\0", 19)
   128        || i != 2)
   129      abort ();
   130  
   131    if (memcpy ((char *) buf3 + 14, buf6, 2) != (char *) buf1 + 14
   132        || memcmp (buf1, "aBcdRSTUVWSlmnrsq\0", 19))
   133      abort ();
   134  
   135    if (memcpy (buf3, buf5, 8) != (char *) buf1
   136        || memcmp (buf1, "RSTUVWXYVWSlmnrsq\0", 19))
   137      abort ();
   138  
   139    if (memcpy (buf3, buf5, 17) != (char *) buf1
   140        || memcmp (buf1, "RSTUVWXYZ01234567\0", 19))
   141      abort ();
   142  
   143    __builtin_memcpy (buf3, "aBcdEFghijklmnopq\0", 19);
   144  
   145    /* These should be handled either by movmemendM or memcpy
   146       call.  */
   147  
   148    /* buf3 points to an unknown object, so __memcpy_chk should not be done.  */
   149    if (memcpy ((char *) buf3 + 4, buf5, n + 6) != (char *) buf1 + 4
   150        || memcmp (buf1, "aBcdRSTUVWklmnopq\0", 19))
   151      abort ();
   152  
   153    /* This call has side-effects in dst, therefore no checking.  */
   154    if (__builtin___memcpy_chk ((char *) buf1 + ++i + 8, (char *) buf5 + 1,
   155  			      n + 1, os ((char *) buf1 + ++i + 8))
   156        != (char *) buf1 + 11
   157        || memcmp (buf1, "aBcdRSTUVWkSmnopq\0", 19)
   158        || i != 3)
   159      abort ();
   160  
   161    if (memcpy ((char *) buf3 + 14, buf6, n + 2) != (char *) buf1 + 14
   162        || memcmp (buf1, "aBcdRSTUVWkSmnrsq\0", 19))
   163      abort ();
   164  
   165    i = 1;
   166  
   167    /* These might be handled by store_by_pieces.  */
   168    if (memcpy (buf2, "ABCDEFGHI", 9) != buf2
   169        || memcmp (buf2, "ABCDEFGHI\0", 11))
   170      abort ();
   171  
   172    if (memcpy (buf2, "abcdefghijklmnopq", 17) != buf2
   173        || memcmp (buf2, "abcdefghijklmnopq\0", 19))
   174      abort ();
   175  
   176    if (__builtin_memcpy (buf4, "ABCDEF", 6) != buf2
   177        || memcmp (buf2, "ABCDEFghijklmnopq\0", 19))
   178      abort ();
   179  
   180    if (__builtin_memcpy (buf4, "a", 1) != buf2
   181        || memcmp (buf2, "aBCDEFghijklmnopq\0", 19))
   182      abort ();
   183  
   184    if (memcpy (buf4 + 2, "bcd" + i++, 2) != buf2 + 2
   185        || memcmp (buf2, "aBcdEFghijklmnopq\0", 19)
   186        || i != 2)
   187      abort ();
   188  
   189    /* These might be handled by move_by_pieces.  */
   190    if (memcpy (buf4 + 4, buf7, 6) != buf2 + 4
   191        || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
   192      abort ();
   193  
   194    /* Side effect.  */
   195    if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, 1,
   196  			      os (buf2 + i++ + 8))
   197        != buf2 + 10
   198        || memcmp (buf2, "aBcdRSTUVWSlmnopq\0", 19)
   199        || i != 3)
   200      abort ();
   201  
   202    if (memcpy (buf4 + 14, buf6, 2) != buf2 + 14
   203        || memcmp (buf2, "aBcdRSTUVWSlmnrsq\0", 19))
   204      abort ();
   205  
   206    __builtin_memcpy (buf4, "aBcdEFghijklmnopq\0", 19);
   207  
   208    /* These should be handled either by movmemendM or memcpy
   209       call.  */
   210    if (memcpy (buf4 + 4, buf7, n + 6) != buf2 + 4
   211        || memcmp (buf2, "aBcdRSTUVWklmnopq\0", 19))
   212      abort ();
   213  
   214    /* Side effect.  */
   215    if (__builtin___memcpy_chk (buf2 + i++ + 8, buf7 + 1, n + 1,
   216  			      os (buf2 + i++ + 8))
   217        != buf2 + 11
   218        || memcmp (buf2, "aBcdRSTUVWkSmnopq\0", 19)
   219        || i != 4)
   220      abort ();
   221  
   222    if (memcpy (buf4 + 14, buf6, n + 2) != buf2 + 14
   223        || memcmp (buf2, "aBcdRSTUVWkSmnrsq\0", 19))
   224      abort ();
   225  
   226    if (chk_calls)
   227      abort ();
   228  }
   229  
   230  void
   231  __attribute__((noinline))
   232  test2 (void)
   233  {
   234    long *x;
   235    char *y;
   236    int z;
   237    __builtin_memcpy (buf5, "RSTUVWXYZ0123456789", 20);
   238    __builtin_memcpy (buf7, "RSTUVWXYZ0123456789", 20);
   239   __asm ("" : "=r" (x) : "0" (buf1));
   240   __asm ("" : "=r" (y) : "0" (buf2));
   241   __asm ("" : "=r" (z) : "0" (0));
   242    test2_sub (x, y, "rstuvwxyz", z);
   243  }
   244  
   245  /* Test whether compile time checking is done where it should
   246     and so is runtime object size checking.  */
   247  void
   248  __attribute__((noinline))
   249  test3 (void)
   250  {
   251    struct A { char buf1[10]; char buf2[10]; } a;
   252    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
   253    char buf3[20];
   254    int i;
   255    size_t l;
   256  
   257    /* The following calls should do runtime checking
   258       - length is not known, but destination is.  */
   259    chk_calls = 0;
   260    memcpy (a.buf1 + 2, s3, l1);
   261    memcpy (r, s3, l1 + 1);
   262    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   263    memcpy (r, s2, l1 + 2);
   264    memcpy (r + 2, s3, l1);
   265    r = buf3;
   266    for (i = 0; i < 4; ++i)
   267      {
   268        if (i == l1 - 1)
   269  	r = &a.buf1[1];
   270        else if (i == l1)
   271  	r = &a.buf2[7];
   272        else if (i == l1 + 1)
   273  	r = &buf3[5];
   274        else if (i == l1 + 2)
   275  	r = &a.buf1[9];
   276      }
   277    memcpy (r, s2, l1);
   278    if (chk_calls != 5)
   279      abort ();
   280  
   281    /* Following have known destination and known length,
   282       so if optimizing certainly shouldn't result in the checking
   283       variants.  */
   284    chk_calls = 0;
   285    memcpy (a.buf1 + 2, s3, 1);
   286    memcpy (r, s3, 2);
   287    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   288    memcpy (r, s2, 3);
   289    r = buf3;
   290    l = 4;
   291    for (i = 0; i < 4; ++i)
   292      {
   293        if (i == l1 - 1)
   294  	r = &a.buf1[1], l = 2;
   295        else if (i == l1)
   296  	r = &a.buf2[7], l = 3;
   297        else if (i == l1 + 1)
   298  	r = &buf3[5], l = 4;
   299        else if (i == l1 + 2)
   300  	r = &a.buf1[9], l = 1;
   301      }
   302    memcpy (r, s2, 1);
   303    /* Here, l is known to be at most 4 and __builtin_object_size (&buf3[16], 0)
   304       is 4, so this doesn't need runtime checking.  */
   305    memcpy (&buf3[16], s2, l);
   306    if (chk_calls)
   307      abort ();
   308    chk_calls = 0;
   309  }
   310  
   311  /* Test whether runtime and/or compile time checking catches
   312     buffer overflows.  */
   313  void
   314  __attribute__((noinline))
   315  test4 (void)
   316  {
   317    struct A { char buf1[10]; char buf2[10]; } a;
   318    char buf3[20];
   319  
   320    chk_fail_allowed = 1;
   321    /* Runtime checks.  */
   322    if (__builtin_setjmp (chk_fail_buf) == 0)
   323      {
   324        memcpy (&a.buf2[9], s2, l1 + 1);
   325        abort ();
   326      }
   327    if (__builtin_setjmp (chk_fail_buf) == 0)
   328      {
   329        memcpy (&a.buf2[7], s3, strlen (s3) + 1);
   330        abort ();
   331      }
   332    /* This should be detectable at compile time already.  */
   333    if (__builtin_setjmp (chk_fail_buf) == 0)
   334      {
   335        memcpy (&buf3[19], "ab", 2);
   336        abort ();
   337      }
   338    chk_fail_allowed = 0;
   339  }
   340  
   341  #ifndef MAX_OFFSET
   342  #define MAX_OFFSET (sizeof (long long))
   343  #endif
   344  
   345  #ifndef MAX_COPY
   346  #define MAX_COPY (10 * sizeof (long long))
   347  #endif
   348  
   349  #ifndef MAX_EXTRA
   350  #define MAX_EXTRA (sizeof (long long))
   351  #endif
   352  
   353  #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
   354  
   355  /* Use a sequence length that is not divisible by two, to make it more
   356     likely to detect when words are mixed up.  */
   357  #define SEQUENCE_LENGTH 31
   358  
   359  static union {
   360    char buf[MAX_LENGTH];
   361    long long align_int;
   362    long double align_fp;
   363  } u1, u2;
   364  
   365  void
   366  __attribute__((noinline))
   367  test5 (void)
   368  {
   369    int off1, off2, len, i;
   370    char *p, *q, c;
   371  
   372    for (off1 = 0; off1 < MAX_OFFSET; off1++)
   373      for (off2 = 0; off2 < MAX_OFFSET; off2++)
   374        for (len = 1; len < MAX_COPY; len++)
   375  	{
   376  	  for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
   377  	    {
   378  	      u1.buf[i] = 'a';
   379  	      if (c >= 'A' + SEQUENCE_LENGTH)
   380  		c = 'A';
   381  	      u2.buf[i] = c;
   382  	    }
   383  
   384  	  p = memcpy (u1.buf + off1, u2.buf + off2, len);
   385  	  if (p != u1.buf + off1)
   386  	    abort ();
   387  
   388  	  q = u1.buf;
   389  	  for (i = 0; i < off1; i++, q++)
   390  	    if (*q != 'a')
   391  	      abort ();
   392  
   393  	  for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
   394  	    {
   395  	      if (c >= 'A' + SEQUENCE_LENGTH)
   396  		c = 'A';
   397  	      if (*q != c)
   398  		abort ();
   399  	    }
   400  
   401  	  for (i = 0; i < MAX_EXTRA; i++, q++)
   402  	    if (*q != 'a')
   403  	      abort ();
   404  	}
   405  }
   406  
   407  #define TESTSIZE 80
   408  
   409  char srcb[TESTSIZE] __attribute__ ((aligned));
   410  char dstb[TESTSIZE] __attribute__ ((aligned));
   411  
   412  void
   413  __attribute__((noinline))
   414  check (char *test, char *match, int n)
   415  {
   416    if (memcmp (test, match, n))
   417      abort ();
   418  }
   419  
   420  #define TN(n) \
   421  { memset (dstb, 0, n); memcpy (dstb, srcb, n); check (dstb, srcb, n); }
   422  #define T(n) \
   423  TN (n) \
   424  TN ((n) + 1) \
   425  TN ((n) + 2) \
   426  TN ((n) + 3)
   427  
   428  void
   429  __attribute__((noinline))
   430  test6 (void)
   431  {
   432    int i;
   433  
   434    chk_calls = 0;
   435  
   436    for (i = 0; i < sizeof (srcb); ++i)
   437        srcb[i] = 'a' + i % 26;
   438  
   439    T (0);
   440    T (4);
   441    T (8);
   442    T (12);
   443    T (16);
   444    T (20);
   445    T (24);
   446    T (28);
   447    T (32);
   448    T (36);
   449    T (40);
   450    T (44);
   451    T (48);
   452    T (52);
   453    T (56);
   454    T (60);
   455    T (64);
   456    T (68);
   457    T (72);
   458    T (76);
   459  
   460    /* All memcpy calls in this routine have constant arguments.  */
   461    if (chk_calls)
   462      abort ();
   463  }
   464  
   465  void
   466  main_test (void)
   467  {
   468  #ifndef __OPTIMIZE__
   469    /* Object size checking is only intended for -O[s123].  */
   470    return;
   471  #endif
   472    __asm ("" : "=r" (l1) : "0" (l1));
   473    test1 ();
   474    test2 ();
   475    test3 ();
   476    test4 ();
   477    test5 ();
   478    test6 ();
   479  }