Binfmt no longer depends on a fixed sized argv[] list

This commit is contained in:
Gregory Nutt 2014-11-12 18:31:32 -06:00
parent fcffafee30
commit 7c119ba787
3 changed files with 44 additions and 16 deletions

View File

@ -271,8 +271,7 @@ int task_create(char *name, int priority, int stack_size, main_t entry, char * c
</P> </P>
<p> <p>
Note that an arbitrary number of arguments may be passed to the Note that an arbitrary number of arguments may be passed to the
spawned functions. The maximum umber of arguments is an OS spawned functions.
configuration parameter (<code>CONFIG_MAX_TASK_ARGS</code>).
</p> </p>
<p> <p>
The arguments are copied (via <code>strdup</code>) so that the The arguments are copied (via <code>strdup</code>) so that the

View File

@ -53,6 +53,11 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * 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 * 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) #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
FAR char *ptr; FAR char *ptr;
size_t argvsize;
size_t argsize; size_t argsize;
int nargs;
int i; 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; bin->argbuffer = (FAR char *)NULL;
i = 0; i = 0;
if (argv) if (argv)
{ {
argsize = 0; 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); 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); 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; i = 0;
if (argsize > 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) if (!bin->argbuffer)
{ {
bdbg("ERROR: Failed to allocate the argument buffer\n"); 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 */ /* Copy the argv list */
ptr = bin->argbuffer; binp->argv = (FAR char **)bin->argbuffer;
for (; i < CONFIG_MAX_TASK_ARGS && argv[i]; i++) ptr = bin->argbuffer + argvsize;
for (; i < argv[i]; i++)
{ {
bin->argv[i] = ptr; bin->argv[i] = ptr;
argsize = strlen(argv[i]) + 1; argsize = strlen(argv[i]) + 1;
memcpy(ptr, argv[i], argsize); memcpy(ptr, argv[i], argsize);
ptr += argsize; ptr += argsize;
} }
}
}
/* Nullify the remainder of the list */ /* Terminate the argv[] list */
for (; i <= CONFIG_MAX_TASK_ARGS; i++) bin->argv[i] = (FAR char *)NULL;
{ }
bin->argv[i] = NULL;
} }
return OK; return OK;

View File

@ -228,13 +228,19 @@ int unload_module(FAR struct binary_s *binp)
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
void binfmt_freeargv(FAR struct binary_s *binp) void binfmt_freeargv(FAR struct binary_s *binp)
{ {
/* Is there an allocated argument buffer */
if (binp->argbuffer) if (binp->argbuffer)
{ {
/* Free the argument buffer */ /* Free the argument buffer */
kmm_free(binp->argbuffer); 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 #endif