Can argc overflow?
I was wandering in SO and saw this question. Then I started wondering if I can overflow argc.
Standard says that argv[argc]
must be a null pointer but this will be false if argc overflow.
(I wrote a small C program and a python script to test it but got a MemoryError
.)
Thanks!
Rationale for International Standard — Programming Languages — C §5.1.2.2.1 Program startup
The specification of
argc
andargv
as arguments tomain
recognizes extensive prior practice.argv[argc]
is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.
Solution 1:
According to the standard
So, from your quote:
argv[argc]
is required to be a null pointer
Therefore, argc
cannot overflow, because then the above statement would not be true.
In practice
In practice, the total size of the arguments passed to a program is limited.
On my Linux/x64 system:
$ getconf ARG_MAX 2097152
Therefore, the total argument size is about 2 megabytes, and argc
cannot overflow. I believe this limit measures a combination of the total data in argv
and the environment. If you exceed this limit when you try to run a command, exec()
will fail with E2BIG
. From man 2 execve
:
E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.
I believe the ~2 megabyte limit on my system is relatively generous compared to other systems. My OS X system reports a limit of ~260KB.
But what if ARG_MAX
were really big?
Okay, let's suppose you're on an old/weird system, so int
is 16 bits, and ARG_MAX is well over 215, which is otherwise quite reasonable. Now, suppose you invoke execve()
with more than 215 arguments. The implementation has two options.
It can allow
argc
to overflow... basically, throwing away your data, ensuring that the program you're running executes in some unexpected and probably erroneous manner, and violating the C standard. Worst of all, the error is silent, so you might never know.Or, it can simply return
EOVERFLOW
fromexecve()
, informing you that it simply can't run an image with that many parameters. Now, the POSIX / SUS standards don't mention anything about this error result... but, I suspect this is simply because the standard writers never expectedARG_MAX
to be larger thanINT_MAX
.
Option #2 is the only reasonable option. If your system somehow chooses option #1, then it is broken and you should file a bug report.
Alternatively, you could be trying to run an old program compiled for a 16-bit system, but you're running it through some kind of emulator or compatibility layer. I'd expect that the emulator or compatibility layer would give an error message if you tried to pass more than 215 parameters to a program.
Solution 2:
In practice, no, you can't. Most systems place a relatively low limit on the total combined size of argv
and envp
. Limits in the tens to low hundreds of KB aren't uncommon; see http://www.in-ulm.de/~mascheck/various/argmax/ for a reasonably comprehensive listing of the limits on various OSes.
Solution 3:
I tried this:
test.c :
⚡⚡⚡ more test.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("argc = %d\n", argc);
printf("Size of argc = %d\n", sizeof(argc));
return 0;
}
Then used a big zipfile
⚡⚡⚡ ls -h bigfile
-rw-r--r-- 1 ehwas ehwas 355M Jan 22 16:54 bigfile
Then read the file as parameters to the test program:
⚡⚡⚡ ./test $(more bigfile)
Result:
5 minutes nothing happend, then everything froze
Then I tried a smaller file:
⚡⚡⚡ ls -h notsobigfile
-rw-r--r-- 1 ehwas ehwas 6.7M Jan 22 17:04 notsobigfile
And:
⚡⚡⚡ ./test $(more notsobigfile)
bash: ./test: Argument list too long
Solution 4:
As indicated by the standard, argv[argc] must be a valid value.
So if the run-time environment is in a situation such that it cannot guarantee that, it should not start the program.