편집 : 예제에 대한 소스를 추가했습니다.
내가 건너 온 이 예 :
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );
이 출력은 다음과 같습니다.
목적지는 원래 = 'abcdefg' strcpy 이후 목적지는 '123456789'가됩니다. destination1은 원래 = 'abcdefg'입니다. strncpy 이후 destination1은 '12345fg'가됩니다.
왜 누군가가이 효과를 원하는지 궁금합니다. 혼란 스러울 것 같습니다. 이 프로그램은 기본적으로 Tom Bro763을 사용하여 누군가의 이름 (예 : Tom Brokaw)을 복사 할 수 있다고 생각하게합니다.
strncpy()
over 사용의 장점은 무엇입니까strcpy()
?
답변
strncpy
길이를 입력하도록 요구하여 버퍼 오버 플로우를 방지합니다. strcpy
후행에 의존하며 \0
항상 발생하지는 않습니다.
둘째, 7 자 문자열에 5 자만 복사하도록 선택한 이유는 저를 넘어서지 만 예상되는 동작을 생성합니다. 세 번째 인수가 있는 첫 번째 n
문자 만 복사합니다 n
.
이 n
함수는 모두 버퍼 오버플로에 대한 방어 코딩으로 사용됩니다. 와 같은 이전 기능 대신 사용하십시오 strcpy
.
답변
이 strncpy()
함수는 매우 특별한 문제를 염두에두고 설계되었습니다. 원래 UNIX 디렉토리 항목의 방식으로 저장된 문자열을 조작하는 것입니다. 이것들은 고정 된 크기의 배열을 사용했고, nul- 종결자는 파일 이름이 배열보다 짧은 경우에만 사용되었습니다.
이것이 두 가지 이상한 이유 뒤에 있습니다 strncpy()
.
- 완전히 채워지면 대상에 Nul- 종결자를 넣지 않습니다. 과
- 항상 목적지를 완전히 채우고 필요한 경우 nuls로 채 웁니다.
“안전한 strcpy()
“경우 다음 strncat()
과 같이 사용하는 것이 좋습니다 .
if (dest_size > 0)
{
dest[0] = '\0';
strncat(dest, source, dest_size - 1);
}
그것은 항상 결과를 무효화하고 필요 이상으로 복사하지 않을 것입니다.
답변
의 의도를 알고 있지만 strncpy
실제로 좋은 기능은 아닙니다. 둘 다 피하십시오. Raymond Chen이 설명합니다 .
개인적으로 내 결론은 단순히
strncpy
null로 끝나는 문자열을 다루는 경우 모든 친구들 을 피하는 것 입니다. 이름에 “str”이 있음에도 불구하고 이러한 함수는 null로 끝나는 문자열을 생성하지 않습니다. 널로 끝나는 문자열을 원시 문자 버퍼로 변환합니다. 두 번째 버퍼가 잘못되어 널로 끝나는 문자열이 예상되는 곳에서 사용합니다. 소스가 너무 길면 적절한 null 종료를 얻지 못할뿐만 아니라 소스가 짧으면 불필요한 null 패딩이 발생합니다.
strncpy가 안전하지 않은 이유 도 참조하십시오 .
답변
strncpy는 strcpy보다 안전하지 않으며 한 유형의 버그를 다른 유형과 교환 할뿐입니다. C에서 C 문자열을 처리 할 때 버퍼의 크기를 알아야합니다. strncpy는 다른 사람들이 언급 한 디렉토리 항목에 대해 정당화되었지만 그렇지 않으면 절대 사용해서는 안됩니다.
- 문자열과 버퍼의 길이를 알고 있다면 왜 strncpy를 사용합니까? 기껏해야 컴퓨팅 능력의 낭비입니다 (쓸모없는 0 추가).
- 길이를 모르면 버퍼 오버플로보다 낫지 않은 문자열을 조용히 잘라낼 위험이 있습니다.
답변
당신이 찾고 strlcpy()
있는 것은 항상 0으로 문자열을 종료하고 버퍼를 초기화하는 함수 입니다. 또한 오버플로를 감지 할 수 있습니다. 유일한 문제는 (정말) 이식성이없고 일부 시스템 (BSD, Solaris)에만 존재한다는 것입니다. 이 기능의 문제점은 http://en.wikipedia.org/wiki/Strlcpy 의 토론에서 볼 수 있듯이 또 다른 웜 캔을 열 수 있다는 것입니다
.
제 개인적인 의견은 strncpy()
및 보다 훨씬 더 유용하다는 것 strcpy()
입니다. 더 나은 성능을 가지고 있으며 snprintf()
. 이 기능이없는 플랫폼의 경우 구현하기가 비교적 쉽습니다. (응용 프로그램의 개발 단계에서는이 두 함수 ( snprintf()
및 strlcpy()
)를 버퍼 오버플로 또는 잘림시 프로그램을 잔인하게 중단하는 트 랩핑 버전으로 대체합니다 . 이렇게하면 최악의 공격자를 신속하게 잡을 수 있습니다. 특히 다른 사람의 코드베이스에서 작업하는 경우 .
편집 : strlcpy()
쉽게 구현할 수 있습니다.
size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t len = strlen(src);
if(dstsize) {
size_t bl = (len < dstsize-1 ? len : dstsize-1);
((char*)memcpy(dst, src, bl))[bl] = 0;
}
return len;
}
답변
이 strncpy()
함수는 더 안전한 함수입니다. 대상 버퍼가 허용 할 수있는 최대 길이를 전달해야합니다. 그렇지 않으면 소스 문자열이 올바르게 0으로 종료되지 않을 strcpy()
수 있습니다. 이 경우 함수는 대상에 더 많은 문자를 기록하여 대상 버퍼 이후의 메모리에있는 모든 것을 손상시킬 수 있습니다. 이것은 많은 익스플로잇에서 사용되는 버퍼 오버런 문제입니다.
또한 read()
버퍼에 종료 0을 넣지 않고 읽은 바이트 수를 반환하는 POSIX API 함수의 경우 수동으로 0을 넣거나 strncpy()
.
예제 코드에서는 index
실제로 인덱스가 아니지만 count
a- 소스에서 대상으로 복사 할 문자 수 를 나타 냅니다. 소스의 처음 n 바이트 중 널 바이트가없는 경우 대상에 배치 된 문자열은 널로 종료되지 않습니다.
답변
strncpy는 목적지의 크기가 더 작더라도 소스의 크기에 대해 ‘\ 0’으로 목적지를 채 웁니다 ….
맨 페이지 :
src의 길이가 n보다 작 으면 strncpy ()는 dest의 나머지 부분을 널 바이트로 채 웁니다.
나머지뿐만 아니라 …이 후 n 문자에 도달 할 때까지. 따라서 오버플로가 발생합니다 … (맨 페이지 구현 참조)