sim: syscall: fix argvlen & argv implementation

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.
This commit is contained in:
Mike Frysinger
2021-11-16 00:03:50 -05:00
parent 8cfc9a1895
commit fab6939b01

View File

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