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

     1  /* Copyright (C) 2004, 2005  Free Software Foundation.
     2  
     3     Ensure builtin __strcat_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 *strcat (char *, const char *);
    10  extern int memcmp (const void *, const void *, size_t);
    11  extern char *strcpy (char *, const char *);
    12  extern int strcmp (const char *, const char *);
    13  extern void *memset (void *, int, size_t);
    14  #define RESET_DST_WITH(FILLER) \
    15    do { memset (dst, 'X', sizeof (dst)); strcpy (dst, (FILLER)); } while (0)
    16  
    17  #include "chk.h"
    18  
    19  const char s1[] = "123";
    20  char p[32] = "";
    21  char *s2 = "defg";
    22  char *s3 = "FGH";
    23  char *s4;
    24  size_t l1 = 1;
    25  char *s5;
    26  
    27  void
    28  __attribute__((noinline))
    29  test1 (void)
    30  {
    31    const char *const x1 = "hello world";
    32    const char *const x2 = "";
    33    char dst[64], *d2;
    34  
    35    chk_calls = 0;
    36    strcat_disallowed = 1;
    37    /* Following strcat calls should be optimized out at compile time.  */  
    38    RESET_DST_WITH (x1);
    39    if (strcat (dst, "") != dst || strcmp (dst, x1))
    40      abort ();
    41    RESET_DST_WITH (x1);
    42    if (strcat (dst, x2) != dst || strcmp (dst, x1))
    43      abort ();
    44    RESET_DST_WITH (x1); d2 = dst;
    45    if (strcat (++d2, x2) != dst+1 || d2 != dst+1 || strcmp (dst, x1))
    46      abort ();
    47    RESET_DST_WITH (x1); d2 = dst;
    48    if (strcat (++d2+5, x2) != dst+6 || d2 != dst+1 || strcmp (dst, x1))
    49      abort ();
    50    RESET_DST_WITH (x1); d2 = dst;
    51    if (strcat (++d2+5, x1+11) != dst+6 || d2 != dst+1 || strcmp (dst, x1))
    52      abort ();
    53    if (chk_calls)
    54      abort ();
    55    strcat_disallowed = 0;
    56  
    57    RESET_DST_WITH (x1);
    58    if (strcat (dst, " 1111") != dst
    59        || memcmp (dst, "hello world 1111\0XXX", 20))
    60      abort ();
    61    
    62    RESET_DST_WITH (x1);
    63    if (strcat (dst+5, " 2222") != dst+5
    64        || memcmp (dst, "hello world 2222\0XXX", 20))
    65      abort ();
    66    
    67    RESET_DST_WITH (x1); d2 = dst;
    68    if (strcat (++d2+5, " 3333") != dst+6 || d2 != dst+1
    69        || memcmp (dst, "hello world 3333\0XXX", 20))
    70      abort ();
    71    
    72    RESET_DST_WITH (x1);
    73    strcat (strcat (strcat (strcat (strcat (strcat (dst, ": this "), ""),
    74  				  "is "), "a "), "test"), ".");
    75    if (memcmp (dst, "hello world: this is a test.\0X", 30))
    76      abort ();
    77  
    78    chk_calls = 0;
    79    strcat_disallowed = 1;
    80    /* Test at least one instance of the __builtin_ style.  We do this
    81       to ensure that it works and that the prototype is correct.  */
    82    RESET_DST_WITH (x1);
    83    if (__builtin_strcat (dst, "") != dst || strcmp (dst, x1))
    84      abort ();
    85    if (chk_calls)
    86      abort ();
    87    strcat_disallowed = 0;
    88  }
    89  
    90  
    91  /* Test whether compile time checking is done where it should
    92     and so is runtime object size checking.  */
    93  void
    94  __attribute__((noinline))
    95  test2 (void)
    96  {
    97    struct A { char buf1[10]; char buf2[10]; } a;
    98    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
    99    char buf3[20];
   100    int i;
   101  
   102    /* The following calls should do runtime checking
   103       - source length is not known, but destination is.  */
   104    memset (&a, '\0', sizeof (a));
   105    s5 = (char *) &a;
   106    __asm __volatile ("" : : "r" (s5) : "memory");
   107    chk_calls = 0;
   108    strcat (a.buf1 + 2, s3 + 3);
   109    strcat (r, s3 + 2);
   110    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   111    memset (r, '\0', 3);
   112    __asm __volatile ("" : : "r" (r) : "memory");
   113    strcat (r, s2 + 2);
   114    strcat (r + 2, s3 + 3);
   115    r = buf3;
   116    for (i = 0; i < 4; ++i)
   117      {
   118        if (i == l1 - 1)
   119  	r = &a.buf1[1];
   120        else if (i == l1)
   121  	r = &a.buf2[7];
   122        else if (i == l1 + 1)
   123  	r = &buf3[5];
   124        else if (i == l1 + 2)
   125  	r = &a.buf1[9];
   126      }
   127    strcat (r, s2 + 4);
   128    if (chk_calls != 5)
   129      abort ();
   130  
   131    /* Following have known destination and known source length,
   132       but we don't know the length of dest string, so runtime checking
   133       is needed too.  */
   134    memset (&a, '\0', sizeof (a));
   135    chk_calls = 0;
   136    s5 = (char *) &a;
   137    __asm __volatile ("" : : "r" (s5) : "memory");
   138    strcat (a.buf1 + 2, "a");
   139    strcat (r, "");
   140    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   141    memset (r, '\0', 3);
   142    __asm __volatile ("" : : "r" (r) : "memory");
   143    strcat (r, s1 + 1);
   144    if (chk_calls != 2)
   145      abort ();
   146    chk_calls = 0;
   147    /* Unknown destination and source, no checking.  */
   148    strcat (s4, s3);
   149    if (chk_calls)
   150      abort ();
   151    chk_calls = 0;
   152  }
   153  
   154  /* Test whether runtime and/or compile time checking catches
   155     buffer overflows.  */
   156  void
   157  __attribute__((noinline))
   158  test3 (void)
   159  {
   160    struct A { char buf1[10]; char buf2[10]; } a;
   161    char buf3[20];
   162  
   163    memset (&a, '\0', sizeof (a));
   164    memset (buf3, '\0', sizeof (buf3));
   165    s5 = (char *) &a;
   166    __asm __volatile ("" : : "r" (s5) : "memory");
   167    s5 = buf3;
   168    __asm __volatile ("" : : "r" (s5) : "memory");
   169    chk_fail_allowed = 1;
   170    /* Runtime checks.  */
   171    if (__builtin_setjmp (chk_fail_buf) == 0)
   172      {
   173        strcat (&a.buf2[9], s2 + 3);
   174        abort ();
   175      }
   176    if (__builtin_setjmp (chk_fail_buf) == 0)
   177      {
   178        strcat (&a.buf2[7], s3 + strlen (s3) - 3);
   179        abort ();
   180      }
   181    if (__builtin_setjmp (chk_fail_buf) == 0)
   182      {
   183        strcat (&buf3[19], "a");
   184        abort ();
   185      }
   186    chk_fail_allowed = 0;
   187  }
   188  
   189  void
   190  main_test (void)
   191  {
   192  #ifndef __OPTIMIZE__
   193    /* Object size checking is only intended for -O[s123].  */
   194    return;
   195  #endif
   196    __asm ("" : "=r" (s2) : "0" (s2));
   197    __asm ("" : "=r" (s3) : "0" (s3));
   198    __asm ("" : "=r" (l1) : "0" (l1));
   199    s4 = p;
   200    test1 ();
   201    memset (p, '\0', sizeof (p));
   202    test2 ();
   203    test3 ();
   204  }