]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a replacement for strcasestr, along with test case. Fixes #282979.
authorJulian Seward <jseward@acm.org>
Fri, 21 Oct 2011 08:07:13 +0000 (08:07 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 21 Oct 2011 08:07:13 +0000 (08:07 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12187

memcheck/mc_replace_strmem.c
memcheck/tests/str_tester.c

index 5a01677a4dcf4025206b2fd03e3c6a5f38832e8b..5785b23e9e60ae0c74880353bb4adba49def8fbe 100644 (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  ---*/
 /*------------------------------------------------------------*/
index 2e2e67d25404a4839d2a1680d9015294d51e214f..85c496a35161f96a68ba5023d3a839d88e0f7789 100644 (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;