[PATCH 3/6] sim: syscall: fix argvlen & argv implementation

Mike Frysinger vapier@gentoo.org
Tue Nov 16 08:36:19 GMT 2021


Now that we have access to the argv & envp strings, finish implementing
these syscalls.  Delete unused variables, fix tbuf by incrementing the
pointer instead of setting to the length, and make sure we don't write
more data than the bufsize says is available.
---
 sim/common/syscall.c | 92 ++++++++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/sim/common/syscall.c b/sim/common/syscall.c
index e353d862504a..bad3b3b6214d 100644
--- a/sim/common/syscall.c
+++ b/sim/common/syscall.c
@@ -141,16 +141,14 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc)
 
   switch (cb_target_to_host_syscall (cb, sc->func))
     {
-#if 0 /* FIXME: wip */
     case CB_SYS_argvlen :
       {
 	/* Compute how much space is required to store the argv,envp
 	   strings so that the program can allocate the space and then
 	   call SYS_argv to fetch the values.  */
-	int addr_size = cb->addr_size;
-	int argc,envc,arglen,envlen;
-	const char **argv = cb->init_argv;
-	const char **envp = cb->init_envp;
+	int argc, envc, arglen, envlen;
+	char **argv = cb->argv;
+	char **envp = cb->envp;
 
 	argc = arglen = 0;
 	if (argv)
@@ -164,7 +162,7 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc)
 	    for ( ; envp[envc]; ++envc)
 	      envlen += strlen (envp[envc]) + 1;
 	  }
-	result = arglen + envlen;
+	result = arglen + 1 + envlen + 1;
 	break;
       }
 
@@ -174,63 +172,73 @@ cb_syscall (host_callback *cb, CB_SYSCALL *sc)
 	TADDR tbuf = sc->arg1;
 	/* Buffer size.  */
 	int bufsize = sc->arg2;
+	int written = 0;
 	/* Q is the target address of where all the strings go.  */
 	TADDR q;
-	int word_size = cb->word_size;
-	int i,argc,envc,len;
-	const char **argv = cb->init_argv;
-	const char **envp = cb->init_envp;
+	int i, argc, envc, len, ret;
+	char **argv = cb->argv;
+	char **envp = cb->envp;
+
+	result = -1;
 
 	argc = 0;
 	if (argv)
 	  {
 	    for ( ; argv[argc]; ++argc)
 	      {
-		int len = strlen (argv[argc]);
-		int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
-		if (written != len)
-		  {
-		    result = -1;
-		    errcode = EINVAL;
-		    goto FinishSyscall;
-		  }
-		tbuf = len + 1;
+		len = strlen (argv[argc]) + 1;
+		if (written + len > bufsize)
+		  goto efault;
+
+		ret = (*sc->write_mem) (cb, sc, tbuf + written, argv[argc],
+					len);
+		if (ret != len)
+		  goto einval;
+
+		written += ret;
 	      }
 	  }
-	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
-	  {
-	    result = -1;
-	    errcode = EINVAL;
-	    goto FinishSyscall;
-	  }
-	tbuf++;
+	/* Double NUL bytes indicates end of strings.  */
+	if (written >= bufsize)
+	  goto efault;
+	if ((*sc->write_mem) (cb, sc, tbuf + written, "", 1) != 1)
+	  goto einval;
+	++written;
+
 	envc = 0;
 	if (envp)
 	  {
 	    for ( ; envp[envc]; ++envc)
 	      {
-		int len = strlen (envp[envc]);
-		int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
-		if (written != len)
-		  {
-		    result = -1;
-		    errcode = EINVAL;
-		    goto FinishSyscall;
-		  }
-		tbuf = len + 1;
+		len = strlen (envp[envc]) + 1;
+		if (written + len > bufsize)
+		  goto efault;
+
+		ret = (*sc->write_mem) (cb, sc, tbuf + written, envp[envc],
+					len);
+		if (ret != len)
+		  goto einval;
+		written += ret;
 	      }
 	  }
-	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
-	  {
-	    result = -1;
-	    errcode = EINVAL;
-	    goto FinishSyscall;
-	  }
+	/* Double NUL bytes indicates end of strings.  */
+	if (written >= bufsize)
+	  goto efault;
+	if ((*sc->write_mem) (cb, sc, tbuf + written, "", 1) != 1)
+	  goto einval;
+
 	result = argc;
 	sc->result2 = envc;
 	break;
+
+ efault:
+	errcode = EFAULT;
+	goto FinishSyscall;
+
+ einval:
+	errcode = EINVAL;
+	goto FinishSyscall;
       }
-#endif /* wip */
 
     case CB_SYS_exit :
       /* Caller must catch and handle; see sim_syscall as an example.  */
-- 
2.33.0



More information about the Gdb-patches mailing list