system() function string length limit

system exec's a shell with arguments "sh","-c", YourAgumentToSystem, (char*)0 (guaranteed by POSIX), so the maximum length (not counting the '\0' terminator) is ARG_MAX -1 -3 -3 - size_of_your_environment.

ARG_MAX is defined in limits.h as

"Maximum length of argument to the exec functions including environment data."

If limits.h, doesn't define ARG_MAX, you should be able to call sysconf(_SC_ARG_MAX) to obtain a runtime limit.

The linux manpage for execve (called by system) provides more information:

On Linux prior to kernel 2.6.23, the memory used to store the environment and argument strings was limited to 32 pages (defined by the kernel constant MAX_ARG_PAGES). On architectures with a 4-kB page size, this yields a maximum size of 128 kB.

On kernel 2.6.23 and later, most architectures support a size limit derived from the soft RLIMIT_STACK resource limit (see getrlimit(2)) that is in force at the time of the execve() call. (Architectures with no memory management unit are excepted: they maintain the limit that was in effect before kernel 2.6.23.) This change allows programs to have a much larger argument and/or environment list. For these architectures, the total size is limited to 1/4 of the allowed stack size. (Imposing the 1/4-limit ensures that the new program always has some stack space.) Since Linux 2.6.25, the kernel places a floor of 32 pages on this size limit, so that, even when RLIMIT_STACK is set very low, applications are guaranteed to have at least as much argument and environment space as was provided by Linux 2.6.23 and earlier. (This guarantee was not provided in Linux 2.6.23 and 2.6.24.) Additionally, the limit per string is 32 pages (the kernel constant MAX_ARG_STRLEN), and the maximum number of strings is 0x7FFFFFFF.

To measure the size of your environment, you can run:

extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;

(As Zan Lynx has pointed out in the comments, this can be sped up (cca 20 times as per my measurements—from 1600ns to 80ns for the 100-string 6KB environment I had when measuring) if you assume the char* pointers in environ point to a contiguous buffer, which they do after a program starts, but calls to setenv, putenv, or unsetenv typically break this:

extern char **environ;
char **e; for(e=environ; *e; e++) {}
size_t envsz =  ($_sz)(e[-1]+strlen(e[-1])+1 - *environ);

In any case, the speed up at the cost of robustness shouldn't matter much if you're expecting to fork+exec (/system) soon, given that fork+exec typically costs at least around 1-2ms on Linux on a modern machine.)


The limit is highly system dependent. It may even depend on the command shell that will be used. You should test the return value of system() to see if the system call was successful: -1 means failure and errno should give you more information. The behavior should be defined for any proper C string.

POSIX documents that system(command) is equivalent to:

execl(<shell path>, "sh", "-c", command, (char *)0);

And also documents ARG_MAX defined in <limits.h> as the limit for the combined lengths of the arguments to exec and the environment variables.

Note however that command may contain wildcards and/or other shell words whose expansion may exceed some other limit. Always check the return value for failure.

Tags:

Linux

C

Posix