modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/builtins/stpncpy-chk.c (about) 1 /* Copyright (C) 2004, 2005, 2011 Free Software Foundation. 2 3 Ensure builtin __stpncpy_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 *stpncpy (char *, const char *, size_t); 10 extern int memcmp (const void *, const void *, size_t); 11 extern int strcmp (const char *, const char *); 12 extern int strncmp (const char *, const char *, size_t); 13 extern void *memset (void *, int, size_t); 14 15 #include "chk.h" 16 17 const char s1[] = "123"; 18 char p[32] = ""; 19 char * volatile s2 = "defg"; /* prevent constant propagation to happen when whole program assumptions are made. */ 20 char * volatile s3 = "FGH"; /* prevent constant propagation to happen when whole program assumptions are made. */ 21 char *s4; 22 volatile size_t l1 = 1; /* prevent constant propagation to happen when whole program assumptions are made. */ 23 int i; 24 25 void 26 __attribute__((noinline)) 27 test1 (void) 28 { 29 const char *const src = "hello world"; 30 const char *src2; 31 char dst[64], *dst2; 32 33 chk_calls = 0; 34 35 memset (dst, 0, sizeof (dst)); 36 if (stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4)) 37 abort(); 38 39 memset (dst, 0, sizeof (dst)); 40 if (stpncpy (dst+16, src, 4) != dst+20 || strncmp (dst+16, src, 4)) 41 abort(); 42 43 memset (dst, 0, sizeof (dst)); 44 if (stpncpy (dst+32, src+5, 4) != dst+36 || strncmp (dst+32, src+5, 4)) 45 abort(); 46 47 memset (dst, 0, sizeof (dst)); 48 dst2 = dst; 49 if (stpncpy (++dst2, src+5, 4) != dst+5 || strncmp (dst2, src+5, 4) 50 || dst2 != dst+1) 51 abort(); 52 53 memset (dst, 0, sizeof (dst)); 54 if (stpncpy (dst, src, 0) != dst || strcmp (dst, "")) 55 abort(); 56 57 memset (dst, 0, sizeof (dst)); 58 dst2 = dst; src2 = src; 59 if (stpncpy (++dst2, ++src2, 0) != dst+1 || strcmp (dst2, "") 60 || dst2 != dst+1 || src2 != src+1) 61 abort(); 62 63 memset (dst, 0, sizeof (dst)); 64 dst2 = dst; src2 = src; 65 if (stpncpy (++dst2+5, ++src2+5, 0) != dst+6 || strcmp (dst2+5, "") 66 || dst2 != dst+1 || src2 != src+1) 67 abort(); 68 69 memset (dst, 0, sizeof (dst)); 70 if (stpncpy (dst, src, 12) != dst+11 || strcmp (dst, src)) 71 abort(); 72 73 /* Test at least one instance of the __builtin_ style. We do this 74 to ensure that it works and that the prototype is correct. */ 75 memset (dst, 0, sizeof (dst)); 76 if (__builtin_stpncpy (dst, src, 4) != dst+4 || strncmp (dst, src, 4)) 77 abort(); 78 79 memset (dst, 0, sizeof (dst)); 80 if (stpncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst+3 81 || strcmp (dst, "bar") 82 || i != 1) 83 abort (); 84 85 /* If return value of stpncpy is ignored, it should be optimized into 86 stpncpy call. */ 87 stpncpy_disallowed = 1; 88 stpncpy (dst + 1, src, 4); 89 stpncpy_disallowed = 0; 90 if (strncmp (dst + 1, src, 4)) 91 abort (); 92 93 if (chk_calls) 94 abort (); 95 } 96 97 void 98 __attribute__((noinline)) 99 test2 (void) 100 { 101 chk_calls = 0; 102 103 /* No runtime checking should be done here, both destination 104 and length are unknown. */ 105 size_t cpy_length = l1 < 4 ? l1 + 1 : 4; 106 if (stpncpy (s4, "abcd", l1 + 1) != s4 + cpy_length || strncmp (s4, "abcd", cpy_length)) 107 abort (); 108 109 if (chk_calls) 110 abort (); 111 } 112 113 /* Test whether compile time checking is done where it should 114 and so is runtime object size checking. */ 115 void 116 __attribute__((noinline)) 117 test3 (void) 118 { 119 struct A { char buf1[10]; char buf2[10]; } a; 120 char *r = l1 == 1 ? &a.buf1[5] : &a.buf2[4]; 121 char buf3[20]; 122 int i; 123 const char *l; 124 size_t l2; 125 126 /* The following calls should do runtime checking 127 - source length is not known, but destination is. 128 The returned value is checked so that stpncpy calls 129 are not rewritten to strncpy calls. */ 130 chk_calls = 0; 131 if (!stpncpy (a.buf1 + 2, s3 + 3, l1)) 132 abort(); 133 if (!stpncpy (r, s3 + 2, l1 + 2)) 134 abort(); 135 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 136 if (!stpncpy (r, s2 + 2, l1 + 2)) 137 abort(); 138 if (!stpncpy (r + 2, s3 + 3, l1)) 139 abort(); 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 if (!stpncpy (r, s2 + 4, l1)) 153 abort(); 154 if (chk_calls != 5) 155 abort (); 156 157 /* Following have known destination and known length, 158 so if optimizing certainly shouldn't result in the checking 159 variants. */ 160 chk_calls = 0; 161 if (!stpncpy (a.buf1 + 2, "", 3)) 162 abort (); 163 if (!stpncpy (a.buf1 + 2, "", 0)) 164 abort (); 165 if (!stpncpy (r, "a", 1)) 166 abort (); 167 if (!stpncpy (r, "a", 3)) 168 abort (); 169 r = l1 == 1 ? __builtin_alloca (4) : &a.buf2[7]; 170 if (!stpncpy (r, s1 + 1, 3)) 171 abort (); 172 if (!stpncpy (r, s1 + 1, 2)) 173 abort (); 174 r = buf3; 175 l = "abc"; 176 l2 = 4; 177 for (i = 0; i < 4; ++i) 178 { 179 if (i == l1 - 1) 180 r = &a.buf1[1], l = "e", l2 = 2; 181 else if (i == l1) 182 r = &a.buf2[7], l = "gh", l2 = 3; 183 else if (i == l1 + 1) 184 r = &buf3[5], l = "jkl", l2 = 4; 185 else if (i == l1 + 2) 186 r = &a.buf1[9], l = "", l2 = 1; 187 } 188 if (!stpncpy (r, "", 1)) 189 abort (); 190 /* Here, strlen (l) + 1 is known to be at most 4 and 191 __builtin_object_size (&buf3[16], 0) is 4, so this doesn't need 192 runtime checking. */ 193 if (!stpncpy (&buf3[16], l, l2)) 194 abort (); 195 if (!stpncpy (&buf3[15], "abc", l2)) 196 abort (); 197 if (!stpncpy (&buf3[10], "fghij", l2)) 198 abort (); 199 if (chk_calls) 200 abort (); 201 chk_calls = 0; 202 } 203 204 /* Test whether runtime and/or compile time checking catches 205 buffer overflows. */ 206 void 207 __attribute__((noinline)) 208 test4 (void) 209 { 210 struct A { char buf1[10]; char buf2[10]; } a; 211 char buf3[20]; 212 213 chk_fail_allowed = 1; 214 /* Runtime checks. */ 215 if (__builtin_setjmp (chk_fail_buf) == 0) 216 { 217 if (stpncpy (&a.buf2[9], s2 + 4, l1 + 1)) 218 // returned value used to prevent stpncpy calls 219 // to be rewritten in strncpy calls 220 i++; 221 abort (); 222 } 223 if (__builtin_setjmp (chk_fail_buf) == 0) 224 { 225 if (stpncpy (&a.buf2[7], s3, l1 + 4)) 226 i++; 227 abort (); 228 } 229 /* This should be detectable at compile time already. */ 230 if (__builtin_setjmp (chk_fail_buf) == 0) 231 { 232 if (stpncpy (&buf3[19], "abc", 2)) 233 i++; 234 abort (); 235 } 236 if (__builtin_setjmp (chk_fail_buf) == 0) 237 { 238 if (stpncpy (&buf3[18], "", 3)) 239 i++; 240 abort (); 241 } 242 chk_fail_allowed = 0; 243 } 244 245 void 246 main_test (void) 247 { 248 #ifndef __OPTIMIZE__ 249 /* Object size checking is only intended for -O[s123]. */ 250 return; 251 #endif 252 __asm ("" : "=r" (s2) : "0" (s2)); 253 __asm ("" : "=r" (s3) : "0" (s3)); 254 __asm ("" : "=r" (l1) : "0" (l1)); 255 test1 (); 256 257 s4 = p; 258 test2 (); 259 test3 (); 260 test4 (); 261 }