Может ли argv [0] содержать пустую строку? - PullRequest
8 голосов
/ 29 декабря 2011

В любой C-программе аргумент командной строки argv[0] указывает на имя, используемое для вызова программы.Есть ли обстоятельства, при которых он будет указывать на пустую строку ""?

Примером фрагмента кода для такого случая будет хорошая ссылка.

Ответы [ 4 ]

9 голосов
/ 29 декабря 2011

Это реализация определена. §5.1.2.2.1 сокращенно:

  • Если значение argc больше нуля, элементы массива argv[0] through argv[argc-1] включительно должен содержать указатели на строки, которые даны значения, определенные реализацией средой хоста до запуска программы. намерение состоит в том, чтобы предоставить программе информацию, определенную до ее запуска из другого места в размещенной среде. [...]

  • Если значение argc больше нуля, строка, на которую указывает argv[0] представляет название программы; argv[0][0] должен быть нулевым символом, если Имя программы недоступно в хост-среде. [...]

Так что если argc больше нуля, то вполне намерение состоит в том, что argv[0] никогда не будет пустой строкой, но это может произойти. (Обратите внимание, что с argc, равным n, argv[0] до argv[n - 1] никогда не равны нулю и всегда указывают на строку. Однако сама строка может быть пустой. Если n равно нулю, argv[0] нуль.)

На практике, конечно, вам просто нужно убедиться, что платформы, на которые вы нацеливаетесь, ведут себя так, как нужно.

7 голосов
/ 29 декабря 2011

Да.

Стандарт языка C явно допускает возможность того, что argv[0] может быть нулевым указателем, или , что он может указывать на пустую строку (""). N1256 5.1.2.2.1p2:

Значение argc должно быть неотрицательным.

argv [argc] должен быть нулевым указателем.

[...]

Если значение argc больше нуля, строка указывает на argv [0] представляет имя программы ; argv [0] [0] должно быть нулевой символ, если имя программы недоступно с хоста среда. Если значение argc больше единицы, строки обозначенные argv [1] через argv [argc-1] представляют программные параметры .

В Unix-подобных системах программы вызываются одной из функций семейства exec() (execl(), execlp() и т. Д.), Которые позволяют вызывающей стороне точно указывать, какие аргументы передаются в main() функция. (Можно даже вызывать программу способами, которые нарушают требования, установленные стандартом C.)

Обратите внимание, что в стандарте говорится, что argv[0] (при условии, что он не является ни нулевым, ни пустым) " представляет имя программы". Стандарт намеренно расплывчат в отношении , как представляет название программы. В частности, ему не нужно указывать имя, по которому можно вызывать программу (поскольку стандарт даже не требует, чтобы программы вызывались по имени).

5 голосов
/ 29 декабря 2011

Другие ответы цитировали стандарт C и показали, что argv[0] и может быть NULL, или это может быть пустая строка (""). Вы должны написать свою программу с предположением, что это может произойти, потому что в противном случае вы создаете (небольшую) угрозу безопасности. Вы можете легко вызвать вашу программу и установить argv на то, что хочет атакующий. В качестве доказательства рассмотрим следующие две программы. Первый, echoargv.c распечатывает содержимое 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);
}

Второй, argv0, вызывает любую другую программу и позволяет пользователю указать 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);
}

(Это версия для Posix. Нестандартные среды могут нуждаться в изменениях.)

Вот как их использовать:

$ 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"
$ 

Первый запуск argv0 устанавливает echoargv s argv[0] в NULL. Второй запуск делает это пустой строкой. Третий прогон здесь просто для удовольствия: обратите внимание, что argv[0] не нужно иметь все, что связано с реальным названием программы.

Как это может вас укусить? Если, например, вы слепо распечатываете название вашей программы в сообщении об использовании:

printf("usage: %s [options] [FILE]...\n", argv[0]);

Лучше:

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

Если вы этого не сделаете, злоумышленник может заставить вашу программу по умолчанию вызывать segfault или заставить вашу программу сообщать пользователю о совершенно неправильных вещах.

1 голос
/ 29 декабря 2011

argv [0] может быть нулевым в C, например, если вы напрямую вызываете основную функцию (с некоторыми приемами можно сделать в C). Я не знаю, разрешает ли C ++ прямой основной вызов.

...