summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/Documentation/NuttxUserGuide.html3
-rw-r--r--nuttx/binfmt/binfmt_exec.c47
-rw-r--r--nuttx/binfmt/binfmt_unloadmodule.c8
3 files changed, 43 insertions, 15 deletions
diff --git a/nuttx/Documentation/NuttxUserGuide.html b/nuttx/Documentation/NuttxUserGuide.html
index 44445e8ce..eb5a27f53 100644
--- a/nuttx/Documentation/NuttxUserGuide.html
+++ b/nuttx/Documentation/NuttxUserGuide.html
@@ -271,8 +271,7 @@ int task_create(char *name, int priority, int stack_size, main_t entry, char * c
</P>
<p>
Note that an arbitrary number of arguments may be passed to the
- spawned functions. The maximum umber of arguments is an OS
- configuration parameter (<code>CONFIG_MAX_TASK_ARGS</code>).
+ spawned functions.
</p>
<p>
The arguments are copied (via <code>strdup</code>) so that the
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