Add a replacement for strcasestr, along with test case. Fixes #282979.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12187
This commit is contained in:
Julian Seward 2011-10-21 08:07:13 +00:00
parent 141e66b02a
commit 1fd197db11
2 changed files with 78 additions and 0 deletions

View File

@ -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 ---*/
/*------------------------------------------------------------*/

View File

@ -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;