문제는 여기 있습니다 :
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
문자열이 대상 버퍼의 길이보다 큰 경우 strncpy는 여전히이를 복사합니다. 버퍼의 크기 대신 문자열의 문자 수를 복사 할 숫자로 지정합니다. 이를 수행하는 올바른 방법은 다음과 같습니다.
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
이것이하는 일은 버퍼의 실제 크기에서 널 종료 문자에 대한 1을 뺀 것으로 복사되는 데이터의 양을 제한합니다. 그런 다음 추가 된 보호 수단으로 버퍼의 마지막 바이트를 널 문자로 설정합니다. 그 이유는 strlenpy가 strlen (str) <len-1 인 경우 종료 널을 포함하여 최대 n 바이트까지 복사하기 때문입니다. 그렇지 않으면 널이 복사되지 않고 버퍼가 종료되지 않으므로 충돌 시나리오가 발생합니다. 끈.
도움이 되었기를 바랍니다.
편집 : 다른 사람의 추가 조사 및 입력시 기능에 대한 가능한 코딩은 다음과 같습니다.
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
문자열의 길이를 이미 알고 있으므로 memcpy를 사용하여 str이 참조하는 위치에서 버퍼로 문자열을 복사 할 수 있습니다. strlen (3)의 매뉴얼 페이지 (FreeBSD 9.3 시스템)에 따라 다음이 언급됩니다.
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
문자열의 길이에 null이 포함되어 있지 않다고 해석합니다. 그렇기 때문에 len + 1 바이트를 복사하여 null을 포함시키고 테스트는 길이 <buffer-2의 크기인지 확인합니다. 널을 위해.
편집 : 것으로 나타났습니다. 액세스가 0으로 시작하는 동안 무언가의 크기가 1로 시작하므로 98 바이트 이상이면 오류가 반환되지만 99 바이트 이상이어야합니다.
편집 : 부호없는 short에 대한 대답은 일반적으로 표현 할 수있는 최대 길이가 65,535 자이므로 정확하지만 문자열이 그보다 길면 값이 줄 바꿈되므로 실제로 중요하지 않습니다. 75,231 (0x000125DF)을 가져 와서 상위 16 비트를 마스킹하여 9695 (0x000025DF)를 제공하는 것과 같습니다. 길이 확인으로 복사가 가능하기 때문에 65,535 이후의 첫 100 문자는이 문제로 볼 수 있지만 문제는 문자열의 처음 100 자까지만 복사하고 null은 문자열을 종료합니다 . 따라서 랩 어라운드 문제가 있어도 버퍼가 여전히 오버플로되지 않습니다.
이것은 문자열의 내용과 사용하는 내용에 따라 보안 위험을 초래할 수도 있고 그렇지 않을 수도 있습니다. 사람이 읽을 수있는 단순한 텍스트라면 일반적으로 문제가 없습니다. 당신은 잘린 문자열을 얻습니다. 그러나 URL이나 SQL 명령 시퀀스와 같은 것이면 문제가있을 수 있습니다.