1#include <stdarg.h> 2 3extern void abort (void); 4 5extern int inside_main; 6void *chk_fail_buf[256] __attribute__((aligned (16))); 7volatile int chk_fail_allowed, chk_calls; 8volatile int memcpy_disallowed, mempcpy_disallowed, memmove_disallowed; 9volatile int memset_disallowed, strcpy_disallowed, stpcpy_disallowed; 10volatile int strncpy_disallowed, strcat_disallowed, strncat_disallowed; 11volatile int sprintf_disallowed, vsprintf_disallowed; 12volatile int snprintf_disallowed, vsnprintf_disallowed; 13extern __SIZE_TYPE__ strlen (const char *); 14extern int vsprintf (char *, const char *, va_list); 15 16void __attribute__((noreturn)) 17__chk_fail (void) 18{ 19 if (chk_fail_allowed) 20 __builtin_longjmp (chk_fail_buf, 1); 21 abort (); 22} 23 24void * 25memcpy (void *dst, const void *src, __SIZE_TYPE__ n) 26{ 27 const char *srcp; 28 char *dstp; 29 30#ifdef __OPTIMIZE__ 31 if (memcpy_disallowed && inside_main) 32 abort (); 33#endif 34 35 srcp = src; 36 dstp = dst; 37 while (n-- != 0) 38 *dstp++ = *srcp++; 39 40 return dst; 41} 42 43void * 44__memcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 45{ 46 /* If size is -1, GCC should always optimize the call into memcpy. */ 47 if (size == (__SIZE_TYPE__) -1) 48 abort (); 49 ++chk_calls; 50 if (n > size) 51 __chk_fail (); 52 return memcpy (dst, src, n); 53} 54 55void * 56mempcpy (void *dst, const void *src, __SIZE_TYPE__ n) 57{ 58 const char *srcp; 59 char *dstp; 60 61#ifdef __OPTIMIZE__ 62 if (mempcpy_disallowed && inside_main) 63 abort (); 64#endif 65 66 srcp = src; 67 dstp = dst; 68 while (n-- != 0) 69 *dstp++ = *srcp++; 70 71 return dstp; 72} 73 74void * 75__mempcpy_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 76{ 77 /* If size is -1, GCC should always optimize the call into mempcpy. */ 78 if (size == (__SIZE_TYPE__) -1) 79 abort (); 80 ++chk_calls; 81 if (n > size) 82 __chk_fail (); 83 return mempcpy (dst, src, n); 84} 85 86void * 87memmove (void *dst, const void *src, __SIZE_TYPE__ n) 88{ 89 const char *srcp; 90 char *dstp; 91 92#ifdef __OPTIMIZE__ 93 if (memmove_disallowed && inside_main) 94 abort (); 95#endif 96 97 srcp = src; 98 dstp = dst; 99 if (srcp < dstp) 100 while (n-- != 0) 101 dstp[n] = srcp[n]; 102 else 103 while (n-- != 0) 104 *dstp++ = *srcp++; 105 106 return dst; 107} 108 109void * 110__memmove_chk (void *dst, const void *src, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 111{ 112 /* If size is -1, GCC should always optimize the call into memmove. */ 113 if (size == (__SIZE_TYPE__) -1) 114 abort (); 115 ++chk_calls; 116 if (n > size) 117 __chk_fail (); 118 return memmove (dst, src, n); 119} 120 121void * 122memset (void *dst, int c, __SIZE_TYPE__ n) 123{ 124 /* Single-byte memsets should be done inline when optimisation 125 is enabled. */ 126#ifdef __OPTIMIZE__ 127 if (memset_disallowed && inside_main && n < 2) 128 abort (); 129#endif 130 131 while (n-- != 0) 132 n[(char *) dst] = c; 133 134 return dst; 135} 136 137void * 138__memset_chk (void *dst, int c, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 139{ 140 /* If size is -1, GCC should always optimize the call into memset. */ 141 if (size == (__SIZE_TYPE__) -1) 142 abort (); 143 ++chk_calls; 144 if (n > size) 145 __chk_fail (); 146 return memset (dst, c, n); 147} 148 149char * 150strcpy (char *d, const char *s) 151{ 152 char *r = d; 153#ifdef __OPTIMIZE__ 154 if (strcpy_disallowed && inside_main) 155 abort (); 156#endif 157 while ((*d++ = *s++)); 158 return r; 159} 160 161char * 162__strcpy_chk (char *d, const char *s, __SIZE_TYPE__ size) 163{ 164 /* If size is -1, GCC should always optimize the call into strcpy. */ 165 if (size == (__SIZE_TYPE__) -1) 166 abort (); 167 ++chk_calls; 168 if (strlen (s) >= size) 169 __chk_fail (); 170 return strcpy (d, s); 171} 172 173char * 174stpcpy (char *dst, const char *src) 175{ 176#ifdef __OPTIMIZE__ 177 if (stpcpy_disallowed && inside_main) 178 abort (); 179#endif 180 181 while (*src != 0) 182 *dst++ = *src++; 183 184 *dst = 0; 185 return dst; 186} 187 188char * 189__stpcpy_chk (char *d, const char *s, __SIZE_TYPE__ size) 190{ 191 /* If size is -1, GCC should always optimize the call into stpcpy. */ 192 if (size == (__SIZE_TYPE__) -1) 193 abort (); 194 ++chk_calls; 195 if (strlen (s) >= size) 196 __chk_fail (); 197 return stpcpy (d, s); 198} 199 200char * 201strncpy (char *s1, const char *s2, __SIZE_TYPE__ n) 202{ 203 char *dest = s1; 204#ifdef __OPTIMIZE__ 205 if (strncpy_disallowed && inside_main) 206 abort(); 207#endif 208 for (; *s2 && n; n--) 209 *s1++ = *s2++; 210 while (n--) 211 *s1++ = 0; 212 return dest; 213} 214 215char * 216__strncpy_chk (char *s1, const char *s2, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 217{ 218 /* If size is -1, GCC should always optimize the call into strncpy. */ 219 if (size == (__SIZE_TYPE__) -1) 220 abort (); 221 ++chk_calls; 222 if (n > size) 223 __chk_fail (); 224 return strncpy (s1, s2, n); 225} 226 227char * 228strcat (char *dst, const char *src) 229{ 230 char *p = dst; 231 232#ifdef __OPTIMIZE__ 233 if (strcat_disallowed && inside_main) 234 abort (); 235#endif 236 237 while (*p) 238 p++; 239 while ((*p++ = *src++)) 240 ; 241 return dst; 242} 243 244char * 245__strcat_chk (char *d, const char *s, __SIZE_TYPE__ size) 246{ 247 /* If size is -1, GCC should always optimize the call into strcat. */ 248 if (size == (__SIZE_TYPE__) -1) 249 abort (); 250 ++chk_calls; 251 if (strlen (d) + strlen (s) >= size) 252 __chk_fail (); 253 return strcat (d, s); 254} 255 256char * 257strncat (char *s1, const char *s2, __SIZE_TYPE__ n) 258{ 259 char *dest = s1; 260 char c; 261#ifdef __OPTIMIZE__ 262 if (strncat_disallowed && inside_main) 263 abort(); 264#endif 265 while (*s1) s1++; 266 c = '\0'; 267 while (n > 0) 268 { 269 c = *s2++; 270 *s1++ = c; 271 if (c == '\0') 272 return dest; 273 n--; 274 } 275 if (c != '\0') 276 *s1 = '\0'; 277 return dest; 278} 279 280char * 281__strncat_chk (char *d, const char *s, __SIZE_TYPE__ n, __SIZE_TYPE__ size) 282{ 283 __SIZE_TYPE__ len = strlen (d), n1 = n; 284 const char *s1 = s; 285 286 /* If size is -1, GCC should always optimize the call into strncat. */ 287 if (size == (__SIZE_TYPE__) -1) 288 abort (); 289 ++chk_calls; 290 while (len < size && n1 > 0) 291 { 292 if (*s1++ == '\0') 293 break; 294 ++len; 295 --n1; 296 } 297 298 if (len >= size) 299 __chk_fail (); 300 return strncat (d, s, n); 301} 302 303/* No chk test in GCC testsuite needs more bytes than this. 304 As we can't expect vsnprintf to be available on the target, 305 assume 4096 bytes is enough. */ 306static char chk_sprintf_buf[4096]; 307 308int 309__sprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, ...) 310{ 311 int ret; 312 va_list ap; 313 314 /* If size is -1 and flag 0, GCC should always optimize the call into 315 sprintf. */ 316 if (size == (__SIZE_TYPE__) -1 && flag == 0) 317 abort (); 318 ++chk_calls; 319#ifdef __OPTIMIZE__ 320 if (sprintf_disallowed && inside_main) 321 abort(); 322#endif 323 va_start (ap, fmt); 324 ret = vsprintf (chk_sprintf_buf, fmt, ap); 325 va_end (ap); 326 if (ret >= 0) 327 { 328 if (ret >= size) 329 __chk_fail (); 330 memcpy (str, chk_sprintf_buf, ret + 1); 331 } 332 return ret; 333} 334 335int 336__vsprintf_chk (char *str, int flag, __SIZE_TYPE__ size, const char *fmt, 337 va_list ap) 338{ 339 int ret; 340 341 /* If size is -1 and flag 0, GCC should always optimize the call into 342 vsprintf. */ 343 if (size == (__SIZE_TYPE__) -1 && flag == 0) 344 abort (); 345 ++chk_calls; 346#ifdef __OPTIMIZE__ 347 if (vsprintf_disallowed && inside_main) 348 abort(); 349#endif 350 ret = vsprintf (chk_sprintf_buf, fmt, ap); 351 if (ret >= 0) 352 { 353 if (ret >= size) 354 __chk_fail (); 355 memcpy (str, chk_sprintf_buf, ret + 1); 356 } 357 return ret; 358} 359 360int 361__snprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size, 362 const char *fmt, ...) 363{ 364 int ret; 365 va_list ap; 366 367 /* If size is -1 and flag 0, GCC should always optimize the call into 368 snprintf. */ 369 if (size == (__SIZE_TYPE__) -1 && flag == 0) 370 abort (); 371 ++chk_calls; 372 if (size < len) 373 __chk_fail (); 374#ifdef __OPTIMIZE__ 375 if (snprintf_disallowed && inside_main) 376 abort(); 377#endif 378 va_start (ap, fmt); 379 ret = vsprintf (chk_sprintf_buf, fmt, ap); 380 va_end (ap); 381 if (ret >= 0) 382 { 383 if (ret < len) 384 memcpy (str, chk_sprintf_buf, ret + 1); 385 else 386 { 387 memcpy (str, chk_sprintf_buf, len - 1); 388 str[len - 1] = '\0'; 389 } 390 } 391 return ret; 392} 393 394int 395__vsnprintf_chk (char *str, __SIZE_TYPE__ len, int flag, __SIZE_TYPE__ size, 396 const char *fmt, va_list ap) 397{ 398 int ret; 399 400 /* If size is -1 and flag 0, GCC should always optimize the call into 401 vsnprintf. */ 402 if (size == (__SIZE_TYPE__) -1 && flag == 0) 403 abort (); 404 ++chk_calls; 405 if (size < len) 406 __chk_fail (); 407#ifdef __OPTIMIZE__ 408 if (vsnprintf_disallowed && inside_main) 409 abort(); 410#endif 411 ret = vsprintf (chk_sprintf_buf, fmt, ap); 412 if (ret >= 0) 413 { 414 if (ret < len) 415 memcpy (str, chk_sprintf_buf, ret + 1); 416 else 417 { 418 memcpy (str, chk_sprintf_buf, len - 1); 419 str[len - 1] = '\0'; 420 } 421 } 422 return ret; 423} 424 425int 426snprintf (char *str, __SIZE_TYPE__ len, const char *fmt, ...) 427{ 428 int ret; 429 va_list ap; 430 431#ifdef __OPTIMIZE__ 432 if (snprintf_disallowed && inside_main) 433 abort(); 434#endif 435 va_start (ap, fmt); 436 ret = vsprintf (chk_sprintf_buf, fmt, ap); 437 va_end (ap); 438 if (ret >= 0) 439 { 440 if (ret < len) 441 memcpy (str, chk_sprintf_buf, ret + 1); 442 else if (len) 443 { 444 memcpy (str, chk_sprintf_buf, len - 1); 445 str[len - 1] = '\0'; 446 } 447 } 448 return ret; 449} 450 451int 452vsnprintf (char *str, __SIZE_TYPE__ len, const char *fmt, va_list ap) 453{ 454 int ret; 455 456#ifdef __OPTIMIZE__ 457 if (vsnprintf_disallowed && inside_main) 458 abort(); 459#endif 460 ret = vsprintf (chk_sprintf_buf, fmt, ap); 461 if (ret >= 0) 462 { 463 if (ret < len) 464 memcpy (str, chk_sprintf_buf, ret + 1); 465 else if (len) 466 { 467 memcpy (str, chk_sprintf_buf, len - 1); 468 str[len - 1] = '\0'; 469 } 470 } 471 return ret; 472} 473