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

     1  /* Copyright (C) 2004, 2005  Free Software Foundation.
     2  
     3     Ensure builtin __stpcpy_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 char *stpcpy (char *, const char *);
    10  extern int memcmp (const void *, const void *, size_t);
    11  
    12  #include "chk.h"
    13  
    14  LOCAL const char s1[] = "123";
    15  char p[32] = "";
    16  char *s2 = "defg";
    17  char *s3 = "FGH";
    18  char *s4;
    19  size_t l1 = 1;
    20  
    21  void
    22  __attribute__((noinline))
    23  test1 (void)
    24  {
    25    int i = 8;
    26  
    27  #if defined __i386__ || defined __x86_64__
    28    /* The functions below might not be optimized into direct stores on all
    29       arches.  It depends on how many instructions would be generated and
    30       what limits the architecture chooses in STORE_BY_PIECES_P.  */
    31    stpcpy_disallowed = 1;
    32  #endif
    33    if (stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
    34      abort ();
    35    if (stpcpy (p + 16, "vwxyz" + 1) != p + 16 + 4 || memcmp (p + 16, "wxyz", 5))
    36      abort ();
    37    if (stpcpy (p + 1, "") != p + 1 + 0 || memcmp (p, "a\0cde", 6))
    38      abort ();
    39    if (stpcpy (p + 3, "fghij") != p + 3 + 5 || memcmp (p, "a\0cfghij", 9))
    40      abort ();
    41  
    42    if (stpcpy ((i++, p + 20 + 1), "23") != (p + 20 + 1 + 2)
    43        || i != 9 || memcmp (p + 19, "z\0""23\0", 5))
    44      abort ();
    45  
    46    if (stpcpy (stpcpy (p, "ABCD"), "EFG") != p + 7 || memcmp (p, "ABCDEFG", 8))
    47      abort();
    48  
    49    /* Test at least one instance of the __builtin_ style.  We do this
    50       to ensure that it works and that the prototype is correct.  */
    51    if (__builtin_stpcpy (p, "abcde") != p + 5 || memcmp (p, "abcde", 6))
    52      abort ();
    53  
    54    /* If return value of stpcpy is ignored, it should be optimized into
    55       strcpy call.  */
    56    stpcpy_disallowed = 1;
    57    stpcpy (p + 1, "abcd");
    58    stpcpy_disallowed = 0;
    59    if (memcmp (p, "aabcd", 6))
    60      abort ();
    61  
    62    if (chk_calls)
    63      abort ();
    64  
    65    chk_calls = 0;
    66    strcpy_disallowed = 1;
    67    if (stpcpy (p, s2) != p + 4 || memcmp (p, "defg\0", 6))
    68      abort ();
    69    strcpy_disallowed = 0;
    70    stpcpy_disallowed = 1;
    71    stpcpy (p + 2, s3);
    72    stpcpy_disallowed = 0;
    73    if (memcmp (p, "deFGH", 6))
    74      abort ();
    75    if (chk_calls != 2)
    76      abort ();
    77  }
    78  
    79  #ifndef MAX_OFFSET
    80  #define MAX_OFFSET (sizeof (long long))
    81  #endif
    82  
    83  #ifndef MAX_COPY
    84  #define MAX_COPY (10 * sizeof (long long))
    85  #endif
    86  
    87  #ifndef MAX_EXTRA
    88  #define MAX_EXTRA (sizeof (long long))
    89  #endif
    90  
    91  #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + 1 + MAX_EXTRA)
    92  
    93  /* Use a sequence length that is not divisible by two, to make it more
    94     likely to detect when words are mixed up.  */
    95  #define SEQUENCE_LENGTH 31
    96  
    97  static union {
    98    char buf[MAX_LENGTH];
    99    long long align_int;
   100    long double align_fp;
   101  } u1, u2;
   102  
   103  volatile char *vx;
   104  
   105  void
   106  __attribute__((noinline))
   107  test2 (void)
   108  {
   109    int off1, off2, len, i;
   110    char *p, *q, c;
   111  
   112    for (off1 = 0; off1 < MAX_OFFSET; off1++)
   113      for (off2 = 0; off2 < MAX_OFFSET; off2++)
   114        for (len = 1; len < MAX_COPY; len++)
   115  	{
   116  	  for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
   117  	    {
   118  	      u1.buf[i] = 'a';
   119  	      if (c >= 'A' + SEQUENCE_LENGTH)
   120  		c = 'A';
   121  	      u2.buf[i] = c;
   122  	    }
   123  	  u2.buf[off2 + len] = '\0';
   124  
   125  	  p = stpcpy (u1.buf + off1, u2.buf + off2);
   126  	  if (p != u1.buf + off1 + len)
   127  	    abort ();
   128  
   129  	  q = u1.buf;
   130  	  for (i = 0; i < off1; i++, q++)
   131  	    if (*q != 'a')
   132  	      abort ();
   133  
   134  	  for (i = 0, c = 'A' + off2; i < len; i++, q++, c++)
   135  	    {
   136  	      if (c >= 'A' + SEQUENCE_LENGTH)
   137  		c = 'A';
   138  	      if (*q != c)
   139  		abort ();
   140  	    }
   141  
   142  	  if (*q++ != '\0')
   143  	    abort ();
   144  	  for (i = 0; i < MAX_EXTRA; i++, q++)
   145  	    if (*q != 'a')
   146  	      abort ();
   147  	}
   148  }
   149  
   150  /* Test whether compile time checking is done where it should
   151     and so is runtime object size checking.  */
   152  void
   153  __attribute__((noinline))
   154  test3 (void)
   155  {
   156    struct A { char buf1[10]; char buf2[10]; } a;
   157    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
   158    char buf3[20];
   159    int i;
   160    const char *l;
   161  
   162    /* The following calls should do runtime checking
   163       - source length is not known, but destination is.  */
   164    chk_calls = 0;
   165    vx = stpcpy (a.buf1 + 2, s3 + 3);
   166    vx = stpcpy (r, s3 + 2);
   167    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   168    vx = stpcpy (r, s2 + 2);
   169    vx = stpcpy (r + 2, s3 + 3);
   170    r = buf3;
   171    for (i = 0; i < 4; ++i)
   172      {
   173        if (i == l1 - 1)
   174  	r = &a.buf1[1];
   175        else if (i == l1)
   176  	r = &a.buf2[7];
   177        else if (i == l1 + 1)
   178  	r = &buf3[5];
   179        else if (i == l1 + 2)
   180  	r = &a.buf1[9];
   181      }
   182    vx = stpcpy (r, s2 + 4);
   183    if (chk_calls != 5)
   184      abort ();
   185  
   186    /* Following have known destination and known source length,
   187       so if optimizing certainly shouldn't result in the checking
   188       variants.  */
   189    chk_calls = 0;
   190    vx = stpcpy (a.buf1 + 2, "");
   191    vx = stpcpy (r, "a");
   192    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   193    vx = stpcpy (r, s1 + 1);
   194    r = buf3;
   195    l = "abc";
   196    for (i = 0; i < 4; ++i)
   197      {
   198        if (i == l1 - 1)
   199  	r = &a.buf1[1], l = "e";
   200        else if (i == l1)
   201  	r = &a.buf2[7], l = "gh";
   202        else if (i == l1 + 1)
   203  	r = &buf3[5], l = "jkl";
   204        else if (i == l1 + 2)
   205  	r = &a.buf1[9], l = "";
   206      }
   207    vx = stpcpy (r, "");
   208    /* Here, strlen (l) + 1 is known to be at most 4 and
   209       __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
   210       runtime checking.  */
   211    vx = stpcpy (&buf3[16], l);
   212    /* Unknown destination and source, no checking.  */
   213    vx = stpcpy (s4, s3);
   214    stpcpy (s4 + 4, s3);
   215    if (chk_calls)
   216      abort ();
   217    chk_calls = 0;
   218  }
   219  
   220  /* Test whether runtime and/or compile time checking catches
   221     buffer overflows.  */
   222  void
   223  __attribute__((noinline))
   224  test4 (void)
   225  {
   226    struct A { char buf1[10]; char buf2[10]; } a;
   227    char buf3[20];
   228  
   229    chk_fail_allowed = 1;
   230    /* Runtime checks.  */
   231    if (__builtin_setjmp (chk_fail_buf) == 0)
   232      {
   233        vx = stpcpy (&a.buf2[9], s2 + 3);
   234        abort ();
   235      }
   236    if (__builtin_setjmp (chk_fail_buf) == 0)
   237      {
   238        vx = stpcpy (&a.buf2[7], s3 + strlen (s3) - 3);
   239        abort ();
   240      }
   241    /* This should be detectable at compile time already.  */
   242    if (__builtin_setjmp (chk_fail_buf) == 0)
   243      {
   244        vx = stpcpy (&buf3[19], "a");
   245        abort ();
   246      }
   247    chk_fail_allowed = 0;
   248  }
   249  
   250  void
   251  main_test (void)
   252  {
   253  #ifndef __OPTIMIZE__
   254    /* Object size checking is only intended for -O[s123].  */
   255    return;
   256  #endif
   257    __asm ("" : "=r" (s2) : "0" (s2));
   258    __asm ("" : "=r" (s3) : "0" (s3));
   259    __asm ("" : "=r" (l1) : "0" (l1));
   260    test1 ();
   261    s4 = p;
   262    test2 ();
   263    test3 ();
   264    test4 ();
   265  }