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

     1  /* Copyright (C) 2004, 2005, 2011  Free Software Foundation.
     2  
     3     Ensure builtin __stpncpy_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 *stpncpy (char *, const char *, size_t);
    10  extern int memcmp (const void *, const void *, size_t);
    11  extern int strcmp (const char *, const char *);
    12  extern int strncmp (const char *, const char *, size_t);
    13  extern void *memset (void *, int, size_t);
    14  
    15  #include "chk.h"
    16  
    17  const char s1[] = "123";
    18  char p[32] = "";
    19  char * volatile s2 = "defg";  /* prevent constant propagation to happen when whole program assumptions are made.  */
    20  char * volatile s3 = "FGH";  /* prevent constant propagation to happen when whole program assumptions are made.  */
    21  char *s4;
    22  volatile size_t l1 = 1;  /* prevent constant propagation to happen when whole program assumptions are made.  */
    23  int i;
    24  
    25  void
    26  __attribute__((noinline))
    27  test1 (void)
    28  {
    29    const char *const src = "hello world";
    30    const char *src2;
    31    char dst[64], *dst2;
    32  
    33    chk_calls = 0;
    34  
    35    memset (dst, 0, sizeof (dst));
    36    if (stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
    37      abort();
    38  
    39    memset (dst, 0, sizeof (dst));
    40    if (stpncpy (dst+16, src, 4) != dst+20 || strncmp (dst+16, src, 4))
    41      abort();
    42  
    43    memset (dst, 0, sizeof (dst));
    44    if (stpncpy (dst+32, src+5, 4) != dst+36 || strncmp (dst+32, src+5, 4))
    45      abort();
    46  
    47    memset (dst, 0, sizeof (dst));
    48    dst2 = dst;
    49    if (stpncpy (++dst2, src+5, 4) != dst+5 || strncmp (dst2, src+5, 4)
    50        || dst2 != dst+1)
    51      abort();
    52  
    53    memset (dst, 0, sizeof (dst));
    54    if (stpncpy (dst, src, 0) != dst || strcmp (dst, ""))
    55      abort();
    56    
    57    memset (dst, 0, sizeof (dst));
    58    dst2 = dst; src2 = src;
    59    if (stpncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "")
    60        || dst2 != dst+1 || src2 != src+1)
    61      abort();
    62  
    63    memset (dst, 0, sizeof (dst));
    64    dst2 = dst; src2 = src;
    65    if (stpncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "")
    66        || dst2 != dst+1 || src2 != src+1)
    67      abort();
    68  
    69    memset (dst, 0, sizeof (dst));
    70    if (stpncpy (dst, src, 12) != dst+11 || strcmp (dst, src))
    71      abort();
    72  
    73    /* Test at least one instance of the __builtin_ style.  We do this
    74       to ensure that it works and that the prototype is correct.  */
    75    memset (dst, 0, sizeof (dst));
    76    if (__builtin_stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4))
    77      abort();
    78  
    79    memset (dst, 0, sizeof (dst));
    80    if (stpncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst+3
    81        || strcmp (dst, "bar")
    82        || i != 1)
    83      abort ();
    84  
    85    /* If return value of stpncpy is ignored, it should be optimized into
    86       stpncpy call.  */
    87    stpncpy_disallowed = 1;
    88    stpncpy (dst + 1, src, 4);
    89    stpncpy_disallowed = 0;
    90    if (strncmp (dst + 1, src, 4))
    91      abort ();
    92  
    93    if (chk_calls)
    94      abort ();
    95  }
    96  
    97  void
    98  __attribute__((noinline))
    99  test2 (void)
   100  {
   101    chk_calls = 0;
   102  
   103    /* No runtime checking should be done here, both destination
   104       and length are unknown.  */
   105    size_t cpy_length = l1 < 4 ? l1 + 1 : 4;
   106    if (stpncpy (s4, "abcd", l1 + 1) != s4 + cpy_length || strncmp (s4, "abcd", cpy_length))
   107      abort ();
   108  
   109    if (chk_calls)
   110      abort ();
   111  }
   112  
   113  /* Test whether compile time checking is done where it should
   114     and so is runtime object size checking.  */
   115  void
   116  __attribute__((noinline))
   117  test3 (void)
   118  {
   119    struct A { char buf1[10]; char buf2[10]; } a;
   120    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
   121    char buf3[20];
   122    int i;
   123    const char *l;
   124    size_t l2;
   125  
   126    /* The following calls should do runtime checking
   127       - source length is not known, but destination is.  
   128       The returned value is checked so that stpncpy calls
   129       are not rewritten to strncpy calls. */
   130    chk_calls = 0;
   131    if (!stpncpy (a.buf1 + 2, s3 + 3, l1))
   132      abort();
   133    if (!stpncpy (r, s3 + 2, l1 + 2))
   134      abort();
   135    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   136    if (!stpncpy (r, s2 + 2, l1 + 2))
   137      abort();
   138    if (!stpncpy (r + 2, s3 + 3, l1))
   139      abort();
   140    r = buf3;
   141    for (i = 0; i < 4; ++i)
   142      {
   143        if (i == l1 - 1)
   144  	r = &a.buf1[1];
   145        else if (i == l1)
   146  	r = &a.buf2[7];
   147        else if (i == l1 + 1)
   148  	r = &buf3[5];
   149        else if (i == l1 + 2)
   150  	r = &a.buf1[9];
   151      }
   152    if (!stpncpy (r, s2 + 4, l1))
   153      abort();
   154    if (chk_calls != 5)
   155      abort ();
   156  
   157    /* Following have known destination and known length,
   158       so if optimizing certainly shouldn't result in the checking
   159       variants.  */
   160    chk_calls = 0;
   161    if (!stpncpy (a.buf1 + 2, "", 3))
   162      abort ();
   163    if (!stpncpy (a.buf1 + 2, "", 0))
   164      abort ();
   165    if (!stpncpy (r, "a", 1))
   166      abort ();
   167    if (!stpncpy (r, "a", 3))
   168      abort ();
   169    r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   170    if (!stpncpy (r, s1 + 1, 3))
   171      abort ();
   172    if (!stpncpy (r, s1 + 1, 2))
   173      abort ();
   174    r = buf3;
   175    l = "abc";
   176    l2 = 4;
   177    for (i = 0; i < 4; ++i)
   178      {
   179        if (i == l1 - 1)
   180  	r = &a.buf1[1], l = "e", l2 = 2;
   181        else if (i == l1)
   182  	r = &a.buf2[7], l = "gh", l2 = 3;
   183        else if (i == l1 + 1)
   184  	r = &buf3[5], l = "jkl", l2 = 4;
   185        else if (i == l1 + 2)
   186  	r = &a.buf1[9], l = "", l2 = 1;
   187      }
   188    if (!stpncpy (r, "", 1))
   189      abort ();
   190    /* Here, strlen (l) + 1 is known to be at most 4 and
   191       __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need
   192       runtime checking.  */
   193    if (!stpncpy (&buf3[16], l, l2))
   194      abort ();
   195    if (!stpncpy (&buf3[15], "abc", l2))
   196      abort ();
   197    if (!stpncpy (&buf3[10], "fghij", l2))
   198      abort ();
   199    if (chk_calls)
   200      abort ();
   201    chk_calls = 0;
   202  }
   203  
   204  /* Test whether runtime and/or compile time checking catches
   205     buffer overflows.  */
   206  void
   207  __attribute__((noinline))
   208  test4 (void)
   209  {
   210    struct A { char buf1[10]; char buf2[10]; } a;
   211    char buf3[20];
   212  
   213    chk_fail_allowed = 1;
   214    /* Runtime checks.  */
   215    if (__builtin_setjmp (chk_fail_buf) == 0)
   216      {
   217        if (stpncpy (&a.buf2[9], s2 + 4, l1 + 1))
   218          // returned value used to prevent stpncpy calls
   219          // to be rewritten in strncpy calls
   220          i++;
   221        abort ();
   222      }
   223    if (__builtin_setjmp (chk_fail_buf) == 0)
   224      {
   225        if (stpncpy (&a.buf2[7], s3, l1 + 4))
   226          i++;
   227        abort ();
   228      }
   229    /* This should be detectable at compile time already.  */
   230    if (__builtin_setjmp (chk_fail_buf) == 0)
   231      {
   232        if (stpncpy (&buf3[19], "abc", 2))
   233          i++;
   234        abort ();
   235      }
   236    if (__builtin_setjmp (chk_fail_buf) == 0)
   237      {
   238        if (stpncpy (&buf3[18], "", 3))
   239          i++;
   240        abort ();
   241      }
   242    chk_fail_allowed = 0;
   243  }
   244  
   245  void
   246  main_test (void)
   247  {
   248  #ifndef __OPTIMIZE__
   249    /* Object size checking is only intended for -O[s123].  */
   250    return;
   251  #endif
   252    __asm ("" : "=r" (s2) : "0" (s2));
   253    __asm ("" : "=r" (s3) : "0" (s3));
   254    __asm ("" : "=r" (l1) : "0" (l1));
   255    test1 ();
   256    
   257    s4 = p;
   258    test2 ();
   259    test3 ();
   260    test4 ();
   261  }