|
From: <sv...@va...> - 2012-12-06 17:16:08
|
sewardj 2012-12-06 17:16:00 +0000 (Thu, 06 Dec 2012)
New Revision: 13162
Log:
Add intercepts for wcscpy, wcscmp, wcsrchr and wcschr on Linux.
Fixes #307828. (Mark Wielaard, mj...@re...)
Added files:
trunk/memcheck/tests/wcs.c
trunk/memcheck/tests/wcs.stderr.exp
trunk/memcheck/tests/wcs.stdout.exp
trunk/memcheck/tests/wcs.vgtest
Modified files:
trunk/memcheck/mc_replace_strmem.c
trunk/memcheck/tests/Makefile.am
Modified: trunk/memcheck/mc_replace_strmem.c (+112 -0)
===================================================================
--- trunk/memcheck/mc_replace_strmem.c 2012-12-06 16:38:50 +00:00 (rev 13161)
+++ trunk/memcheck/mc_replace_strmem.c 2012-12-06 17:16:00 +00:00 (rev 13162)
@@ -97,6 +97,10 @@
20350 STRCASESTR
20360 MEMRCHR
20370 WCSLEN
+ 20380 WCSCMP
+ 20390 WCSCPY
+ 20400 WCSCHR
+ 20410 WCSRCHR
*/
@@ -1570,7 +1574,115 @@
#endif
+/*---------------------- wcscmp ----------------------*/
+// This is a wchar_t equivalent to strcmp. We don't
+// have wchar_t available here, but in the GNU C Library
+// wchar_t is always 32 bits wide and wcscmp uses signed
+// comparison, not unsigned as in strcmp function.
+
+#define WCSCMP(soname, fnname) \
+ int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
+ ( const Int* s1, const Int* s2 ); \
+ int VG_REPLACE_FUNCTION_EZU(20380,soname,fnname) \
+ ( const Int* s1, const Int* s2 ) \
+ { \
+ register Int c1; \
+ register Int c2; \
+ while (True) { \
+ c1 = *s1; \
+ c2 = *s2; \
+ if (c1 != c2) break; \
+ if (c1 == 0) break; \
+ s1++; s2++; \
+ } \
+ if (c1 < c2) return -1; \
+ if (c1 > c2) return 1; \
+ return 0; \
+ }
+
+#if defined(VGO_linux)
+ WCSCMP(VG_Z_LIBC_SONAME, wcscmp)
+#endif
+
+/*---------------------- wcscpy ----------------------*/
+
+// This is a wchar_t equivalent to strcpy. We don't
+// have wchar_t available here, but in the GNU C Library
+// wchar_t is always 32 bits wide.
+
+#define WCSCPY(soname, fnname) \
+ Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
+ ( Int* dst, const Int* src ); \
+ Int* VG_REPLACE_FUNCTION_EZU(20390,soname,fnname) \
+ ( Int* dst, const Int* src ) \
+ { \
+ const Int* src_orig = src; \
+ Int* dst_orig = dst; \
+ \
+ while (*src) *dst++ = *src++; \
+ *dst = 0; \
+ \
+ /* This checks for overlap after copying, unavoidable without */ \
+ /* pre-counting length... should be ok */ \
+ if (is_overlap(dst_orig, \
+ src_orig, \
+ (Addr)dst-(Addr)dst_orig+1, \
+ (Addr)src-(Addr)src_orig+1)) \
+ RECORD_OVERLAP_ERROR("wcscpy", dst_orig, src_orig, 0); \
+ \
+ return dst_orig; \
+ }
+
+#if defined(VGO_linux)
+ WCSCPY(VG_Z_LIBC_SONAME, wcscpy)
+#endif
+
+
+/*---------------------- wcschr ----------------------*/
+
+// This is a wchar_t equivalent to strchr. We don't
+// have wchar_t available here, but in the GNU C Library
+// wchar_t is always 32 bits wide.
+
+#define WCSCHR(soname, fnname) \
+ Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ); \
+ Int* VG_REPLACE_FUNCTION_EZU(20400,soname,fnname) ( const Int* s, Int c ) \
+ { \
+ Int* p = (Int*)s; \
+ while (True) { \
+ if (*p == c) return p; \
+ if (*p == 0) return NULL; \
+ p++; \
+ } \
+ }
+
+#if defined(VGO_linux)
+ WCSCHR(VG_Z_LIBC_SONAME, wcschr)
+#endif
+/*---------------------- wcsrchr ----------------------*/
+
+// This is a wchar_t equivalent to strrchr. We don't
+// have wchar_t available here, but in the GNU C Library
+// wchar_t is always 32 bits wide.
+
+#define WCSRCHR(soname, fnname) \
+ Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ); \
+ Int* VG_REPLACE_FUNCTION_EZU(20410,soname,fnname)( const Int* s, Int c ) \
+ { \
+ Int* p = (Int*) s; \
+ Int* last = NULL; \
+ while (True) { \
+ if (*p == c) last = p; \
+ if (*p == 0) return last; \
+ p++; \
+ } \
+ }
+
+#if defined(VGO_linux)
+ WCSRCHR(VG_Z_LIBC_SONAME, wcsrchr)
+#endif
+
/*------------------------------------------------------------*/
/*--- Improve definedness checking of process environment ---*/
/*------------------------------------------------------------*/
Added: trunk/memcheck/tests/wcs.stderr.exp (+3 -0)
===================================================================
--- trunk/memcheck/tests/wcs.stderr.exp 2012-12-06 16:38:50 +00:00 (rev 13161)
+++ trunk/memcheck/tests/wcs.stderr.exp 2012-12-06 17:16:00 +00:00 (rev 13162)
@@ -0,0 +1,3 @@
+wcslen: 53
+wcscmp equal: 0
+wcsrchr == wcschr: 1
Added: trunk/memcheck/tests/wcs.c (+29 -0)
===================================================================
--- trunk/memcheck/tests/wcs.c 2012-12-06 16:38:50 +00:00 (rev 13161)
+++ trunk/memcheck/tests/wcs.c 2012-12-06 17:16:00 +00:00 (rev 13162)
@@ -0,0 +1,29 @@
+// Uses various wchar_t * functions that have hand written SSE assembly
+// implementations in glibc. wcslen, wcscpy, wcscmp, wcsrchr, wcschr.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+int main(int argc, char **argv)
+{
+ wchar_t a[] = L"The spazzy orange tiger jumped over the tawny jaguar.";
+ wchar_t *b, *c;
+ wchar_t *d, *e;
+
+ size_t l = wcslen (a);
+ fprintf (stderr, "wcslen: %zd\n", l); // wcslen: 53
+
+ b = (wchar_t *) malloc((l + 1) * sizeof (wchar_t));
+ c = wcscpy (b, a);
+
+ fprintf (stderr, "wcscmp equal: %d\n", wcscmp (a, b)); // wcscmp equal: 0
+
+ d = wcsrchr (a, L'd');
+ e = wcschr (a, L'd');
+
+ fprintf (stderr, "wcsrchr == wcschr: %d\n", d == e); // wcsrchr == wcschr: 1
+
+ free (c); // b == c
+ return 0;
+}
Modified: trunk/memcheck/tests/Makefile.am (+2 -0)
===================================================================
--- trunk/memcheck/tests/Makefile.am 2012-12-06 16:38:50 +00:00 (rev 13161)
+++ trunk/memcheck/tests/Makefile.am 2012-12-06 17:16:00 +00:00 (rev 13162)
@@ -218,6 +218,7 @@
vcpu_fbench.stdout.exp vcpu_fbench.stderr.exp vcpu_fbench.vgtest \
vcpu_fnfns.stdout.exp vcpu_fnfns.stdout.exp-glibc28-amd64 \
vcpu_fnfns.stdout.exp-darwin vcpu_fnfns.stderr.exp vcpu_fnfns.vgtest \
+ wcs.vgtest wcs.stderr.exp wcs.stdout.exp \
wrap1.vgtest wrap1.stdout.exp wrap1.stderr.exp \
wrap2.vgtest wrap2.stdout.exp wrap2.stderr.exp \
wrap3.vgtest wrap3.stdout.exp wrap3.stderr.exp \
@@ -294,6 +295,7 @@
varinfo1 varinfo2 varinfo3 varinfo4 \
varinfo5 varinfo5so.so varinfo6 \
vcpu_fbench vcpu_fnfns \
+ wcs \
xml1 \
wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \
writev1
Added: trunk/memcheck/tests/wcs.stdout.exp (+0 -0)
===================================================================
Added: trunk/memcheck/tests/wcs.vgtest (+2 -0)
===================================================================
--- trunk/memcheck/tests/wcs.vgtest 2012-12-06 16:38:50 +00:00 (rev 13161)
+++ trunk/memcheck/tests/wcs.vgtest 2012-12-06 17:16:00 +00:00 (rev 13162)
@@ -0,0 +1,2 @@
+prog: wcs
+vgopts: -q
|