문제
명령줄 인수를 문자 배열에 전달하는 두 가지 방법을 찾았습니다.
int main (int argc, char **argv)
{
const char *s1 = argv[0];
char s2[256];
strcpy(s2, argv[0]);
printf("s1: %s\ns2: %s\n\n", s1, s2);
}
AIX 시스템에서 IBM xlc 컴파일러로 컴파일됨
[내 프롬프트]> ./a.out
s1:./a.out
s2:./a.out
어떤 구현(s1 또는 s2)이 올바른가요?s1은 argv[0]의 길이에 제한이 없기 때문에 좋습니다.s2에서는 argv[0] 길이가 256자 미만이어야 합니다.
s1이 어떻게/왜 작동해야 하는지 이해하지 못합니다.나 생각하다 s1의 오른쪽은 컴파일 타임에 필요하지만 생각하다 런타임에 생성됩니다.
해결책
S1이 작동하는 이유는 ArgV의 유형 [0]이기 때문입니다. ~이다 포인터. 당신은 단순히 안전한 주소 (실제 값이 아님)를 할당하는 것입니다. 당신은 어떤 종류의 할당이나 캐스트를 수행하지 않습니다.
나는 일반적으로 인수 변수에서만 읽어야하기 때문에 첫 번째 옵션을 선호합니다.
다른 팁
문자열을 변경하고 싶지 않다면 S1이 작동합니다.
문자열을 변경하려면 문자열을 사본을 만들 수 있습니다. 시스템이 지원하는 경우 더 안전한 strnlen () 및 strncpy ()를 사용해야합니다.
컴파일 타임에 S1의 오른쪽은 필요하다고 생각하지만 런타임에 생성된다고 생각합니다.
아니요, 성명서가 발생할 때마다 필요합니다. 예를 들어:
void f() {
int x = 1;
...
}
정수 X는 컴파일 타임이 아닌 함수가 호출 될 때마다 1으로 초기화됩니다.
S2는 버퍼 오버런에 취약한 유쾌한 속성을 가지고 있습니다.
나는 사람들이 ARGV의 가치를 바꾸는 것을 보았다 [0]. 경우에 따라 (일부 OS에서) 변경되는 ARGV [0]는 프로그램을 변경 한대로 PS에 표시 할 수 있습니다.
인수를 변경하지 않고 참조만 하고 싶다면 s1 맞다.
어떤 방식으로든 인수를 수정해야 하는 경우 다음과 같이 인수의 복사본을 만들어야 합니다. s2 예를 들어, 그러나 s2 예를 들어 길이가 복사하려는 버퍼보다 긴지 명시적으로 확인해야 합니다.예를 들어 filename.jpg와 같은 인수를 입력으로 사용하고 filename.gif를 출력으로 저장하는 경우 확장자를 .jpg에서 .gif로 변경하므로 해당 인수의 복사본을 만들어야 합니다.
나는 S1, 특히 n> 0 인 Argv [n]에 대해 S1과 함께 갈 것입니다. S2와 같은 것은 클래식 버퍼 오버플로 공격을 위해 당신을 열어줍니다. 기본적으로, 사용자는 길이가 256자가 넘는 인수를 포맷하고 스택에 정보를 덮어 쓰면 원하는 코드를 실행할 수 있습니다.