问题
In any C program, the command line argument argv[0]
points to the name used to invoke the program. Is there any circumstance in which it will point to an empty string ""
?
An example code snippet for such a case would be a good reference.
回答1:
It's implementation defined. §5.1.2.2.1 abridged:
If the value of
argc
is greater than zero, the array membersargv[0]
throughargv[argc-1]
inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. [...]If the value of
argc
is greater than zero, the string pointed to byargv[0]
represents the program name;argv[0][0]
shall be the null character if the program name is not available from the host environment. [...]
So if argc
is greater than zero, it's quite the intention that argv[0]
never be an empty string, but it could happen. (Note that with argc
equal to n
, argv[0]
through argv[n - 1]
are never null and always point to a string. The string itself may be empty, though. If n
is zero, argv[0]
is null.)
In practice, of course, you just need to make sure the platforms your targetting behave as needed.
回答2:
Yes.
The C language standard explicitly allows for the possibility that argv[0]
can be a null pointer, or that it can point to an empty string (""
). N1256 5.1.2.2.1p2:
The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.
[...]
If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
On Unix-like systems, programs are invoked by one of the exec()
family of functions (execl()
, execlp()
, etc.), which allow the caller to specify exactly what arguments are passed to the main()
function. (It's even possible to invoke a program in ways that violate the requirements imposed by the C standard.)
Note that the standard says that argv[0]
(assuming it's neither null nor empty) "represents the program name". The standard is deliberately vague about how it represents the program name. In particular, it needn't provide a name by which the program can be invoked (since the standard doesn't even require that programs can be invoked by name).
回答3:
Other replies have quoted the C standard and shown that argv[0]
and can be NULL
or it can be the empty string (""
). You should write your program with the assumption that this can happen, because otherwise you are creating a (small) security risk. It's easy to invoke your program and set argv
to anything an attacker wants. As proof, consider the following two programs. The first one, echoargv.c
prints out the contents of argv
:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i;
for (i = 0; i < argc; ++i)
printf("argv[%d] = \"%s\"\n", i, argv[i]);
exit(0);
}
The second one, argv0
, invokes any other program and lets the user specify the other program's argv:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
(void) execv(argv[1], argv+2);
perror("execv");
exit(1);
}
(This is a Posix-specific version. Non-standard environments may need changes.)
Here's how to use them:
$ gcc -o echoargv echoargv.c
$ gcc -o argv0 argv0.c
$ ./argv0 ./echoargv
$ ./argv0 ./echoargv ''
argv[0] = ""
$ ./argv0 ./echoargv 'this is fun' 'it is fun indeed'
argv[0] = "this is fun"
argv[1] = "it is fun indeed"
$
The first run of argv0
sets echoargv
's argv[0]
to be NULL.
The second run makes it be the empty string.
The third run is there just for fun: note how argv[0]
doesn't need to have
anything to do with the actual name of the program.
How can this bite you? If, for example, you blindly print out the name of your program in a usage message:
printf("usage: %s [options] [FILE]...\n", argv[0]);
Better:
const char *program_name = "some default name"; /* (global) variable */
if (argv[0] && argv[0][0])
program_name = argv[0];
printf("usage: %s [options] [FILE]...\n", program_name);
If you don't do this, an attacker can cause your program to segfault at will, or might get your program to report entirely wrong things to the user.
回答4:
argv[0] can be null in C, for example if you directly invoke a main function (with some tricks can be done in C). I don't know if C++ allows direct main invocation.
来源:https://stackoverflow.com/questions/8665439/can-argv0-contain-an-empty-string