Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

system() function string length limit

Tags:

c

linux

posix

How long can be a string passed to system()?

I know the POSIX minimum is 4096, but I would like to know the actual size I can use. Is there any macro defined in any header for that, similar to FILENAME_MAX?

char cmd[SOME_MACRO];

...
system(cmd);
like image 817
alx Avatar asked Apr 13 '19 15:04

alx


People also ask

What is the maximum possible length of a string?

While an individual quoted string cannot be longer than 2048 bytes, a string literal of roughly 65535 bytes can be constructed by concatenating strings.

How do I limit the length of a string in C++?

You can construct a string with the capacity to hold 50 characters by using: std::string str(50, '\0'); However, unlike C arrays, it is possible to increase its size by adding more data to it.

How do I limit the length of a string in Python?

Use a formatted string literal to format a string and limit its length, e.g. result = f'{my_str:5.5}' . You can use expressions in f-strings to limit the string's length to a given number of characters.

How long can string be vb net?

Environment String Length. There is a maximum of 32768 characters for any environment string used as a command-line argument.


2 Answers

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.)

like image 181
PSkocik Avatar answered Sep 28 '22 17:09

PSkocik


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.

like image 32
chqrlie Avatar answered Sep 28 '22 17:09

chqrlie