diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-11-12 18:31:32 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-11-12 18:31:32 -0600 |
commit | 12c4a9fe2ca2a1483c87f4c0bf9cb362580e9421 (patch) | |
tree | dbe1fd377b0bc1e15cad76ab6249b9de408cc8b0 /nuttx/binfmt | |
parent | dadf6c080c22acc418abea5dc7f55fcc2df16d92 (diff) | |
download | px4-nuttx-12c4a9fe2ca2a1483c87f4c0bf9cb362580e9421.tar.gz px4-nuttx-12c4a9fe2ca2a1483c87f4c0bf9cb362580e9421.tar.bz2 px4-nuttx-12c4a9fe2ca2a1483c87f4c0bf9cb362580e9421.zip |
Binfmt no longer depends on a fixed sized argv[] list
Diffstat (limited to 'nuttx/binfmt')
-rw-r--r-- | nuttx/binfmt/binfmt_exec.c | 47 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_unloadmodule.c | 8 |
2 files changed, 42 insertions, 13 deletions
diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c index a250b2269..0dbd13b0e 100644 --- a/nuttx/binfmt/binfmt_exec.c +++ b/nuttx/binfmt/binfmt_exec.c @@ -53,6 +53,11 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* This is an artificial limit to detect error conditions where an argv[] + * list is not properly terminated. + */ + +#define MAX_EXEC_ARGS 256 /**************************************************************************** * Private Function Prototypes @@ -80,31 +85,51 @@ static inline int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *ar { #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) FAR char *ptr; + size_t argvsize; size_t argsize; + int nargs; int i; - /* Get the size of the argument list */ + /* Get the number of arguments and the size of the argument list */ + bin->argv = (FAR char **)NULL; bin->argbuffer = (FAR char *)NULL; i = 0; if (argv) { argsize = 0; - for (i = 0; i < CONFIG_MAX_TASK_ARGS && argv[i]; i++) + nargs = 0; + + for (i = 0; argv[i]; i++) { + /* Increment the size of the allocation with the size of the next string */ + argsize += (strlen(argv[i]) + 1); + nargs++; + + /* This is a sanity check to prevent running away with an unterminated + * argv[] list. MAX_EXEC_ARGS should be sufficiently large that this + * never happens in normal usage. + */ + + if (nargs > MAX_EXEC_ARGS) + { + bdbg("ERROR: Too many arguments: %lu\n", (unsigned long)argvsize); + return -E2BIG; + } } bvdbg("args=%d argsize=%lu\n", i, (unsigned long)argsize); - /* Allocate a temporary argument buffer */ + /* Allocate the argv array and an argument buffer */ i = 0; if (argsize > 0) { - bin->argbuffer = (FAR char *)kmm_malloc(argsize); + argvsize = (nargs + 1) * sizeof(FAR char *); + bin->argbuffer = (FAR char *)kmm_malloc(argvsize + argsize); if (!bin->argbuffer) { bdbg("ERROR: Failed to allocate the argument buffer\n"); @@ -113,22 +138,20 @@ static inline int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *ar /* Copy the argv list */ - ptr = bin->argbuffer; - for (; i < CONFIG_MAX_TASK_ARGS && argv[i]; i++) + binp->argv = (FAR char **)bin->argbuffer; + ptr = bin->argbuffer + argvsize; + for (; i < argv[i]; i++) { bin->argv[i] = ptr; argsize = strlen(argv[i]) + 1; memcpy(ptr, argv[i], argsize); ptr += argsize; } - } - } - /* Nullify the remainder of the list */ + /* Terminate the argv[] list */ - for (; i <= CONFIG_MAX_TASK_ARGS; i++) - { - bin->argv[i] = NULL; + bin->argv[i] = (FAR char *)NULL; + } } return OK; diff --git a/nuttx/binfmt/binfmt_unloadmodule.c b/nuttx/binfmt/binfmt_unloadmodule.c index ce1b0e53d..535942b0f 100644 --- a/nuttx/binfmt/binfmt_unloadmodule.c +++ b/nuttx/binfmt/binfmt_unloadmodule.c @@ -228,13 +228,19 @@ int unload_module(FAR struct binary_s *binp) #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) void binfmt_freeargv(FAR struct binary_s *binp) { + /* Is there an allocated argument buffer */ + if (binp->argbuffer) { /* Free the argument buffer */ kmm_free(binp->argbuffer); - binp->argbuffer = NULL; } + + /* Nullify the allocated argv[] array and the argument buffer pointers */ + + binp->argbuffer = (FAR char *)NULL; + binp->argv = (FAR char **)NULL; } #endif |