fix for #113230



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4751 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index c1b582c..9092020 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -1601,12 +1601,23 @@
    PRE_REG_READ0(long, "munlockall");
 }
 
-// XXX: sort of x86/Linux-specific
+// This has different signatures for different platforms.
+//
+//  x86:   int  sys_pipe(unsigned long __user *fildes);
+//  AMD64: long sys_pipe(int *fildes);
+//  ppc32: int  sys_pipe(int __user *fildes);
+//  ppc64: int  sys_pipe(int __user *fildes);
+//
+// The type of the argument is most important, and it is an array of 32 bit
+// values in all cases.  (The return type differs across platforms, but it
+// is not used.)  So we use 'int' as its type.  This fixed bug #113230 which
+// was caused by using an array of 'unsigned long's, which didn't work on
+// AMD64.
 PRE(sys_pipe)
 {
    PRINT("sys_pipe ( %p )", ARG1);
-   PRE_REG_READ1(int, "pipe", unsigned long *, filedes);
-   PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(long) );
+   PRE_REG_READ1(int, "pipe", int *, filedes);
+   PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) );
 }
 POST(sys_pipe)
 {
diff --git a/docs/internals/3_0_BUGSTATUS.txt b/docs/internals/3_0_BUGSTATUS.txt
index 59e4122..ae66e67 100644
--- a/docs/internals/3_0_BUGSTATUS.txt
+++ b/docs/internals/3_0_BUGSTATUS.txt
@@ -155,6 +155,13 @@
 FIXED-TRUNK:    TODO
 FIXED-30BRANCH: TODO
 
+----------------------------------------------------------------
+113230  Valgrind sys_pipe on x86-64 wrongly thinks file descriptors
+        should be 64bit
+
+FIXED-TRUNK:    vg:4669
+FIXED-30BRANCH: TODO
+
 
 ========================================================================
 === Bugs targeted for 3.1.0 and 3.0.1 (all done, 3.0.1 released)     ===
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index 28bc930..7a01b45 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -63,6 +63,7 @@
 	oset_test.stderr.exp oset_test.stdout.exp oset_test.vgtest \
 	partiallydefinedeq.vgtest partiallydefinedeq.stderr.exp \
 	partiallydefinedeq.stdout.exp \
+	pipe.stderr.exp pipe.vgtest \
 	pointer-trace.vgtest \
 	pointer-trace.stderr.exp pointer-trace.stderr.exp64 \
 	post-syscall.stderr.exp post-syscall.stdout.exp post-syscall.vgtest \
@@ -107,7 +108,7 @@
 	nanoleak new_nothrow \
 	null_socket oset_test overlap \
 	partiallydefinedeq \
-	pointer-trace \
+	pipe pointer-trace \
 	post-syscall \
 	realloc1 realloc2 realloc3 \
 	sigaltstack signal2 sigprocmask sigkill \
diff --git a/memcheck/tests/pipe.c b/memcheck/tests/pipe.c
new file mode 100644
index 0000000..cf97739
--- /dev/null
+++ b/memcheck/tests/pipe.c
@@ -0,0 +1,16 @@
+// This is a regtest for bug #113230, in which 64-bit platforms mistakenly
+// behaved as if pipe() took an array of 64-bit ints, when it really takes
+// an array of 32-bit ints.
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+   int *filedes = malloc(2 * sizeof(int));
+
+   pipe(filedes);
+
+   return 0;
+}
diff --git a/memcheck/tests/pipe.stderr.exp b/memcheck/tests/pipe.stderr.exp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/memcheck/tests/pipe.stderr.exp
diff --git a/memcheck/tests/pipe.vgtest b/memcheck/tests/pipe.vgtest
new file mode 100644
index 0000000..45698a4
--- /dev/null
+++ b/memcheck/tests/pipe.vgtest
@@ -0,0 +1,2 @@
+prog: pipe
+vgopts: -q