Home > Mobile >  Is it safe to use a char pointer in *argv[] directly in C?
Is it safe to use a char pointer in *argv[] directly in C?

Time:06-12

I have the following code to get a string from a user with getopt() in C:

#include <stdio.h>
#include <getopt.h>
#include "util.h"

int main(int argc, char *argv[]) {
    if (argc == 1) {
        usage(); // from util.h
        return 0;
    }

    char *argument = NULL;
    char ch;
    while ((ch = getopt(argc, argv, ":f:"))) {
        switch (ch) {
        case 'f':
            argument = optarg;
            break;
        }
    }
    // ... use `argument` with other stuff ...
}

Is this safe to do, or should I use strcpy() to copy the string into argument? If I accidentally change the contents of argument, could an attacker change stuff like environment variables?

CodePudding user response:

Is this safe to do, or should I use strcpy() to copy the string into argument?

It is safe to do, and getopt() is designed to be used that way. More generally, the program arguments provided to main are specified to be writable strings belonging to the program.

Do note, however, that some getopt() implementations, notably GNU's, may reorder the elements of argv.

If I accidentally change the contents of argument, could an attacker change stuff like environment variables?

The argument strings are susceptible to bounds overflow errors just like any other objects in the program. If, through programming error or other means, your program attempts to write past the bounds of any object then the behavior is undefined. Modification of environment variables is one of the more plausible members of the unbounded space of possible manifestations of UB.

Note, however, that making a copy of the arguments doesn't help in that regard. You must avoid overrunning the bounds of any such copies, too, lest UB be triggered, with the same unbounded space of possible manifestations.

If you want to make sure that the program arguments cannot be modified via variable argument, then it would be idiomatic to declare it as a pointer to const char instead of a pointer to (modifiable) char. That will not interfere with assigning the value of optarg to it.

CodePudding user response:

Yes, this is "safe".

The contents of argv are supplied by the host environment, and belong to your process for its entire duration.

On argv:

The strings are modifiable, and any modifications made persist until program termination, although these modifications do not propagate back to the host environment: they can be used, for example, with strtok.

With that said, privileged processes, like the ps utility, are generally capable of accessing the current values of argv. Using argv for sensitive information is ill advised.

See: Hiding secret from command line parameter on Unix and Can argv be changed at runtime (not by the app itself) for security concerns.


Aside: getopt returns an int. The distinction is important, because if char is unsigned, it cannot represent the terminating value:

If all command-line options have been parsed, then getopt() returns -1.

You should use int to reliably test against this value, otherwise the loop will continue infinitely.

int ch;

while (-1 != (ch = getopt(argc, argv, ":f:")))
  • Related