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 }