1 2/*--------------------------------------------------------------------*/ 3/*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/ 4/*--- simulated CPU. ---*/ 5/*--- mc_replace_strmem.c ---*/ 6/*--------------------------------------------------------------------*/ 7 8/* 9 This file is part of MemCheck, a heavyweight Valgrind tool for 10 detecting memory errors. 11 12 Copyright (C) 2000-2011 Julian Seward 13 jseward@acm.org 14 15 This program is free software; you can redistribute it and/or 16 modify it under the terms of the GNU General Public License as 17 published by the Free Software Foundation; either version 2 of the 18 License, or (at your option) any later version. 19 20 This program is distributed in the hope that it will be useful, but 21 WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 General Public License for more details. 24 25 You should have received a copy of the GNU General Public License 26 along with this program; if not, write to the Free Software 27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 28 02111-1307, USA. 29 30 The GNU General Public License is contained in the file COPYING. 31*/ 32 33#include "pub_tool_basics.h" 34#include "pub_tool_hashtable.h" 35#include "pub_tool_redir.h" 36#include "pub_tool_tooliface.h" 37#include "valgrind.h" 38 39#include "mc_include.h" 40#include "memcheck.h" 41 42/* --------------------------------------------------------------------- 43 We have our own versions of these functions for two reasons: 44 (a) it allows us to do overlap checking 45 (b) some of the normal versions are hyper-optimised, which fools 46 Memcheck and cause spurious value warnings. Our versions are 47 simpler. 48 49 Note that overenthusiastic use of PLT bypassing by the glibc people also 50 means that we need to patch multiple versions of some of the functions to 51 our own implementations. 52 53 THEY RUN ON THE SIMD CPU! 54 ------------------------------------------------------------------ */ 55 56/* Assignment of behavioural equivalence class tags: 2NNNP is intended 57 to be reserved for Memcheck. Current usage: 58 59 20010 STRRCHR 60 20020 STRCHR 61 20030 STRCAT 62 20040 STRNCAT 63 20050 STRLCAT 64 20060 STRNLEN 65 20070 STRLEN 66 20080 STRCPY 67 20090 STRNCPY 68 20100 STRLCPY 69 20110 STRNCMP 70 20120 STRCASECMP 71 20130 STRNCASECMP 72 20140 STRCASECMP_L 73 20150 STRNCASECMP_L 74 20160 STRCMP 75 20170 MEMCHR 76 77 20180 MEMCPY if there's a conflict between memcpy and 78 20181 MEMMOVE memmove, prefer memmove 79 80 20190 MEMCMP 81 20200 STPCPY 82 20210 MEMSET 83 2022P unused (was previously MEMMOVE) 84 20230 BCOPY 85 20240 GLIBC25___MEMMOVE_CHK 86 20250 GLIBC232_STRCHRNUL 87 20260 GLIBC232_RAWMEMCHR 88 20270 GLIBC25___STRCPY_CHK 89 20280 GLIBC25___STPCPY_CHK 90 20290 GLIBC25_MEMPCPY 91 20300 GLIBC26___MEMCPY_CHK 92 20310 STRSTR 93 20320 STRPBRK 94 20330 STRCSPN 95 20340 STRSPN 96 20350 STRCASESTR 97*/ 98 99 100/* Figure out if [dst .. dst+dstlen-1] overlaps with 101 [src .. src+srclen-1]. 102 We assume that the address ranges do not wrap around 103 (which is safe since on Linux addresses >= 0xC0000000 104 are not accessible and the program will segfault in this 105 circumstance, presumably). 106*/ 107static inline 108Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen ) 109{ 110 Addr loS, hiS, loD, hiD; 111 112 if (dstlen == 0 || srclen == 0) 113 return False; 114 115 loS = (Addr)src; 116 loD = (Addr)dst; 117 hiS = loS + srclen - 1; 118 hiD = loD + dstlen - 1; 119 120 /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */ 121 if (loS < loD) { 122 return !(hiS < loD); 123 } 124 else if (loD < loS) { 125 return !(hiD < loS); 126 } 127 else { 128 /* They start at same place. Since we know neither of them has 129 zero length, they must overlap. */ 130 return True; 131 } 132} 133 134 135/* Call here to exit if we can't continue. On Android we can't call 136 _exit for some reason, so we have to blunt-instrument it. */ 137__attribute__ ((__noreturn__)) 138static inline void my_exit ( int x ) 139{ 140# if defined(VGPV_arm_linux_android) 141 __asm__ __volatile__(".word 0xFFFFFFFF"); 142 while (1) {} 143# else 144 extern __attribute__ ((__noreturn__)) void _exit(int status); 145 _exit(x); 146# endif 147} 148 149 150// This is a macro rather than a function because we don't want to have an 151// extra function in the stack trace. 152#define RECORD_OVERLAP_ERROR(s, src, dst, len) \ 153 VALGRIND_DO_CLIENT_REQUEST_STMT( \ 154 _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \ 155 s, src, dst, len, 0) 156 157 158/*---------------------- strrchr ----------------------*/ 159 160#define STRRCHR(soname, fnname) \ 161 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \ 162 char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \ 163 { \ 164 UChar ch = (UChar)((UInt)c); \ 165 UChar* p = (UChar*)s; \ 166 UChar* last = NULL; \ 167 while (True) { \ 168 if (*p == ch) last = p; \ 169 if (*p == 0) return last; \ 170 p++; \ 171 } \ 172 } 173 174// Apparently rindex() is the same thing as strrchr() 175#if defined(VGO_linux) 176 STRRCHR(VG_Z_LIBC_SONAME, strrchr) 177 STRRCHR(VG_Z_LIBC_SONAME, rindex) 178 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) 179 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) 180 181#elif defined(VGO_darwin) 182 //STRRCHR(VG_Z_LIBC_SONAME, strrchr) 183 STRRCHR(VG_Z_LIBC_SONAME, rindex) 184 STRRCHR(VG_Z_DYLD, strrchr) 185 STRRCHR(VG_Z_DYLD, rindex) 186 STRRCHR(VG_Z_LIBC_SONAME, strrchr) 187 188#endif 189 190 191/*---------------------- strchr ----------------------*/ 192 193#define STRCHR(soname, fnname) \ 194 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \ 195 char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \ 196 { \ 197 UChar ch = (UChar)((UInt)c); \ 198 UChar* p = (UChar*)s; \ 199 while (True) { \ 200 if (*p == ch) return p; \ 201 if (*p == 0) return NULL; \ 202 p++; \ 203 } \ 204 } 205 206// Apparently index() is the same thing as strchr() 207#if defined(VGO_linux) 208 STRCHR(VG_Z_LIBC_SONAME, strchr) 209 STRCHR(VG_Z_LIBC_SONAME, index) 210 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 211# if !defined(VGP_x86_linux) 212 STRCHR(VG_Z_LD_LINUX_SO_2, strchr) 213 STRCHR(VG_Z_LD_LINUX_SO_2, index) 214 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) 215 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) 216# endif 217 218#elif defined(VGO_darwin) 219 //STRCHR(VG_Z_LIBC_SONAME, strchr) 220 STRCHR(VG_Z_LIBC_SONAME, index) 221 STRCHR(VG_Z_DYLD, strchr) 222 STRCHR(VG_Z_DYLD, index) 223 STRCHR(VG_Z_LIBC_SONAME, strchr) 224 225#endif 226 227 228/*---------------------- strcat ----------------------*/ 229 230#define STRCAT(soname, fnname) \ 231 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 232 ( char* dst, const char* src ); \ 233 char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 234 ( char* dst, const char* src ) \ 235 { \ 236 const Char* src_orig = src; \ 237 Char* dst_orig = dst; \ 238 while (*dst) dst++; \ 239 while (*src) *dst++ = *src++; \ 240 *dst = 0; \ 241 \ 242 /* This is a bit redundant, I think; any overlap and the strcat will */ \ 243 /* go forever... or until a seg fault occurs. */ \ 244 if (is_overlap(dst_orig, \ 245 src_orig, \ 246 (Addr)dst-(Addr)dst_orig+1, \ 247 (Addr)src-(Addr)src_orig+1)) \ 248 RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \ 249 \ 250 return dst_orig; \ 251 } 252 253#if defined(VGO_linux) 254 STRCAT(VG_Z_LIBC_SONAME, strcat) 255 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) 256 257#elif defined(VGO_darwin) 258 STRCAT(VG_Z_LIBC_SONAME, strcat) 259 260#endif 261 262 263/*---------------------- strncat ----------------------*/ 264 265#define STRNCAT(soname, fnname) \ 266 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 267 ( char* dst, const char* src, SizeT n ); \ 268 char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 269 ( char* dst, const char* src, SizeT n ) \ 270 { \ 271 const Char* src_orig = src; \ 272 Char* dst_orig = dst; \ 273 SizeT m = 0; \ 274 \ 275 while (*dst) dst++; \ 276 while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \ 277 *dst = 0; /* always add null */ \ 278 \ 279 /* This checks for overlap after copying, unavoidable without */ \ 280 /* pre-counting lengths... should be ok */ \ 281 if (is_overlap(dst_orig, \ 282 src_orig, \ 283 (Addr)dst-(Addr)dst_orig+1, \ 284 (Addr)src-(Addr)src_orig+1)) \ 285 RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \ 286 \ 287 return dst_orig; \ 288 } 289 290#if defined(VGO_linux) 291 STRNCAT(VG_Z_LIBC_SONAME, strncat) 292 293#elif defined(VGO_darwin) 294 STRNCAT(VG_Z_LIBC_SONAME, strncat) 295 STRNCAT(VG_Z_DYLD, strncat) 296 297#endif 298 299 300/*---------------------- strlcat ----------------------*/ 301 302/* Append src to dst. n is the size of dst's buffer. dst is guaranteed 303 to be nul-terminated after the copy, unless n <= strlen(dst_orig). 304 Returns min(n, strlen(dst_orig)) + strlen(src_orig). 305 Truncation occurred if retval >= n. 306*/ 307#define STRLCAT(soname, fnname) \ 308 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 309 ( char* dst, const char* src, SizeT n ); \ 310 SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 311 ( char* dst, const char* src, SizeT n ) \ 312 { \ 313 const Char* src_orig = src; \ 314 Char* dst_orig = dst; \ 315 SizeT m = 0; \ 316 \ 317 while (m < n && *dst) { m++; dst++; } \ 318 if (m < n) { \ 319 /* Fill as far as dst_orig[n-2], then nul-terminate. */ \ 320 while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 321 *dst = 0; \ 322 } else { \ 323 /* No space to copy anything to dst. m == n */ \ 324 } \ 325 /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \ 326 while (*src) { m++; src++; } \ 327 /* This checks for overlap after copying, unavoidable without */ \ 328 /* pre-counting lengths... should be ok */ \ 329 if (is_overlap(dst_orig, \ 330 src_orig, \ 331 (Addr)dst-(Addr)dst_orig+1, \ 332 (Addr)src-(Addr)src_orig+1)) \ 333 RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \ 334 \ 335 return m; \ 336 } 337 338#if defined(VGO_linux) 339 340#elif defined(VGO_darwin) 341 //STRLCAT(VG_Z_LIBC_SONAME, strlcat) 342 STRLCAT(VG_Z_DYLD, strlcat) 343 STRLCAT(VG_Z_LIBC_SONAME, strlcat) 344 345#endif 346 347 348/*---------------------- strnlen ----------------------*/ 349 350#define STRNLEN(soname, fnname) \ 351 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 352 ( const char* str, SizeT n ); \ 353 SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 354 ( const char* str, SizeT n ) \ 355 { \ 356 SizeT i = 0; \ 357 while (i < n && str[i] != 0) i++; \ 358 return i; \ 359 } 360 361#if defined(VGO_linux) 362 STRNLEN(VG_Z_LIBC_SONAME, strnlen) 363 STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) 364 365#elif defined(VGO_darwin) 366 STRNLEN(VG_Z_LIBC_SONAME, strnlen) 367 368#endif 369 370 371/*---------------------- strlen ----------------------*/ 372 373// Note that this replacement often doesn't get used because gcc inlines 374// calls to strlen() with its own built-in version. This can be very 375// confusing if you aren't expecting it. Other small functions in 376// this file may also be inline by gcc. 377 378#define STRLEN(soname, fnname) \ 379 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 380 ( const char* str ); \ 381 SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 382 ( const char* str ) \ 383 { \ 384 SizeT i = 0; \ 385 while (str[i] != 0) i++; \ 386 return i; \ 387 } 388 389#if defined(VGO_linux) 390 STRLEN(VG_Z_LIBC_SONAME, strlen) 391 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 392# if defined(VGPV_arm_linux_android) 393 STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */ 394# endif 395 396#elif defined(VGO_darwin) 397 //STRLEN(VG_Z_LIBC_SONAME, strlen) 398 STRLEN(VG_Z_LIBC_SONAME, strlen) 399 400#endif 401 402 403/*---------------------- strcpy ----------------------*/ 404 405#define STRCPY(soname, fnname) \ 406 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 407 ( char* dst, const char* src ); \ 408 char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 409 ( char* dst, const char* src ) \ 410 { \ 411 const Char* src_orig = src; \ 412 Char* dst_orig = dst; \ 413 \ 414 while (*src) *dst++ = *src++; \ 415 *dst = 0; \ 416 \ 417 /* This checks for overlap after copying, unavoidable without */ \ 418 /* pre-counting length... should be ok */ \ 419 if (is_overlap(dst_orig, \ 420 src_orig, \ 421 (Addr)dst-(Addr)dst_orig+1, \ 422 (Addr)src-(Addr)src_orig+1)) \ 423 RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \ 424 \ 425 return dst_orig; \ 426 } 427 428#if defined(VGO_linux) 429 STRCPY(VG_Z_LIBC_SONAME, strcpy) 430 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 431 432#elif defined(VGO_darwin) 433 //STRCPY(VG_Z_LIBC_SONAME, strcpy) 434 STRCPY(VG_Z_DYLD, strcpy) 435 STRCPY(VG_Z_LIBC_SONAME, strcpy) 436 437#endif 438 439 440/*---------------------- strncpy ----------------------*/ 441 442#define STRNCPY(soname, fnname) \ 443 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 444 ( char* dst, const char* src, SizeT n ); \ 445 char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 446 ( char* dst, const char* src, SizeT n ) \ 447 { \ 448 const Char* src_orig = src; \ 449 Char* dst_orig = dst; \ 450 SizeT m = 0; \ 451 \ 452 while (m < n && *src) { m++; *dst++ = *src++; } \ 453 /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 454 /* but only m+1 bytes of src if terminator was found */ \ 455 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 456 RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \ 457 while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ 458 \ 459 return dst_orig; \ 460 } 461 462#if defined(VGO_linux) 463 STRNCPY(VG_Z_LIBC_SONAME, strncpy) 464 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy) 465 466#elif defined(VGO_darwin) 467 //STRNCPY(VG_Z_LIBC_SONAME, strncpy) 468 STRNCPY(VG_Z_DYLD, strncpy) 469 STRNCPY(VG_Z_LIBC_SONAME, strncpy) 470 471#endif 472 473 474/*---------------------- strlcpy ----------------------*/ 475 476/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0. 477 Returns strlen(src). Does not zero-fill the remainder of dst. */ 478#define STRLCPY(soname, fnname) \ 479 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 480 ( char* dst, const char* src, SizeT n ); \ 481 SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 482 ( char* dst, const char* src, SizeT n ) \ 483 { \ 484 const char* src_orig = src; \ 485 char* dst_orig = dst; \ 486 SizeT m = 0; \ 487 \ 488 while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 489 /* m non-nul bytes have now been copied, and m <= n-1. */ \ 490 /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 491 /* but only m+1 bytes of src if terminator was found */ \ 492 if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 493 RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \ 494 /* Nul-terminate dst. */ \ 495 if (n > 0) *dst = 0; \ 496 /* Finish counting strlen(src). */ \ 497 while (*src) src++; \ 498 return src - src_orig; \ 499 } 500 501#if defined(VGO_linux) 502 503#elif defined(VGO_darwin) 504 //STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 505 STRLCPY(VG_Z_DYLD, strlcpy) 506 STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 507 508#endif 509 510 511/*---------------------- strncmp ----------------------*/ 512 513#define STRNCMP(soname, fnname) \ 514 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 515 ( const char* s1, const char* s2, SizeT nmax ); \ 516 int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 517 ( const char* s1, const char* s2, SizeT nmax ) \ 518 { \ 519 SizeT n = 0; \ 520 while (True) { \ 521 if (n >= nmax) return 0; \ 522 if (*s1 == 0 && *s2 == 0) return 0; \ 523 if (*s1 == 0) return -1; \ 524 if (*s2 == 0) return 1; \ 525 \ 526 if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \ 527 if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \ 528 \ 529 s1++; s2++; n++; \ 530 } \ 531 } 532 533#if defined(VGO_linux) 534 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 535 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 536 537#elif defined(VGO_darwin) 538 //STRNCMP(VG_Z_LIBC_SONAME, strncmp) 539 STRNCMP(VG_Z_DYLD, strncmp) 540 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 541 542#endif 543 544 545/*---------------------- strcasecmp ----------------------*/ 546 547#define STRCASECMP(soname, fnname) \ 548 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 549 ( const char* s1, const char* s2 ); \ 550 int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 551 ( const char* s1, const char* s2 ) \ 552 { \ 553 extern int tolower(int); \ 554 register unsigned char c1; \ 555 register unsigned char c2; \ 556 while (True) { \ 557 c1 = tolower(*(unsigned char *)s1); \ 558 c2 = tolower(*(unsigned char *)s2); \ 559 if (c1 != c2) break; \ 560 if (c1 == 0) break; \ 561 s1++; s2++; \ 562 } \ 563 if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 564 if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 565 return 0; \ 566 } 567 568#if defined(VGO_linux) 569# if !defined(VGPV_arm_linux_android) 570 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 571 STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) 572# endif 573 574#elif defined(VGO_darwin) 575 STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 576 577#endif 578 579 580/*---------------------- strncasecmp ----------------------*/ 581 582#define STRNCASECMP(soname, fnname) \ 583 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 584 ( const char* s1, const char* s2, SizeT nmax ); \ 585 int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 586 ( const char* s1, const char* s2, SizeT nmax ) \ 587 { \ 588 extern int tolower(int); \ 589 SizeT n = 0; \ 590 while (True) { \ 591 if (n >= nmax) return 0; \ 592 if (*s1 == 0 && *s2 == 0) return 0; \ 593 if (*s1 == 0) return -1; \ 594 if (*s2 == 0) return 1; \ 595 \ 596 if (tolower(*(unsigned char*)s1) \ 597 < tolower(*(unsigned char*)s2)) return -1; \ 598 if (tolower(*(unsigned char*)s1) \ 599 > tolower(*(unsigned char*)s2)) return 1; \ 600 \ 601 s1++; s2++; n++; \ 602 } \ 603 } 604 605#if defined(VGO_linux) 606# if !defined(VGPV_arm_linux_android) 607 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 608 STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp) 609# endif 610 611#elif defined(VGO_darwin) 612 STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 613 STRNCASECMP(VG_Z_DYLD, strncasecmp) 614 615#endif 616 617 618/*---------------------- strcasecmp_l ----------------------*/ 619 620#define STRCASECMP_L(soname, fnname) \ 621 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 622 ( const char* s1, const char* s2, void* locale ); \ 623 int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 624 ( const char* s1, const char* s2, void* locale ) \ 625 { \ 626 extern int tolower_l(int, void*) __attribute__((weak)); \ 627 register unsigned char c1; \ 628 register unsigned char c2; \ 629 while (True) { \ 630 c1 = tolower_l(*(unsigned char *)s1, locale); \ 631 c2 = tolower_l(*(unsigned char *)s2, locale); \ 632 if (c1 != c2) break; \ 633 if (c1 == 0) break; \ 634 s1++; s2++; \ 635 } \ 636 if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 637 if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 638 return 0; \ 639 } 640 641#if defined(VGO_linux) 642 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 643 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) 644 STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l) 645 646#elif defined(VGO_darwin) 647 STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 648 649#endif 650 651 652/*---------------------- strncasecmp_l ----------------------*/ 653 654#define STRNCASECMP_L(soname, fnname) \ 655 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 656 ( const char* s1, const char* s2, SizeT nmax, void* locale ); \ 657 int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 658 ( const char* s1, const char* s2, SizeT nmax, void* locale ) \ 659 { \ 660 extern int tolower_l(int, void*) __attribute__((weak)); \ 661 SizeT n = 0; \ 662 while (True) { \ 663 if (n >= nmax) return 0; \ 664 if (*s1 == 0 && *s2 == 0) return 0; \ 665 if (*s1 == 0) return -1; \ 666 if (*s2 == 0) return 1; \ 667 \ 668 if (tolower_l(*(unsigned char*)s1, locale) \ 669 < tolower_l(*(unsigned char*)s2, locale)) return -1; \ 670 if (tolower_l(*(unsigned char*)s1, locale) \ 671 > tolower_l(*(unsigned char*)s2, locale)) return 1; \ 672 \ 673 s1++; s2++; n++; \ 674 } \ 675 } 676 677#if defined(VGO_linux) 678 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 679 STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l) 680 681#elif defined(VGO_darwin) 682 STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 683 STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l) 684 685#endif 686 687 688/*---------------------- strcmp ----------------------*/ 689 690#define STRCMP(soname, fnname) \ 691 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 692 ( const char* s1, const char* s2 ); \ 693 int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 694 ( const char* s1, const char* s2 ) \ 695 { \ 696 register unsigned char c1; \ 697 register unsigned char c2; \ 698 while (True) { \ 699 c1 = *(unsigned char *)s1; \ 700 c2 = *(unsigned char *)s2; \ 701 if (c1 != c2) break; \ 702 if (c1 == 0) break; \ 703 s1++; s2++; \ 704 } \ 705 if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 706 if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 707 return 0; \ 708 } 709 710#if defined(VGO_linux) 711 STRCMP(VG_Z_LIBC_SONAME, strcmp) 712 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 713 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) 714 STRCMP(VG_Z_LD64_SO_1, strcmp) 715# if defined(VGPV_arm_linux_android) 716 STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */ 717# endif 718 719#elif defined(VGO_darwin) 720 //STRCMP(VG_Z_LIBC_SONAME, strcmp) 721 STRCMP(VG_Z_LIBC_SONAME, strcmp) 722 723#endif 724 725 726/*---------------------- memchr ----------------------*/ 727 728#define MEMCHR(soname, fnname) \ 729 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 730 (const void *s, int c, SizeT n); \ 731 void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 732 (const void *s, int c, SizeT n) \ 733 { \ 734 SizeT i; \ 735 UChar c0 = (UChar)c; \ 736 UChar* p = (UChar*)s; \ 737 for (i = 0; i < n; i++) \ 738 if (p[i] == c0) return (void*)(&p[i]); \ 739 return NULL; \ 740 } 741 742#if defined(VGO_linux) 743 MEMCHR(VG_Z_LIBC_SONAME, memchr) 744 745#elif defined(VGO_darwin) 746 MEMCHR(VG_Z_LIBC_SONAME, memchr) 747 MEMCHR(VG_Z_DYLD, memchr) 748 749#endif 750 751 752/*---------------------- memcpy ----------------------*/ 753 754#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \ 755 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 756 ( void *dst, const void *src, SizeT len ); \ 757 void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 758 ( void *dst, const void *src, SizeT len ) \ 759 { \ 760 if (do_ol_check && is_overlap(dst, src, len, len)) \ 761 RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \ 762 \ 763 const Addr WS = sizeof(UWord); /* 8 or 4 */ \ 764 const Addr WM = WS - 1; /* 7 or 3 */ \ 765 \ 766 if (len > 0) { \ 767 if (dst < src) { \ 768 \ 769 /* Copying backwards. */ \ 770 SizeT n = len; \ 771 Addr d = (Addr)dst; \ 772 Addr s = (Addr)src; \ 773 \ 774 if (((s^d) & WM) == 0) { \ 775 /* s and d have same UWord alignment. */ \ 776 /* Pull up to a UWord boundary. */ \ 777 while ((s & WM) != 0 && n >= 1) \ 778 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 779 /* Copy UWords. */ \ 780 while (n >= WS) \ 781 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ 782 if (n == 0) \ 783 return dst; \ 784 } \ 785 if (((s|d) & 1) == 0) { \ 786 /* Both are 16-aligned; copy what we can thusly. */ \ 787 while (n >= 2) \ 788 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ 789 } \ 790 /* Copy leftovers, or everything if misaligned. */ \ 791 while (n >= 1) \ 792 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 793 \ 794 } else if (dst > src) { \ 795 \ 796 SizeT n = len; \ 797 Addr d = ((Addr)dst) + n; \ 798 Addr s = ((Addr)src) + n; \ 799 \ 800 /* Copying forwards. */ \ 801 if (((s^d) & WM) == 0) { \ 802 /* s and d have same UWord alignment. */ \ 803 /* Back down to a UWord boundary. */ \ 804 while ((s & WM) != 0 && n >= 1) \ 805 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 806 /* Copy UWords. */ \ 807 while (n >= WS) \ 808 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ 809 if (n == 0) \ 810 return dst; \ 811 } \ 812 if (((s|d) & 1) == 0) { \ 813 /* Both are 16-aligned; copy what we can thusly. */ \ 814 while (n >= 2) \ 815 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ 816 } \ 817 /* Copy leftovers, or everything if misaligned. */ \ 818 while (n >= 1) \ 819 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 820 \ 821 } \ 822 } \ 823 \ 824 return dst; \ 825 } 826 827#define MEMMOVE(soname, fnname) \ 828 MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0) 829 830#define MEMCPY(soname, fnname) \ 831 MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1) 832 833#if defined(VGO_linux) 834 /* For older memcpy we have to use memmove-like semantics and skip 835 the overlap check; sigh; see #275284. */ 836 MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */ 837 MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */ 838 MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */ 839 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ 840 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ 841 /* icc9 blats these around all over the place. Not only in the main 842 executable but various .so's. They are highly tuned and read 843 memory beyond the source boundary (although work correctly and 844 never go across page boundaries), so give errors when run 845 natively, at least for misaligned source arg. Just intercepting 846 in the exe only until we understand more about the problem. See 847 http://bugs.kde.org/show_bug.cgi?id=139776 848 */ 849 MEMCPY(NONE, ZuintelZufastZumemcpy) 850 851#elif defined(VGO_darwin) 852 // glider: see https://bugs.kde.org/show_bug.cgi?id=285662 853 MEMCPY(VG_Z_LIBC_SONAME, memcpy) 854 MEMCPY(VG_Z_DYLD, memcpy) 855 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */ 856 MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */ 857 858#endif 859 860 861/*---------------------- memcmp ----------------------*/ 862 863#define MEMCMP(soname, fnname) \ 864 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 865 ( const void *s1V, const void *s2V, SizeT n ); \ 866 int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 867 ( const void *s1V, const void *s2V, SizeT n ) \ 868 { \ 869 int res; \ 870 unsigned char a0; \ 871 unsigned char b0; \ 872 unsigned char* s1 = (unsigned char*)s1V; \ 873 unsigned char* s2 = (unsigned char*)s2V; \ 874 \ 875 while (n != 0) { \ 876 a0 = s1[0]; \ 877 b0 = s2[0]; \ 878 s1 += 1; \ 879 s2 += 1; \ 880 res = ((int)a0) - ((int)b0); \ 881 if (res != 0) \ 882 return res; \ 883 n -= 1; \ 884 } \ 885 return 0; \ 886 } 887 888#if defined(VGO_linux) 889 MEMCMP(VG_Z_LIBC_SONAME, memcmp) 890 MEMCMP(VG_Z_LIBC_SONAME, bcmp) 891 MEMCMP(VG_Z_LD_SO_1, bcmp) 892 893#elif defined(VGO_darwin) 894 MEMCMP(VG_Z_LIBC_SONAME, memcmp) 895 MEMCMP(VG_Z_LIBC_SONAME, bcmp) 896 MEMCMP(VG_Z_DYLD, memcmp) 897 MEMCMP(VG_Z_DYLD, bcmp) 898 899#endif 900 901 902/*---------------------- stpcpy ----------------------*/ 903 904/* Copy SRC to DEST, returning the address of the terminating '\0' in 905 DEST. (minor variant of strcpy) */ 906#define STPCPY(soname, fnname) \ 907 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 908 ( char* dst, const char* src ); \ 909 char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 910 ( char* dst, const char* src ) \ 911 { \ 912 const Char* src_orig = src; \ 913 Char* dst_orig = dst; \ 914 \ 915 while (*src) *dst++ = *src++; \ 916 *dst = 0; \ 917 \ 918 /* This checks for overlap after copying, unavoidable without */ \ 919 /* pre-counting length... should be ok */ \ 920 if (is_overlap(dst_orig, \ 921 src_orig, \ 922 (Addr)dst-(Addr)dst_orig+1, \ 923 (Addr)src-(Addr)src_orig+1)) \ 924 RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \ 925 \ 926 return dst; \ 927 } 928 929#if defined(VGO_linux) 930 STPCPY(VG_Z_LIBC_SONAME, stpcpy) 931 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy) 932 STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) 933 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) 934 935#elif defined(VGO_darwin) 936 STPCPY(VG_Z_LIBC_SONAME, stpcpy) 937 STPCPY(VG_Z_DYLD, stpcpy) 938 939#endif 940 941 942/*---------------------- memset ----------------------*/ 943 944/* Why are we bothering to intercept this? It seems entirely 945 pointless. */ 946 947#define MEMSET(soname, fnname) \ 948 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 949 (void *s, Int c, SizeT n); \ 950 void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 951 (void *s, Int c, SizeT n) \ 952 { \ 953 Addr a = (Addr)s; \ 954 UInt c4 = (c & 0xFF); \ 955 c4 = (c4 << 8) | c4; \ 956 c4 = (c4 << 16) | c4; \ 957 while ((a & 3) != 0 && n >= 1) \ 958 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 959 while (n >= 4) \ 960 { *(UInt*)a = c4; a += 4; n -= 4; } \ 961 while (n >= 1) \ 962 { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 963 return s; \ 964 } 965 966#if defined(VGO_linux) 967 MEMSET(VG_Z_LIBC_SONAME, memset) 968 969#elif defined(VGO_darwin) 970 //MEMSET(VG_Z_LIBC_SONAME, memset) 971 MEMSET(VG_Z_DYLD, memset) 972 MEMSET(VG_Z_LIBC_SONAME, memset) 973 974#endif 975 976 977/*---------------------- memmove ----------------------*/ 978 979/* memmove -- use the MEMMOVE defn above. */ 980 981#if defined(VGO_linux) 982 MEMMOVE(VG_Z_LIBC_SONAME, memmove) 983 984#elif defined(VGO_darwin) 985 // glider: see https://bugs.kde.org/show_bug.cgi?id=285662 986 MEMMOVE(VG_Z_LIBC_SONAME, memmove) 987 MEMMOVE(VG_Z_DYLD, memmove) 988 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */ 989 MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */ 990 991#endif 992 993 994/*---------------------- bcopy ----------------------*/ 995 996#define BCOPY(soname, fnname) \ 997 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 998 (const void *srcV, void *dstV, SizeT n); \ 999 void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 1000 (const void *srcV, void *dstV, SizeT n) \ 1001 { \ 1002 SizeT i; \ 1003 Char* dst = (Char*)dstV; \ 1004 Char* src = (Char*)srcV; \ 1005 if (dst < src) { \ 1006 for (i = 0; i < n; i++) \ 1007 dst[i] = src[i]; \ 1008 } \ 1009 else \ 1010 if (dst > src) { \ 1011 for (i = 0; i < n; i++) \ 1012 dst[n-i-1] = src[n-i-1]; \ 1013 } \ 1014 } 1015 1016// kcc: enabled bcopy interceptor on non-mac targets. 1017BCOPY(VG_Z_LIBC_SONAME, bcopy) 1018#if defined(VGO_linux) 1019 1020#elif defined(VGO_darwin) 1021 //BCOPY(VG_Z_LIBC_SONAME, bcopy) 1022 BCOPY(VG_Z_DYLD, bcopy) 1023#endif 1024 1025/*-------------------- memmove_chk --------------------*/ 1026 1027/* glibc 2.5 variant of memmove which checks the dest is big enough. 1028 There is no specific part of glibc that this is copied from. */ 1029#define GLIBC25___MEMMOVE_CHK(soname, fnname) \ 1030 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1031 (void *dstV, const void *srcV, SizeT n, SizeT destlen); \ 1032 void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1033 (void *dstV, const void *srcV, SizeT n, SizeT destlen) \ 1034 { \ 1035 SizeT i; \ 1036 Char* dst = (Char*)dstV; \ 1037 Char* src = (Char*)srcV; \ 1038 if (destlen < n) \ 1039 goto badness; \ 1040 if (dst < src) { \ 1041 for (i = 0; i < n; i++) \ 1042 dst[i] = src[i]; \ 1043 } \ 1044 else \ 1045 if (dst > src) { \ 1046 for (i = 0; i < n; i++) \ 1047 dst[n-i-1] = src[n-i-1]; \ 1048 } \ 1049 return dst; \ 1050 badness: \ 1051 VALGRIND_PRINTF_BACKTRACE( \ 1052 "*** memmove_chk: buffer overflow detected ***: " \ 1053 "program terminated\n"); \ 1054 my_exit(127); \ 1055 /*NOTREACHED*/ \ 1056 return NULL; \ 1057 } 1058 1059#if defined(VGO_linux) 1060 GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk) 1061 1062#elif defined(VGO_darwin) 1063 1064#endif 1065 1066 1067/*-------------------- strchrnul --------------------*/ 1068 1069/* Find the first occurrence of C in S or the final NUL byte. */ 1070#define GLIBC232_STRCHRNUL(soname, fnname) \ 1071 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1072 (const char* s, int c_in); \ 1073 char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1074 (const char* s, int c_in) \ 1075 { \ 1076 unsigned char c = (unsigned char) c_in; \ 1077 unsigned char* char_ptr = (unsigned char *)s; \ 1078 while (1) { \ 1079 if (*char_ptr == 0) return char_ptr; \ 1080 if (*char_ptr == c) return char_ptr; \ 1081 char_ptr++; \ 1082 } \ 1083 } 1084 1085#if defined(VGO_linux) 1086 GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul) 1087 1088#elif defined(VGO_darwin) 1089 1090#endif 1091 1092 1093/*---------------------- rawmemchr ----------------------*/ 1094 1095/* Find the first occurrence of C in S. */ 1096#define GLIBC232_RAWMEMCHR(soname, fnname) \ 1097 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1098 (const char* s, int c_in); \ 1099 char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1100 (const char* s, int c_in) \ 1101 { \ 1102 unsigned char c = (unsigned char) c_in; \ 1103 unsigned char* char_ptr = (unsigned char *)s; \ 1104 while (1) { \ 1105 if (*char_ptr == c) return char_ptr; \ 1106 char_ptr++; \ 1107 } \ 1108 } 1109 1110#if defined (VGO_linux) 1111 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) 1112 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) 1113 1114#elif defined(VGO_darwin) 1115 1116#endif 1117 1118 1119/*---------------------- strcpy_chk ----------------------*/ 1120 1121/* glibc variant of strcpy that checks the dest is big enough. 1122 Copied from glibc-2.5/debug/test-strcpy_chk.c. */ 1123#define GLIBC25___STRCPY_CHK(soname,fnname) \ 1124 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1125 (char* dst, const char* src, SizeT len); \ 1126 char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1127 (char* dst, const char* src, SizeT len) \ 1128 { \ 1129 char* ret = dst; \ 1130 if (! len) \ 1131 goto badness; \ 1132 while ((*dst++ = *src++) != '\0') \ 1133 if (--len == 0) \ 1134 goto badness; \ 1135 return ret; \ 1136 badness: \ 1137 VALGRIND_PRINTF_BACKTRACE( \ 1138 "*** strcpy_chk: buffer overflow detected ***: " \ 1139 "program terminated\n"); \ 1140 my_exit(127); \ 1141 /*NOTREACHED*/ \ 1142 return NULL; \ 1143 } 1144 1145#if defined(VGO_linux) 1146 GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk) 1147 1148#elif defined(VGO_darwin) 1149 1150#endif 1151 1152 1153/*---------------------- stpcpy_chk ----------------------*/ 1154 1155/* glibc variant of stpcpy that checks the dest is big enough. 1156 Copied from glibc-2.5/debug/test-stpcpy_chk.c. */ 1157#define GLIBC25___STPCPY_CHK(soname,fnname) \ 1158 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1159 (char* dst, const char* src, SizeT len); \ 1160 char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1161 (char* dst, const char* src, SizeT len) \ 1162 { \ 1163 if (! len) \ 1164 goto badness; \ 1165 while ((*dst++ = *src++) != '\0') \ 1166 if (--len == 0) \ 1167 goto badness; \ 1168 return dst - 1; \ 1169 badness: \ 1170 VALGRIND_PRINTF_BACKTRACE( \ 1171 "*** stpcpy_chk: buffer overflow detected ***: " \ 1172 "program terminated\n"); \ 1173 my_exit(127); \ 1174 /*NOTREACHED*/ \ 1175 return NULL; \ 1176 } 1177 1178#if defined(VGO_linux) 1179 GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk) 1180 1181#elif defined(VGO_darwin) 1182 1183#endif 1184 1185 1186/*---------------------- mempcpy ----------------------*/ 1187 1188/* mempcpy */ 1189#define GLIBC25_MEMPCPY(soname, fnname) \ 1190 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1191 ( void *dst, const void *src, SizeT len ); \ 1192 void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1193 ( void *dst, const void *src, SizeT len ) \ 1194 { \ 1195 register char *d; \ 1196 register char *s; \ 1197 SizeT len_saved = len; \ 1198 \ 1199 if (len == 0) \ 1200 return dst; \ 1201 \ 1202 if (is_overlap(dst, src, len, len)) \ 1203 RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \ 1204 \ 1205 if ( dst > src ) { \ 1206 d = (char *)dst + len - 1; \ 1207 s = (char *)src + len - 1; \ 1208 while ( len-- ) { \ 1209 *d-- = *s--; \ 1210 } \ 1211 } else if ( dst < src ) { \ 1212 d = (char *)dst; \ 1213 s = (char *)src; \ 1214 while ( len-- ) { \ 1215 *d++ = *s++; \ 1216 } \ 1217 } \ 1218 return (void*)( ((char*)dst) + len_saved ); \ 1219 } 1220 1221#if defined(VGO_linux) 1222 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1223 GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ 1224 1225#elif defined(VGO_darwin) 1226 GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1227 1228#endif 1229 1230 1231/*-------------------- memcpy_chk --------------------*/ 1232 1233#define GLIBC26___MEMCPY_CHK(soname, fnname) \ 1234 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1235 (void* dst, const void* src, SizeT len, SizeT dstlen ); \ 1236 void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1237 (void* dst, const void* src, SizeT len, SizeT dstlen ) \ 1238 { \ 1239 register char *d; \ 1240 register char *s; \ 1241 \ 1242 if (dstlen < len) goto badness; \ 1243 \ 1244 if (len == 0) \ 1245 return dst; \ 1246 \ 1247 if (is_overlap(dst, src, len, len)) \ 1248 RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \ 1249 \ 1250 if ( dst > src ) { \ 1251 d = (char *)dst + len - 1; \ 1252 s = (char *)src + len - 1; \ 1253 while ( len-- ) { \ 1254 *d-- = *s--; \ 1255 } \ 1256 } else if ( dst < src ) { \ 1257 d = (char *)dst; \ 1258 s = (char *)src; \ 1259 while ( len-- ) { \ 1260 *d++ = *s++; \ 1261 } \ 1262 } \ 1263 return dst; \ 1264 badness: \ 1265 VALGRIND_PRINTF_BACKTRACE( \ 1266 "*** memcpy_chk: buffer overflow detected ***: " \ 1267 "program terminated\n"); \ 1268 my_exit(127); \ 1269 /*NOTREACHED*/ \ 1270 return NULL; \ 1271 } 1272 1273#if defined(VGO_linux) 1274 GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) 1275 1276#elif defined(VGO_darwin) 1277 1278#endif 1279 1280 1281/*---------------------- strstr ----------------------*/ 1282 1283#define STRSTR(soname, fnname) \ 1284 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1285 (void* haystack, void* needle); \ 1286 void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1287 (void* haystack, void* needle) \ 1288 { \ 1289 UChar* h = (UChar*)haystack; \ 1290 UChar* n = (UChar*)needle; \ 1291 \ 1292 /* find the length of n, not including terminating zero */ \ 1293 UWord nlen = 0; \ 1294 while (n[nlen]) nlen++; \ 1295 \ 1296 /* if n is the empty string, match immediately. */ \ 1297 if (nlen == 0) return h; \ 1298 \ 1299 /* assert(nlen >= 1); */ \ 1300 UChar n0 = n[0]; \ 1301 \ 1302 while (1) { \ 1303 UChar hh = *h; \ 1304 if (hh == 0) return NULL; \ 1305 if (hh != n0) { h++; continue; } \ 1306 \ 1307 UWord i; \ 1308 for (i = 0; i < nlen; i++) { \ 1309 if (n[i] != h[i]) \ 1310 break; \ 1311 } \ 1312 /* assert(i >= 0 && i <= nlen); */ \ 1313 if (i == nlen) \ 1314 return h; \ 1315 \ 1316 h++; \ 1317 } \ 1318 } 1319 1320#if defined(VGO_linux) 1321 STRSTR(VG_Z_LIBC_SONAME, strstr) 1322 1323#elif defined(VGO_darwin) 1324 1325#endif 1326 1327 1328/*---------------------- strpbrk ----------------------*/ 1329 1330#define STRPBRK(soname, fnname) \ 1331 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1332 (void* sV, void* acceptV); \ 1333 void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1334 (void* sV, void* acceptV) \ 1335 { \ 1336 UChar* s = (UChar*)sV; \ 1337 UChar* accept = (UChar*)acceptV; \ 1338 \ 1339 /* find the length of 'accept', not including terminating zero */ \ 1340 UWord nacc = 0; \ 1341 while (accept[nacc]) nacc++; \ 1342 \ 1343 /* if n is the empty string, fail immediately. */ \ 1344 if (nacc == 0) return NULL; \ 1345 \ 1346 /* assert(nacc >= 1); */ \ 1347 while (1) { \ 1348 UWord i; \ 1349 UChar sc = *s; \ 1350 if (sc == 0) \ 1351 break; \ 1352 for (i = 0; i < nacc; i++) { \ 1353 if (sc == accept[i]) \ 1354 return s; \ 1355 } \ 1356 s++; \ 1357 } \ 1358 \ 1359 return NULL; \ 1360 } 1361 1362#if defined(VGO_linux) 1363 STRPBRK(VG_Z_LIBC_SONAME, strpbrk) 1364 1365#elif defined(VGO_darwin) 1366 1367#endif 1368 1369 1370/*---------------------- strcspn ----------------------*/ 1371 1372#define STRCSPN(soname, fnname) \ 1373 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1374 (void* sV, void* rejectV); \ 1375 SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1376 (void* sV, void* rejectV) \ 1377 { \ 1378 UChar* s = (UChar*)sV; \ 1379 UChar* reject = (UChar*)rejectV; \ 1380 \ 1381 /* find the length of 'reject', not including terminating zero */ \ 1382 UWord nrej = 0; \ 1383 while (reject[nrej]) nrej++; \ 1384 \ 1385 UWord len = 0; \ 1386 while (1) { \ 1387 UWord i; \ 1388 UChar sc = *s; \ 1389 if (sc == 0) \ 1390 break; \ 1391 for (i = 0; i < nrej; i++) { \ 1392 if (sc == reject[i]) \ 1393 break; \ 1394 } \ 1395 /* assert(i >= 0 && i <= nrej); */ \ 1396 if (i < nrej) \ 1397 break; \ 1398 s++; \ 1399 len++; \ 1400 } \ 1401 \ 1402 return len; \ 1403 } 1404 1405#if defined(VGO_linux) 1406 STRCSPN(VG_Z_LIBC_SONAME, strcspn) 1407 1408#elif defined(VGO_darwin) 1409 1410#endif 1411 1412 1413/*---------------------- strspn ----------------------*/ 1414 1415#define STRSPN(soname, fnname) \ 1416 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1417 (void* sV, void* acceptV); \ 1418 SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1419 (void* sV, void* acceptV) \ 1420 { \ 1421 UChar* s = (UChar*)sV; \ 1422 UChar* accept = (UChar*)acceptV; \ 1423 \ 1424 /* find the length of 'accept', not including terminating zero */ \ 1425 UWord nacc = 0; \ 1426 while (accept[nacc]) nacc++; \ 1427 if (nacc == 0) return 0; \ 1428 \ 1429 UWord len = 0; \ 1430 while (1) { \ 1431 UWord i; \ 1432 UChar sc = *s; \ 1433 if (sc == 0) \ 1434 break; \ 1435 for (i = 0; i < nacc; i++) { \ 1436 if (sc == accept[i]) \ 1437 break; \ 1438 } \ 1439 /* assert(i >= 0 && i <= nacc); */ \ 1440 if (i == nacc) \ 1441 break; \ 1442 s++; \ 1443 len++; \ 1444 } \ 1445 \ 1446 return len; \ 1447 } 1448 1449#if defined(VGO_linux) 1450 STRSPN(VG_Z_LIBC_SONAME, strspn) 1451 1452#elif defined(VGO_darwin) 1453 1454#endif 1455 1456 1457/*---------------------- strcasestr ----------------------*/ 1458 1459#define STRCASESTR(soname, fnname) \ 1460 void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1461 (void* haystack, void* needle); \ 1462 void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1463 (void* haystack, void* needle) \ 1464 { \ 1465 extern int tolower(int); \ 1466 UChar* h = (UChar*)haystack; \ 1467 UChar* n = (UChar*)needle; \ 1468 \ 1469 /* find the length of n, not including terminating zero */ \ 1470 UWord nlen = 0; \ 1471 while (n[nlen]) nlen++; \ 1472 \ 1473 /* if n is the empty string, match immediately. */ \ 1474 if (nlen == 0) return h; \ 1475 \ 1476 /* assert(nlen >= 1); */ \ 1477 UChar n0 = tolower(n[0]); \ 1478 \ 1479 while (1) { \ 1480 UChar hh = tolower(*h); \ 1481 if (hh == 0) return NULL; \ 1482 if (hh != n0) { h++; continue; } \ 1483 \ 1484 UWord i; \ 1485 for (i = 0; i < nlen; i++) { \ 1486 if (tolower(n[i]) != tolower(h[i])) \ 1487 break; \ 1488 } \ 1489 /* assert(i >= 0 && i <= nlen); */ \ 1490 if (i == nlen) \ 1491 return h; \ 1492 \ 1493 h++; \ 1494 } \ 1495 } 1496 1497#if defined(VGO_linux) 1498 STRCASESTR(VG_Z_LIBC_SONAME, strcasestr) 1499 1500#elif defined(VGO_darwin) 1501 1502#endif 1503 1504 1505/*------------------------------------------------------------*/ 1506/*--- Improve definedness checking of process environment ---*/ 1507/*------------------------------------------------------------*/ 1508 1509#if defined(VGO_linux) 1510 1511/* If these wind up getting generated via a macro, so that multiple 1512 versions of each function exist (as above), use the _EZU variants 1513 to assign equivalance class tags. */ 1514 1515/*---------------------- putenv ----------------------*/ 1516 1517int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string); 1518int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string) 1519{ 1520 OrigFn fn; 1521 Word result; 1522 const char* p = string; 1523 VALGRIND_GET_ORIG_FN(fn); 1524 /* Now by walking over the string we magically produce 1525 traces when hitting undefined memory. */ 1526 if (p) 1527 while (*p++) 1528 __asm__ __volatile__("" ::: "memory"); 1529 CALL_FN_W_W(result, fn, string); 1530 return result; 1531} 1532 1533 1534/*---------------------- unsetenv ----------------------*/ 1535 1536int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name); 1537int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name) 1538{ 1539 OrigFn fn; 1540 Word result; 1541 const char* p = name; 1542 VALGRIND_GET_ORIG_FN(fn); 1543 /* Now by walking over the string we magically produce 1544 traces when hitting undefined memory. */ 1545 if (p) 1546 while (*p++) 1547 __asm__ __volatile__("" ::: "memory"); 1548 CALL_FN_W_W(result, fn, name); 1549 return result; 1550} 1551 1552 1553/*---------------------- setenv ----------------------*/ 1554 1555/* setenv */ 1556int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1557 (const char* name, const char* value, int overwrite); 1558int VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1559 (const char* name, const char* value, int overwrite) 1560{ 1561 OrigFn fn; 1562 Word result; 1563 const char* p; 1564 VALGRIND_GET_ORIG_FN(fn); 1565 /* Now by walking over the string we magically produce 1566 traces when hitting undefined memory. */ 1567 if (name) 1568 for (p = name; *p; p++) 1569 __asm__ __volatile__("" ::: "memory"); 1570 if (value) 1571 for (p = value; *p; p++) 1572 __asm__ __volatile__("" ::: "memory"); 1573 VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite); 1574 CALL_FN_W_WWW(result, fn, name, value, overwrite); 1575 return result; 1576} 1577 1578#endif /* defined(VGO_linux) */ 1579 1580/*--------------------------------------------------------------------*/ 1581/*--- end ---*/ 1582/*--------------------------------------------------------------------*/ 1583