9

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.

3

4 Answers 4

9

It's implementation defined. §5.1.2.2.1 abridged:

  • If the value of argc is greater than zero, the array members argv[0] through argv[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 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. [...]

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.

Sign up to request clarification or add additional context in comments.

5 Comments

So in fact if argv[0][0] may be 0 argv[0] may 'be' empty.
@alk: argv[0] is never null when argc is greater than zero, but it may point to an empty string.
@KeithThompson: You name it ... ;-)
@GMan Thanks for your answer. Could you please let me know from where you get the C specification? f.e. Where do you get the info about 5.1.2.2.1 from?
@SangeethSaravanaraj: This is the latest draft of the C99 standard. This is the latest available draft of the recently published 2011 standard.
7

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

10 Comments

It can't be null, just empty. The previous paragraph requires that each argv point to a string (and that the last is null). A crappy implementation could supply them all with empty strings, but not all null.
If argc == 0, then argv[0] is a null pointer. (I hadn't quoted that part when you wrote your comment.)
It wasn't. I have upvoted, though, since our answers are similar.
@KeithThompson +1 for mentioning the exec() family of functions! Thanks!!
So do we simply assume the callers of exec invoked it according to the standard, program vulnerability aside @KeithThompson?
|
7

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.

1 Comment

+1 for the awesome example! It was indeed a lot of fun reading your post!! Thanks :)
1

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.

7 Comments

Isn't the OP asking about argv[0] referring to an empty string ("", {'\0'}), but to argv[0] being NULL?
@alk The OP is about empty/null string and not argv[0]=NULL
C++ does not allow you to call main(); C does.
if can be null then can be empty too (\0). The core of the answer is "when main is not invoked by system". An example ? well you can write a main in C which calls itself recursively without passing argv. in C main is just a function. However I think it's bad damn bad practice to invoke main directly. But we're not talking about good or bad practices, are we? See GMan & Keith answers for details about it. They're better than mine (they actually give refs).
Yes, if you call main recursively in C, you can pass any garbage values you like. Something like argc == 2, argv[1] == NULL is likely to break any normal argument processing. But that's just a bug in your code. You can safely make assumptions about argc and argv in the initial invocation of main.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.