C 표준 라이브러리의 기능을 위험하게 하는 것은 무엇이며, 대체 방법은 무엇입니까?
C를 학습하는 동안 일부 기능을 권장하는 리소스를 정기적으로 발견합니다(예:gets() )는에 절대하지 마십시오는 안전하게 사용하기 어렵거나 불가능하기 때문에 절대 사용하지 마십시오.
C 표준 라이브러리에 이러한 "절대 사용하지 않는" 함수가 다수 포함되어 있는 경우, 이러한 함수의 목록, 안전하지 않은 이유 및 대신 수행할 작업을 학습해야 합니다.
지금까지 다음과 같은 기능을 배웠습니다.
- 메모리 덮어쓰기를 방지할 수 없습니다.
- 문자열을 null로 종단하는 것은 보증되지 않습니다.
- 콜간의 내부 상태 유지
일반적으로 사용하기에 안전하지 않은 것으로 간주됩니다.이러한 행동을 보이는 기능 목록이 있습니까?그 밖에 안전하게 사용할 수 없는 기능이 있습니까?
ㅇㅇ.fgets(..., ..., STDIN)에 대한 좋은 대안이다.gets()size 파라미터( )가 필요하기 때문입니다.gets()C11)에서는 사실상 C 표준에서 완전히 삭제되었습니다.:fgets()님의 드롭인 대체품이 아닙니다.gets()의 끝부분을 \n버퍼에 완전한 행을 읽을 수 있는 공간이 있는 경우 문자.
scanf()입력이 예상 포맷에 맞지 않을 경우(입력 되감기 및 재시도 할 수 없기 때문에)는, 「불량」이 아니고, 경우에 따라서는 문제가 있다고 생각되는 경우가 있습니다.잘못된 형식의 입력을 포기할 수 있다면 사용할 수 있습니다.더 좋은'은 '더 좋은' 입력 입니다.fgets() ★★★★★★★★★★★★★★★★★」fgetc() 읽어야 한다, 한다, 읽어야 한다, 읽어야 한다, 읽어야 한다, 읽어야 한다.sscanf() 분석합니다.strchr() ★★★★★★★★★★★★★★★★★」strtol(), 다음의 에, 에, 에, 에, 의 구체적인 는, 을 "%s"의 scanf().
C 함수는 및 함수입니다mktemp()는 일반적으로 안전하게 사용할 수 없습니다.이는 파일의 존재 여부를 테스트한 후 작성하는 사이에 항상 TOCTTOU 레이스 조건이 존재하기 때문입니다. mkstemp() ★★★★★★★★★★★★★★★★★」tmpfile()를 대체할 수 있습니다.
strncpy()금금하다왜냐하면 공간이 없어도 수신처를 무효로 하지 않기 때문입니다.이 함수는 일반적인 이름에도 불구하고 일반적인 C 문자열과는 다른 특정 스타일의 문자열을 작성하기 위해 설계되었습니다.이 문자열은 필드를 정확히 채우는 경우 늘 터미네이터가 필요하지 않은 기존 고정 너비 필드에 저장됩니다(원래 UNIX 디렉토리 엔트리는 이 스타일입니다).이러한 상황이 아니라면 이 기능은 피하는 것이 좋습니다.
atoi()를 들어, 번호가 의를 알 수 때문에 이 될 수.int을 사용합니다.strtol()이게 너한테 중요한 일이라면 말이야
strcpy(),strcat() ★★★★★★★★★★★★★★★★★」sprintf() gets()- 대상 버퍼의 크기를 지정할 수 없습니다.적어도 이론상으로는 안전하게 사용하는 것이 가능합니다.그러나 사용하는 것이 훨씬 좋습니다.strncat() ★★★★★★★★★★★★★★★★★」snprintf()할 수 .)strncpy()★★★★★★★★★★★★★★★★★★★★★」, 「」는 해 주세요.n★★★★★★에snprintf()는, 버퍼의 은, 「Destination Buffer(행선지 버퍼입니다.n★★★★★★에strncat()는 추가할 최대 문자수이며 늘 터미네이터는 포함되지 않습니다.크기를 이미 한 경우 은 "이러한 문자열과 버퍼 크기를 계산하는 것입니다.memmove() ★★★★★★★★★★★★★★★★★」memcpy().
테마로 '를 한다면,scanf(), 사용 안 함, 플레인 사용 안 함, 플레인 사용 안 함"%s" - 수수(((((((((((((((((((((((((:"%200s".
옛날에는 대부분의 문자열 함수에 경계 검사가 없었습니다.물론 오래된 함수를 삭제하거나 상한을 포함하도록 시그니처를 수정할 수는 없습니다.이 경우 호환성이 깨집니다.이 기능들 중 거의 모든 기능에는 대체 "n" 버전이 있습니다.예를 들어 다음과 같습니다.
strcpy -> strncpy
strlen -> strnlen
strcmp -> strncmp
strcat -> strncat
strdup -> strndup
sprintf -> snprintf
wcscpy -> wcsncpy
wcslen -> wcsnlen
그리고 더 많이.
안전하지 않은 함수를 사용할 경우 gcc가 오류를 보고하는 헤더 파일을 만드는 프로젝트인 https://github.com/leafsr/gcc-poison도 참조하십시오.
엄밀히 말하면, 정말 위험한 기능이 하나 있습니다.렇렇 it it it it 。gets()왜냐하면 그 입력은 프로그래머의 통제 하에 있지 않기 때문이다.는, 전제 , 및 플레이트 코드라고 하는 됩니다."좋다"와 "나쁘다"는 결국 방어적 프로그래밍, 즉 전제조건, 사후조건 및 보일러 플레이트 코드로 귀결됩니다.
★★를 strcpy()예를들면.프로그래머가 함수를 호출하기 전에 충족해야 하는 몇 가지 전제 조건이 있습니다.두 문자열 모두 유효하고 NULL이 아닌 종료 문자열 0에 대한 포인터여야 합니다.또, 행선지는, 다음의 범위내에서, 최종 문자열 길이를 가지는 충분한 스페이스를 제공할 필요가 있습니다.size_t또한 문자열은 중복될 수 없습니다.
은 꽤 많은 이며, 도 「전제 조건」, 「전제 조건」에 의해서 되지 않습니다.strcpy()는 이 두 않으면 플레이트 한 후 해야 합니다.그렇지 않으면 콜을 하기 전에 추가 보일러 플레이트 코드를 사용하여 명시적으로 테스트해야 합니다.strcpy():
n = DST_BUFFER_SIZE;
if ((dst != NULL) && (src != NULL) && (strlen(dst)+strlen(src)+1 <= n))
{
strcpy(dst, src);
}
이미 오버랩되지 않은 문자열과 종료되지 않은 문자열을 사일런트하게 가정하고 있습니다.
strncpy()는 이러한 체크의 일부를 포함하지만, 결과가 제로 종료되지 않을 수 있기 때문에 함수를 호출한 후 프로그래머가 주의해야 할 다른 전제 조건을 추가합니다.
strncpy(dst, src, n);
if (n > 0)
{
dst[n-1] = '\0';
}
이러한 기능이 "나쁜" 것으로 간주되는 이유는 무엇입니까?왜냐하면 프로그래머가 유효성에 대해 잘못 가정할 때 각 콜에 대해 추가적인 보일러 플레이트 코드가 실제로 안전한 쪽에 있어야 하기 때문에 프로그래머는 이 코드를 잊어버리기 쉽습니다.
이 노래입니다.printf() 합니다.이러한 함수는 오류와 성공을 나타내는 상태를 반환합니다. 또는 에 대한 성공했는지 합니다.stdout stderr은 성공했는지 확인합니다.표준 채널이 작동하지 않으면 아무것도 할 수 없다는 주장과 함께.그럼 사용자 데이터를 복구하고 종료 코드를 오류 표시로 프로그램을 종료하는 것은 어떨까요?파손된 사용자 데이터로 크래시 및 굽기를 대신할 수 있습니다.
시간과 비용이 제한된 환경에서는 항상 얼마나 많은 안전망을 원하는지 그리고 그 결과 발생하는 최악의 시나리오는 무엇인지에 대한 문제입니다.str-functions의 경우와 같이 버퍼 오버플로우일 경우 이를 금지하고 안전망이 이미 설치된 상태에서 래퍼 기능을 제공하는 것이 타당합니다.
이에 대한 마지막 질문입니다.당신의 "좋은" 대안이 정말 좋다고 확신하는 이유는 무엇입니까?
strtok()는 일반적으로 콜 사이에 상태 정보를 저장하기 때문에 악으로 간주됩니다.멀티스레드 환경에서 IT를 실행하려고 하지 마십시오.
7페이지(PDF페이지 9) SAFCode 개발 프랙티스 보기
편집: 페이지에서 -
을 이루다
Strncpy에 대해 덧붙이자면 여기 있는 대부분의 사람들은 언급하는 것을 잊었다.strncpy는 지정된 길이로 버퍼를 클리어하기 때문에 성능 문제를 일으킬 수 있습니다.
char buff[1000];
strncpy(buff, "1", sizeof buff);
1글자를 복사하고 999바이트를 0으로 덮어씁니다.
strlcpy를 선호하는 또 다른 이유는 strlcpy가 BSDism이라는 것은 알지만 구현이 너무 쉬워서 사용하지 않을 이유가 없습니다.
최대 길이 매개변수를 사용하지 않고 대신 존재하는 마커 끝에 의존하는 기능(예: 많은 '끈' 처리 기능).
콜간에 상태를 유지하는 임의의 메서드.
sprintf는 하지 , 「」, 「」, 「」를 사용합니다.snprintfgmtime,localtimeuse gmtime_r,localtime_r
strcpy - 또!
대부분의 사람들은 strcpy가 위험하다는 것에 동의하지만 strncpy가 유용한 대체물이 되는 경우는 드물다.어떤 경우에도 문자열을 잘라낼 필요가 있는 타이밍을 아는 것이 중요합니다.이 때문에, 통상, 송신원스트링의 길이를 조사할 필요가 있습니다.이 경우 복사할 문자 수를 정확히 알 수 있으므로 보통 memcpy가 더 적합합니다.
예: 잘라내기 오류:
n = strlen( src );
if( n >= buflen )
return ERROR;
memcpy( dst, src, n + 1 );
잘라내기는 허용되지만 발신자가 알 수 있도록 문자 수를 반환해야 합니다.
n = strlen( src );
if( n >= buflen )
n = buflen - 1;
memcpy( dst, src, n );
dst[n] = '\0';
return n;
언급URL : https://stackoverflow.com/questions/1253053/what-makes-a-c-standard-library-function-dangerous-and-what-is-the-alternative
'source' 카테고리의 다른 글
| 예외에 정보를 추가하시겠습니까? (0) | 2022.12.03 |
|---|---|
| OS X의 sem_init (0) | 2022.11.24 |
| Python에서 확장자가 .txt인 디렉토리에서 모든 파일 찾기 (0) | 2022.11.24 |
| MySQL 계층 재귀 쿼리를 만드는 방법 (0) | 2022.11.24 |
| 코드의 메서드에서 현재 콜스택 인쇄 (0) | 2022.11.24 |