diff --git a/Documentation/NuttxUserGuide.html b/Documentation/NuttxUserGuide.html index 44445e8ce0..eb5a27f53d 100644 --- a/Documentation/NuttxUserGuide.html +++ b/Documentation/NuttxUserGuide.html @@ -271,8 +271,7 @@ int task_create(char *name, int priority, int stack_size, main_t entry, char * c

Note that an arbitrary number of arguments may be passed to the - spawned functions. The maximum umber of arguments is an OS - configuration parameter (CONFIG_MAX_TASK_ARGS). + spawned functions.

The arguments are copied (via strdup) so that the diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c index a250b22691..0dbd13b0ec 100644 --- a/binfmt/binfmt_exec.c +++ b/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,24 +138,22 @@ 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; } + + /* Terminate the argv[] list */ + + bin->argv[i] = (FAR char *)NULL; } } - /* Nullify the remainder of the list */ - - for (; i <= CONFIG_MAX_TASK_ARGS; i++) - { - bin->argv[i] = NULL; - } - return OK; #else diff --git a/binfmt/binfmt_unloadmodule.c b/binfmt/binfmt_unloadmodule.c index ce1b0e53d1..535942b0f6 100644 --- a/binfmt/binfmt_unloadmodule.c +++ b/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