From: Julian Seward Date: Fri, 21 Oct 2011 08:07:13 +0000 (+0000) Subject: Add a replacement for strcasestr, along with test case. Fixes #282979. X-Git-Tag: svn/VALGRIND_3_7_0~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fd197db1153122a2ed701516f4c7b283da490f3;p=thirdparty%2Fvalgrind.git Add a replacement for strcasestr, along with test case. Fixes #282979. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12187 --- diff --git a/memcheck/mc_replace_strmem.c b/memcheck/mc_replace_strmem.c index 5a01677a4d..5785b23e9e 100644 --- a/memcheck/mc_replace_strmem.c +++ b/memcheck/mc_replace_strmem.c @@ -93,6 +93,7 @@ 20320 STRPBRK 20330 STRCSPN 20340 STRSPN + 20350 STRCASESTR */ @@ -1451,6 +1452,54 @@ static inline void my_exit ( int x ) #endif +/*---------------------- strcasestr ----------------------*/ + +#define STRCASESTR(soname, fnname) \ + void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ + (void* haystack, void* needle); \ + void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ + (void* haystack, void* needle) \ + { \ + extern int tolower(int); \ + UChar* h = (UChar*)haystack; \ + UChar* n = (UChar*)needle; \ + \ + /* find the length of n, not including terminating zero */ \ + UWord nlen = 0; \ + while (n[nlen]) nlen++; \ + \ + /* if n is the empty string, match immediately. */ \ + if (nlen == 0) return h; \ + \ + /* assert(nlen >= 1); */ \ + UChar n0 = tolower(n[0]); \ + \ + while (1) { \ + UChar hh = tolower(*h); \ + if (hh == 0) return NULL; \ + if (hh != n0) { h++; continue; } \ + \ + UWord i; \ + for (i = 0; i < nlen; i++) { \ + if (tolower(n[i]) != tolower(h[i])) \ + break; \ + } \ + /* assert(i >= 0 && i <= nlen); */ \ + if (i == nlen) \ + return h; \ + \ + h++; \ + } \ + } + +#if defined(VGO_linux) + STRCASESTR(VG_Z_LIBC_SONAME, strcasestr) + +#elif defined(VGO_darwin) + +#endif + + /*------------------------------------------------------------*/ /*--- Improve definedness checking of process environment ---*/ /*------------------------------------------------------------*/ diff --git a/memcheck/tests/str_tester.c b/memcheck/tests/str_tester.c index 2e2e67d254..85c496a351 100644 --- a/memcheck/tests/str_tester.c +++ b/memcheck/tests/str_tester.c @@ -1373,6 +1373,33 @@ test_strncasecmp (void) check(strncasecmp("ADC", "abcd", 2) > 0, 20); } +static void +test_strcasestr (void) +{ + it = "strcasestr"; + check(strcasestr("abCd", "z") == NULL, 1); /* Not found. */ + check(strcasestr("AbcD", "abX") == NULL, 2); /* Dead end. */ + (void) strcpy(one, "abCd"); + check(strcasestr(one, "c") == one+2, 3); /* Basic test. */ + check(strcasestr(one, "Bc") == one+1, 4); /* Multichar. */ + check(strcasestr(one, "d") == one+3, 5); /* End of string. */ + check(strcasestr(one, "Cd") == one+2, 6); /* Tail of string. */ + check(strcasestr(one, "aBc") == one, 7); /* Beginning. */ + check(strcasestr(one, "aBcd") == one, 8); /* Exact match. */ + check(strcasestr(one, "AbcDe") == NULL, 9); /* Too long. */ + check(strcasestr(one, "dE") == NULL, 10); /* Past end. */ + check(strcasestr(one, "") == one, 11); /* Finding empty. */ + (void) strcpy(one, "abAba"); + check(strcasestr(one, "Ba") == one+1, 12); /* Finding first. */ + (void) strcpy(one, ""); + check(strcasestr(one, "b") == NULL, 13); /* Empty string. */ + check(strcasestr(one, "") == one, 14); /* Empty in empty string. */ + (void) strcpy(one, "BcbCa"); + check(strcasestr(one, "bCa") == one+2, 15); /* False start. */ + (void) strcpy(one, "bbBcaBbcA"); + check(strcasestr(one, "bbCa") == one+1, 16); /* With overlap. */ +} + int main (void) { @@ -1501,6 +1528,8 @@ main (void) /* strncasecmp. Without locale dependencies. */ test_strncasecmp (); + test_strcasestr (); + if (errors == 0) { status = EXIT_SUCCESS;