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

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