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