modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.c (about) 1 /* Copyright (C) 2004, 2005 Free Software Foundation. 2 3 Ensure builtin __strcpy_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 12 #include "chk.h" 13 14 LOCAL const char s1[] = "123"; 15 char p[32] = ""; 16 char *s2 = "defg"; 17 char *s3 = "FGH"; 18 char *s4; 19 size_t l1 = 1; 20 21 void 22 __attribute__((noinline)) 23 test1 (void) 24 { 25 chk_calls = 0; 26 #ifndef __OPTIMIZE_SIZE__ 27 strcpy_disallowed = 1; 28 #else 29 strcpy_disallowed = 0; 30 #endif 31 32 if (strcpy (p, "abcde") != p || memcmp (p, "abcde", 6)) 33 abort (); 34 if (strcpy (p + 16, "vwxyz" + 1) != p + 16 || memcmp (p + 16, "wxyz", 5)) 35 abort (); 36 if (strcpy (p + 1, "") != p + 1 || memcmp (p, "a\0cde", 6)) 37 abort (); 38 if (strcpy (p + 3, "fghij") != p + 3 || memcmp (p, "a\0cfghij", 9)) 39 abort (); 40 41 /* Test at least one instance of the __builtin_ style. We do this 42 to ensure that it works and that the prototype is correct. */ 43 if (__builtin_strcpy (p, "abcde") != p || memcmp (p, "abcde", 6)) 44 abort (); 45 46 strcpy_disallowed = 0; 47 if (chk_calls) 48 abort (); 49 } 50 51 #ifndef MAX_OFFSET 52 #define MAX_OFFSET (sizeof (long long)) 53 #endif 54 55 #ifndef MAX_COPY 56 #define MAX_COPY (10 * sizeof (long long)) 57 #endif 58 59 #ifndef MAX_EXTRA 60 #define MAX_EXTRA (sizeof (long long)) 61 #endif 62 63 #define MAX_LENGTH (MAX_OFFSET + MAX_COPY + 1 + MAX_EXTRA) 64 65 /* Use a sequence length that is not divisible by two, to make it more 66 likely to detect when words are mixed up. */ 67 #define SEQUENCE_LENGTH 31 68 69 static union { 70 char buf[MAX_LENGTH]; 71 long long align_int; 72 long double align_fp; 73 } u1, u2; 74 75 void 76 __attribute__((noinline)) 77 test2 (void) 78 { 79 int off1, off2, len, i; 80 char *p, *q, c; 81 82 for (off1 = 0; off1 < MAX_OFFSET; off1++) 83 for (off2 = 0; off2 < MAX_OFFSET; off2++) 84 for (len = 1; len < MAX_COPY; len++) 85 { 86 for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++) 87 { 88 u1.buf[i] = 'a'; 89 if (c >= 'A' + SEQUENCE_LENGTH) 90 c = 'A'; 91 u2.buf[i] = c; 92 } 93 u2.buf[off2 + len] = '\0'; 94 95 p = strcpy (u1.buf + off1, u2.buf + off2); 96 if (p != u1.buf + off1) 97 abort (); 98 99 q = u1.buf; 100 for (i = 0; i < off1; i++, q++) 101 if (*q != 'a') 102 abort (); 103 104 for (i = 0, c = 'A' + off2; i < len; i++, q++, c++) 105 { 106 if (c >= 'A' + SEQUENCE_LENGTH) 107 c = 'A'; 108 if (*q != c) 109 abort (); 110 } 111 112 if (*q++ != '\0') 113 abort (); 114 for (i = 0; i < MAX_EXTRA; i++, q++) 115 if (*q != 'a') 116 abort (); 117 } 118 } 119 120 /* Test whether compile time checking is done where it should 121 and so is runtime object size checking. */ 122 void 123 __attribute__((noinline)) 124 test3 (void) 125 { 126 struct A { char buf1[10]; char buf2[10]; } a; 127 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4]; 128 char buf3[20]; 129 int i; 130 const char *l; 131 132 /* The following calls should do runtime checking 133 - source length is not known, but destination is. */ 134 chk_calls = 0; 135 strcpy (a.buf1 + 2, s3 + 3); 136 strcpy (r, s3 + 2); 137 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 138 strcpy (r, s2 + 2); 139 strcpy (r + 2, s3 + 3); 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 strcpy (r, s2 + 4); 153 if (chk_calls != 5) 154 abort (); 155 156 /* Following have known destination and known source length, 157 so if optimizing certainly shouldn't result in the checking 158 variants. */ 159 chk_calls = 0; 160 strcpy (a.buf1 + 2, ""); 161 strcpy (r, "a"); 162 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 163 strcpy (r, s1 + 1); 164 r = buf3; 165 l = "abc"; 166 for (i = 0; i < 4; ++i) 167 { 168 if (i == l1 - 1) 169 r = &a.buf1[1], l = "e"; 170 else if (i == l1) 171 r = &a.buf2[7], l = "gh"; 172 else if (i == l1 + 1) 173 r = &buf3[5], l = "jkl"; 174 else if (i == l1 + 2) 175 r = &a.buf1[9], l = ""; 176 } 177 strcpy (r, ""); 178 /* Here, strlen (l) + 1 is known to be at most 4 and 179 __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need 180 runtime checking. */ 181 strcpy (&buf3[16], l); 182 /* Unknown destination and source, no checking. */ 183 strcpy (s4, s3); 184 if (chk_calls) 185 abort (); 186 chk_calls = 0; 187 } 188 189 /* Test whether runtime and/or compile time checking catches 190 buffer overflows. */ 191 void 192 __attribute__((noinline)) 193 test4 (void) 194 { 195 struct A { char buf1[10]; char buf2[10]; } a; 196 char buf3[20]; 197 198 chk_fail_allowed = 1; 199 /* Runtime checks. */ 200 if (__builtin_setjmp (chk_fail_buf) == 0) 201 { 202 strcpy (&a.buf2[9], s2 + 3); 203 abort (); 204 } 205 if (__builtin_setjmp (chk_fail_buf) == 0) 206 { 207 strcpy (&a.buf2[7], s3 + strlen (s3) - 3); 208 abort (); 209 } 210 /* This should be detectable at compile time already. */ 211 if (__builtin_setjmp (chk_fail_buf) == 0) 212 { 213 strcpy (&buf3[19], "a"); 214 abort (); 215 } 216 chk_fail_allowed = 0; 217 } 218 219 void 220 main_test (void) 221 { 222 #ifndef __OPTIMIZE__ 223 /* Object size checking is only intended for -O[s123]. */ 224 return; 225 #endif 226 __asm ("" : "=r" (s2) : "0" (s2)); 227 __asm ("" : "=r" (s3) : "0" (s3)); 228 __asm ("" : "=r" (l1) : "0" (l1)); 229 test1 (); 230 test2 (); 231 s4 = p; 232 test3 (); 233 test4 (); 234 }