From: Mike Frysinger Date: Tue, 16 Nov 2021 05:03:50 +0000 (-0500) Subject: sim: syscall: fix argvlen & argv implementation X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fab6939b01da06e1b5f423a8c7f72160b0a1e35d;p=binutils-gdb.git 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. --- diff --git a/sim/common/syscall.c b/sim/common/syscall.c index e353d862504..bad3b3b6214 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. */