From 597999400ea763c3f9e5157db14279375f9f6e77 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 12 Nov 2014 18:44:11 -0600 Subject: [PATCH] execl() no longer depends on CONFIG_MAX_TASK_ARGS --- libc/unistd/lib_execl.c | 53 ++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/libc/unistd/lib_execl.c b/libc/unistd/lib_execl.c index fa50c14298..873bbc429e 100644 --- a/libc/unistd/lib_execl.c +++ b/libc/unistd/lib_execl.c @@ -47,6 +47,11 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* This is an artificial limit to detect error conditions where an argv[] + * list is not properly terminated. + */ + +#define MAX_EXECL_ARGS 256 /**************************************************************************** * Global Variables @@ -119,28 +124,60 @@ int execl(FAR const char *path, ...) { - FAR char *argv[CONFIG_MAX_TASK_ARGS+1]; + FAR char **argv; + size_t nargs; va_list ap; int argc; + int ret; + + /* Count the number of arguments */ + + va_start(ap, path); + for (nargs = 0, argc = 0; argv[argc]; argc++) + { + /* Increment the number of args. Here is a sanity check to prevent + * running away with an unterminated argv[] list. MAX_EXECL_ARGS + * should be sufficiently large that this never happens in normal + * usage. + */ + + if (++nargs > MAX_EXECL_ARGS) + { + set_errno(E2BIG); + return ERROR; + } + } + + va_end(ap); + + /* Allocate a temporary argv[] array */ + + argv = (FAR char **)malloc((nargs + 1) * sizeof(FAR char *)); + if (argv = (FAR char **)NULL) + { + set_errno(ENOMEM); + return ERROR; + } /* Collect the arguments into the argv[] array */ va_start(ap, path); - for (argc = 0; argc < CONFIG_MAX_TASK_ARGS; argc++) + for (argc = 0; argc < nargs; argc++) { argv[argc] = va_arg(ap, FAR char *); - if (argv[argc] == NULL) - { - break; - } } - argv[CONFIG_MAX_TASK_ARGS] = NULL; + argv[nargs] = NULL; va_end(ap); /* Then let execv() do the real work */ - return execv(path, (char * const *)&argv); + ret = execv(path, (char * const *)&argv); + + /* Free the allocated argv[] list */ + + free(argv); + return ret; } #endif /* CONFIG_LIBC_EXECFUNCS */ \ No newline at end of file