Now doing pre_mem_read()s on the args to execve(), so eg. Memcheck can check
them.  Added a regtest for this.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2244 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c
index 5ae3cfe..f1509ad 100644
--- a/coregrind/vg_syscalls.c
+++ b/coregrind/vg_syscalls.c
@@ -1810,13 +1810,28 @@
 		  arg2, sizeof( vki_cap_user_data_t) );
 }
 
+// Pre_read a char** argument.
+void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
+{
+   while (True) {
+      Addr a_deref = deref_Addr( tid, a, s1 );
+      if (0 == a_deref)
+         break;
+      SYSCALL_TRACK( pre_mem_read_asciiz, tid, s2, a_deref );
+      a += sizeof(char*);
+   }
+}
+
 PRE(execve)
 {
    /* int execve (const char *filename, 
       char *const argv [], 
       char *const envp[]); */
-   MAYBE_PRINTF("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n", 
-		arg1, arg1, arg2, arg3);
+   MAYBE_PRINTF("execve ( %p(%s), %p, %p )\n", arg1, arg1, arg2, arg3);
+
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "execve(filename)", arg1 );
+   pre_argv_envp( arg2, tid, "execve(argv)", "execve(argv[i])" );
+   pre_argv_envp( arg3, tid, "execve(envp)", "execve(envp[i])" );
 
    /* Erk.  If the exec fails, then the following will have made a
       mess of things which makes it hard for us to continue.  The
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index b94f2c1..2a2c7e5 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -24,6 +24,7 @@
 	error_counts.stderr.exp error_counts.stdout.exp error_counts.vgtest \
 	errs1.stderr.exp errs1.vgtest \
 	exitprog.stderr.exp exitprog.vgtest \
+	execve.stderr.exp execve.vgtest \
 	fprw.stderr.exp fprw.vgtest \
 	fwrite.stderr.exp fwrite.stdout.exp fwrite.vgtest \
 	inits.stderr.exp inits.vgtest \
@@ -68,7 +69,8 @@
 check_PROGRAMS = \
 	badaddrvalue badfree badjump badloop badrw brk buflen_check \
 	clientperm custom_alloc \
-	doublefree error_counts errs1 exitprog fprw fwrite inits inline \
+	doublefree error_counts errs1 exitprog execve \
+	fprw fwrite inits inline \
 	malloc1 malloc2 malloc3 manuel1 manuel2 manuel3 \
 	memalign_test memcmptest mmaptest nanoleak new_nothrow null_socket \
 	overlap pushfpopf \
@@ -93,6 +95,7 @@
 doublefree_SOURCES 	= doublefree.c
 error_counts_SOURCES 	= error_counts.c
 errs1_SOURCES 		= errs1.c
+execve_SOURCES 		= execve.c
 exitprog_SOURCES 	= exitprog.c
 fprw_SOURCES 		= fprw.c
 fwrite_SOURCES 		= fwrite.c
diff --git a/memcheck/tests/execve.c b/memcheck/tests/execve.c
new file mode 100644
index 0000000..0e8222d
--- /dev/null
+++ b/memcheck/tests/execve.c
@@ -0,0 +1,12 @@
+#include <unistd.h>
+
+int main(void)
+{
+   char* bad[2]  = { (char*)1, NULL };
+   char* good[1] = {           NULL };
+
+   execve(NULL, bad, bad);
+   execve("/bin/true", good, good);
+
+   return 0;
+}
diff --git a/memcheck/tests/execve.stderr.exp b/memcheck/tests/execve.stderr.exp
new file mode 100644
index 0000000..aee2580
--- /dev/null
+++ b/memcheck/tests/execve.stderr.exp
@@ -0,0 +1,14 @@
+Syscall param execve(filename) contains uninitialised or unaddressable byte(s)
+   at 0x........: execve (in /...libc...)
+   by 0x........: main (execve.c:8)
+ Address 0x........ is not stack'd, malloc'd or free'd
+
+Syscall param execve(argv[i]) contains uninitialised or unaddressable byte(s)
+   at 0x........: execve (in /...libc...)
+   by 0x........: main (execve.c:8)
+ Address 0x........ is not stack'd, malloc'd or free'd
+
+Syscall param execve(envp[i]) contains uninitialised or unaddressable byte(s)
+   at 0x........: execve (in /...libc...)
+   by 0x........: main (execve.c:8)
+ Address 0x........ is not stack'd, malloc'd or free'd
diff --git a/memcheck/tests/execve.vgtest b/memcheck/tests/execve.vgtest
new file mode 100644
index 0000000..51a8d51
--- /dev/null
+++ b/memcheck/tests/execve.vgtest
@@ -0,0 +1,2 @@
+prog: execve
+vgopts: -q