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