modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.c (about) 1 /* Copyright (C) 2004, 2005 Free Software Foundation. 2 3 Ensure builtin __snprintf_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 *strcpy (char *, const char *); 10 extern int memcmp (const void *, const void *, size_t); 11 extern void *memset (void *, int, size_t); 12 extern int sprintf (char *, const char *, ...); 13 extern int snprintf (char *, size_t, const char *, ...); 14 15 #include "chk.h" 16 17 const char s1[] = "123"; 18 char p[32] = ""; 19 char *s2 = "defg"; 20 char *s3 = "FGH"; 21 char *s4; 22 size_t l1 = 1; 23 static char buffer[32]; 24 char * volatile ptr = "barf"; /* prevent constant propagation to happen when whole program assumptions are made. */ 25 26 void 27 __attribute__((noinline)) 28 test1 (void) 29 { 30 chk_calls = 0; 31 /* snprintf_disallowed = 1; */ 32 33 memset (buffer, 'A', 32); 34 snprintf (buffer, 4, "foo"); 35 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A') 36 abort (); 37 38 memset (buffer, 'A', 32); 39 if (snprintf (buffer, 4, "foo bar") != 7) 40 abort (); 41 if (memcmp (buffer, "foo", 4) || buffer[4] != 'A') 42 abort (); 43 44 memset (buffer, 'A', 32); 45 snprintf (buffer, 32, "%s", "bar"); 46 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A') 47 abort (); 48 49 memset (buffer, 'A', 32); 50 if (snprintf (buffer, 21, "%s", "bar") != 3) 51 abort (); 52 if (memcmp (buffer, "bar", 4) || buffer[4] != 'A') 53 abort (); 54 55 snprintf_disallowed = 0; 56 57 memset (buffer, 'A', 32); 58 if (snprintf (buffer, 4, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12) 59 != 4) 60 abort (); 61 if (memcmp (buffer, "121", 4) || buffer[4] != 'A') 62 abort (); 63 64 memset (buffer, 'A', 32); 65 if (snprintf (buffer, 32, "%d%d%d", (int) l1, (int) l1 + 1, (int) l1 + 12) 66 != 4) 67 abort (); 68 if (memcmp (buffer, "1213", 5) || buffer[5] != 'A') 69 abort (); 70 71 if (chk_calls) 72 abort (); 73 74 memset (buffer, 'A', 32); 75 snprintf (buffer, strlen (ptr) + 1, "%s", ptr); 76 if (memcmp (buffer, "barf", 5) || buffer[5] != 'A') 77 abort (); 78 79 memset (buffer, 'A', 32); 80 snprintf (buffer, l1 + 31, "%d - %c", (int) l1 + 27, *ptr); 81 if (memcmp (buffer, "28 - b\0AAAAA", 12)) 82 abort (); 83 84 if (chk_calls != 2) 85 abort (); 86 chk_calls = 0; 87 88 memset (s4, 'A', 32); 89 snprintf (s4, l1 + 6, "%d - %c", (int) l1 - 17, ptr[1]); 90 if (memcmp (s4, "-16 - \0AAA", 10)) 91 abort (); 92 if (chk_calls) 93 abort (); 94 } 95 96 /* Test whether compile time checking is done where it should 97 and so is runtime object size checking. */ 98 void 99 __attribute__((noinline)) 100 test2 (void) 101 { 102 struct A { char buf1[10]; char buf2[10]; } a; 103 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4]; 104 char buf3[20]; 105 int i; 106 107 /* The following calls should do runtime checking 108 - length is not known, but destination is. */ 109 chk_calls = 0; 110 snprintf (a.buf1 + 2, l1, "%s", s3 + 3); 111 snprintf (r, l1 + 4, "%s%c", s3 + 3, s3[3]); 112 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 113 snprintf (r, strlen (s2) - 2, "%c %s", s2[2], s2 + 4); 114 snprintf (r + 2, l1, s3 + 3); 115 r = buf3; 116 for (i = 0; i < 4; ++i) 117 { 118 if (i == l1 - 1) 119 r = &a.buf1[1]; 120 else if (i == l1) 121 r = &a.buf2[7]; 122 else if (i == l1 + 1) 123 r = &buf3[5]; 124 else if (i == l1 + 2) 125 r = &a.buf1[9]; 126 } 127 snprintf (r, l1, s2 + 4); 128 if (chk_calls != 5) 129 abort (); 130 131 /* Following have known destination and known source length, 132 so if optimizing certainly shouldn't result in the checking 133 variants. */ 134 chk_calls = 0; 135 /* snprintf_disallowed = 1; */ 136 snprintf (a.buf1 + 2, 4, ""); 137 snprintf (r, 1, "a"); 138 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 139 snprintf (r, 3, "%s", s1 + 1); 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 snprintf (r, 1, "%s", ""); 153 snprintf (r, 0, "%s", ""); 154 snprintf_disallowed = 0; 155 /* Unknown destination and source, no checking. */ 156 snprintf (s4, l1 + 31, "%s %d", s3, 0); 157 if (chk_calls) 158 abort (); 159 } 160 161 /* Test whether runtime and/or compile time checking catches 162 buffer overflows. */ 163 void 164 __attribute__((noinline)) 165 test3 (void) 166 { 167 struct A { char buf1[10]; char buf2[10]; } a; 168 char buf3[20]; 169 170 chk_fail_allowed = 1; 171 /* Runtime checks. */ 172 if (__builtin_setjmp (chk_fail_buf) == 0) 173 { 174 snprintf (&a.buf2[9], l1 + 1, "%c%s", s2[3], s2 + 4); 175 abort (); 176 } 177 if (__builtin_setjmp (chk_fail_buf) == 0) 178 { 179 snprintf (&a.buf2[7], l1 + 30, "%s%c", s3 + strlen (s3) - 2, *s3); 180 abort (); 181 } 182 if (__builtin_setjmp (chk_fail_buf) == 0) 183 { 184 snprintf (&a.buf2[7], l1 + 3, "%d", (int) l1 + 9999); 185 abort (); 186 } 187 /* This should be detectable at compile time already. */ 188 if (__builtin_setjmp (chk_fail_buf) == 0) 189 { 190 snprintf (&buf3[19], 2, "a"); 191 abort (); 192 } 193 if (__builtin_setjmp (chk_fail_buf) == 0) 194 { 195 snprintf (&buf3[17], 4, "a"); 196 abort (); 197 } 198 if (__builtin_setjmp (chk_fail_buf) == 0) 199 { 200 snprintf (&buf3[17], 4, "%s", "abc"); 201 abort (); 202 } 203 chk_fail_allowed = 0; 204 } 205 206 void 207 main_test (void) 208 { 209 #ifndef __OPTIMIZE__ 210 /* Object size checking is only intended for -O[s123]. */ 211 return; 212 #endif 213 __asm ("" : "=r" (s2) : "0" (s2)); 214 __asm ("" : "=r" (s3) : "0" (s3)); 215 __asm ("" : "=r" (l1) : "0" (l1)); 216 s4 = p; 217 test1 (); 218 test2 (); 219 test3 (); 220 }