On Fri, Jun 17, 2011 at 04:16:33AM -0400, Jeff King wrote:

> Yeah, they even ship a commented-out implementation of strspn; the patch
> I mentioned above basically just uncomments it.
> [...]
> I'll attach the full pristine patch from valgrind 3.6.1-5 that fixes it
> for me.

I get a similar issue with the optimized strcasestr:

  $ cat >foo.c <<'EOF'
  #define _GNU_SOURCE
  #include <string.h>

  int main(void)
  {
    char buf[32];

    strcpy(buf, "foo");
    return strcasestr(buf, "bar") != buf;
  }
  EOF

  $ gcc -o foo foo.c
  $ valgrind ./foo
  ==27953== Conditional jump or move depends on uninitialised value(s)
  ==27953==    at 0x4B34E2D: __strcasestr_sse42 (strstr.c:218)
  ==27953==    by 0x400519: main (in /home/peff/foo/valgrind/foo)

The attached patch fixes it (the implementation is ripped from the
strstr that valgrind provides, with tolower() used as appropriate (this
is what their strcasecmp re-implementation does)).

-Peff
diff --git a/memcheck/mc_replace_strmem.c b/memcheck/mc_replace_strmem.c
index 0622a5e..8c7747d 100644
--- a/memcheck/mc_replace_strmem.c
+++ b/memcheck/mc_replace_strmem.c
@@ -1045,6 +1045,48 @@ STRSTR(VG_Z_LIBC_SONAME,          strstr)
 #endif
 
 
+#define STRCASESTR(soname, fnname) \
+   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+         (void* haystack, void* needle); \
+   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
+         (void* haystack, void* needle) \
+   { \
+      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)
+#endif
+
+
 #define STRPBRK(soname, fnname) \
    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
          (void* sV, void* acceptV); \

Reply via email to