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

     1  /* Copyright (C) 2004, 2005  Free Software Foundation.
     2  
     3     Ensure builtin __vsprintf_chk performs correctly.  */
     4  
     5  #include <stdarg.h>
     6  
     7  extern void abort (void);
     8  typedef __SIZE_TYPE__ size_t;
     9  extern size_t strlen(const char *);
    10  extern void *memcpy (void *, const void *, size_t);
    11  extern char *strcpy (char *, const char *);
    12  extern int memcmp (const void *, const void *, size_t);
    13  extern void *memset (void *, int, size_t);
    14  extern int vsprintf (char *, const char *, va_list);
    15  
    16  #include "chk.h"
    17  
    18  const char s1[] = "123";
    19  char p[32] = "";
    20  char *s2 = "defg";
    21  char *s3 = "FGH";
    22  char *s4;
    23  size_t l1 = 1;
    24  static char buffer[32];
    25  char * volatile ptr = "barf";  /* prevent constant propagation to happen when whole program assumptions are made.  */
    26  
    27  int
    28  __attribute__((noinline))
    29  test1_sub (int i, ...)
    30  {
    31    int ret = 0;
    32    va_list ap;
    33    va_start (ap, i);
    34    switch (i)
    35      {
    36      case 0:
    37        vsprintf (buffer, "foo", ap);
    38        break;
    39      case 1:
    40        ret = vsprintf (buffer, "foo", ap);
    41        break;
    42      case 2:
    43        vsprintf (buffer, "%s", ap);
    44        break;
    45      case 3:
    46        ret = vsprintf (buffer, "%s", ap);
    47        break;
    48      case 4:
    49        vsprintf (buffer, "%d - %c", ap);
    50        break;
    51      case 5:
    52        vsprintf (s4, "%d - %c", ap);
    53        break;
    54      }
    55    va_end (ap);
    56    return ret;
    57  }
    58  
    59  void
    60  __attribute__((noinline))
    61  test1 (void)
    62  {
    63    chk_calls = 0;
    64    vsprintf_disallowed = 1;
    65  
    66    memset (buffer, 'A', 32);
    67    test1_sub (0);
    68    if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
    69      abort ();
    70  
    71    memset (buffer, 'A', 32);
    72    if (test1_sub (1) != 3)
    73      abort ();
    74    if (memcmp (buffer, "foo", 4) || buffer[4] != 'A')
    75      abort ();
    76  
    77    if (chk_calls)
    78      abort ();
    79    vsprintf_disallowed = 0;
    80  
    81    memset (buffer, 'A', 32);
    82    test1_sub (2, "bar");
    83    if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
    84      abort ();
    85  
    86    memset (buffer, 'A', 32);
    87    if (test1_sub (3, "bar") != 3)
    88      abort ();
    89    if (memcmp (buffer, "bar", 4) || buffer[4] != 'A')
    90      abort ();
    91  
    92    memset (buffer, 'A', 32);
    93    test1_sub (2, ptr);
    94    if (memcmp (buffer, "barf", 5) || buffer[5] != 'A')
    95      abort ();
    96  
    97    memset (buffer, 'A', 32);
    98    test1_sub (4, (int) l1 + 27, *ptr);
    99    if (memcmp (buffer, "28 - b\0AAAAA", 12))
   100      abort ();
   101  
   102    if (chk_calls != 4)
   103      abort ();
   104    chk_calls = 0;
   105  
   106    test1_sub (5, (int) l1 - 17, ptr[1]);
   107    if (memcmp (s4, "-16 - a", 8))
   108      abort ();
   109    if (chk_calls)
   110      abort ();
   111  }
   112  
   113  void
   114  __attribute__((noinline))
   115  test2_sub (int i, ...)
   116  {
   117    va_list ap;
   118    struct A { char buf1[10]; char buf2[10]; } a;
   119    char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4];
   120    char buf3[20];
   121    int j;
   122  
   123    va_start (ap, i);
   124    /* The following calls should do runtime checking
   125       - source length is not known, but destination is.  */
   126    switch (i)
   127      {
   128      case 0:
   129        vsprintf (a.buf1 + 2, "%s", ap);
   130        break;
   131      case 1:
   132        vsprintf (r, "%s%c", ap);
   133        break;
   134      case 2:
   135        r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   136        vsprintf (r, "%c %s", ap);
   137        break;
   138      case 3:
   139        r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   140        vsprintf (r + 2, s3 + 3, ap);
   141        break;
   142      case 4:
   143      case 7:
   144        r = buf3;
   145        for (j = 0; j < 4; ++j)
   146  	{
   147  	  if (j == l1 - 1)
   148  	    r = &a.buf1[1];
   149  	  else if (j == l1)
   150  	    r = &a.buf2[7];
   151  	  else if (j == l1 + 1)
   152  	    r = &buf3[5];
   153  	  else if (j == l1 + 2)
   154  	    r = &a.buf1[9];
   155  	}
   156        if (i == 4)
   157  	vsprintf (r, s2 + 4, ap);
   158        else
   159  	vsprintf (r, "a", ap);
   160        break;
   161      case 5:
   162        r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7];
   163        vsprintf (r, "%s", ap);
   164        break;
   165      case 6:
   166        vsprintf (a.buf1 + 2, "", ap);
   167        break;
   168      case 8:
   169        vsprintf (s4, "%s %d", ap);
   170        break;
   171      }
   172    va_end (ap);
   173  }
   174  
   175  /* Test whether compile time checking is done where it should
   176     and so is runtime object size checking.  */
   177  void
   178  __attribute__((noinline))
   179  test2 (void)
   180  {
   181    /* The following calls should do runtime checking
   182       - source length is not known, but destination is.  */
   183    chk_calls = 0;
   184    test2_sub (0, s3 + 3);
   185    test2_sub (1, s3 + 3, s3[3]);
   186    test2_sub (2, s2[2], s2 + 4);
   187    test2_sub (3);
   188    test2_sub (4);
   189    test2_sub (5, s1 + 1);
   190    if (chk_calls != 6)
   191      abort ();
   192  
   193    /* Following have known destination and known source length,
   194       so if optimizing certainly shouldn't result in the checking
   195       variants.  */
   196    chk_calls = 0;
   197    vsprintf_disallowed = 1;
   198    test2_sub (6);
   199    test2_sub (7);
   200    vsprintf_disallowed = 0;
   201    /* Unknown destination and source, no checking.  */
   202    test2_sub (8, s3, 0);
   203    if (chk_calls)
   204      abort ();
   205  }
   206  
   207  void
   208  __attribute__((noinline))
   209  test3_sub (int i, ...)
   210  {
   211    va_list ap;
   212    struct A { char buf1[10]; char buf2[10]; } a;
   213    char buf3[20];
   214  
   215    va_start (ap, i);
   216    /* The following calls should do runtime checking
   217       - source length is not known, but destination is.  */
   218    switch (i)
   219      {
   220      case 0:
   221        vsprintf (&a.buf2[9], "%c%s", ap);
   222        break;
   223      case 1:
   224        vsprintf (&a.buf2[7], "%s%c", ap);
   225        break;
   226      case 2:
   227        vsprintf (&a.buf2[7], "%d", ap);
   228        break;
   229      case 3:
   230        vsprintf (&buf3[17], "%s", ap);
   231        break;
   232      case 4:
   233        vsprintf (&buf3[19], "a", ap);
   234        break;
   235      }
   236    va_end (ap);
   237  }
   238  
   239  /* Test whether runtime and/or compile time checking catches
   240     buffer overflows.  */
   241  void
   242  __attribute__((noinline))
   243  test3 (void)
   244  {
   245    chk_fail_allowed = 1;
   246    /* Runtime checks.  */
   247    if (__builtin_setjmp (chk_fail_buf) == 0)
   248      {
   249        test3_sub (0, s2[3], s2 + 4);
   250        abort ();
   251      }
   252    if (__builtin_setjmp (chk_fail_buf) == 0)
   253      {
   254        test3_sub (1, s3 + strlen (s3) - 2, *s3);
   255        abort ();
   256      }
   257    if (__builtin_setjmp (chk_fail_buf) == 0)
   258      {
   259        test3_sub (2, (int) l1 + 9999);
   260        abort ();
   261      }
   262    if (__builtin_setjmp (chk_fail_buf) == 0)
   263      {
   264        test3_sub (3, "abc");
   265        abort ();
   266      }
   267    /* This should be detectable at compile time already.  */
   268    if (__builtin_setjmp (chk_fail_buf) == 0)
   269      {
   270        test3_sub (4);
   271        abort ();
   272      }
   273    chk_fail_allowed = 0;
   274  }
   275  
   276  void
   277  main_test (void)
   278  {
   279  #ifndef __OPTIMIZE__
   280    /* Object size checking is only intended for -O[s123].  */
   281    return;
   282  #endif
   283    __asm ("" : "=r" (s2) : "0" (s2));
   284    __asm ("" : "=r" (s3) : "0" (s3));
   285    __asm ("" : "=r" (l1) : "0" (l1));
   286    s4 = p;
   287    test1 ();
   288    test2 ();
   289    test3 ();
   290  }