sprintf/snprintf 중 어느 것이 더 안전한가?
다음 두 가지 옵션 중 어떤 옵션을 더 안전하게 사용할 수 있는지 알고 싶다.
#define MAXLEN 255
char buff[MAXLEN + 1]
sprintf(buff, "%.*s", MAXLEN, name)
snprintf(buff, MAXLEN, "%s", name)
내가 이해한 것은 둘 다 같다는 것이다.추천 좀 해줘.
가장 은 장고 장고를 하는 이다.snprintf
!
size_t nbytes = snprintf(NULL, 0, "%s", name) + 1; /* +1 for the '\0' */
char *str = malloc(nbytes);
snprintf(str, nbytes, "%s", name);
C99년에snprintf
문자열에 쓰여진 바이트 수를 반환하며, 문자열에는 바이트 수를 제외한다.'\0'
만약 필요한 바이트의 양보다 적다면,snprintf
형식을 확장하는 데 필요했을 바이트 수(아직은 제외됨)'\0'
. 지나가면서.snprintf
길이 0의 끈, 확장된 문자열의 길이를 미리 알아내고 필요한 메모리를 할당하는 데 사용할 수 있다.
당신이 준 두 가지 표현은 동등하지 않다.sprintf
쓰기 위한 최대 바이트 수를 지정하는 인수를 사용하지 않고 단순히 대상 버퍼, 형식 문자열 및 여러 개의 인수를 필요로 한다.따라서, 그것은 당신의 버퍼에 공간이 있는 것보다 더 많은 바이트를 쓸 수 있고, 그렇게 함으로써 임의 코드를 쓸 수 있다.그%.*s
다음과 같은 이유로 만족스러운 해결책이 아니다.
- 형식 지정자가 길이를 가리킬 때, 그것은 같은 길이를 가리킨다.
strlen
; 이 값은 문자열의 문자 수를 측정하는 척도로, 메모리의 길이가 아니다(즉, null terminator를 계산하지 않음). - 형식 문자열을 변경하면(예를 들어, 새 줄을 추가하면) 의 동작이 변경된다.
sprintf
버퍼 오버플로와 관련된 버전와 함께snprintf
, 형식 문자열 또는 입력 유형의 변경에 관계없이 고정되고 명확한 최대값이 설정된다.
라고 말하고 싶다.snprintf()
내가 이 구절을 읽기 전까지는 훨씬 더 낫다.
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/838-BSI.html
간략한 요약:snprintf()
시스템에서 시스템으로의 행동 변화를 휴대할 수 없다.는 장문휴가 있다.snprintf()
에 일어날 수 있다.snprintf()
단순히 전화만으로 실행된다.sprintf()
은 그것이 당신을 오버플로로부터 한다고 생각할지 도 모른다당신은 그것이 당신을 버퍼 오버플로로부터 보호하고 당신의 경계를 늦추었다고 생각할지 모르지만, 그렇지 않을지도 모른다.
그래서 지금 나는 여전히 말한다.snprintf()
더 안전하면서도 내가 그것을 사용할 때 조심하는 것.
질문의 간단한 예로, 두 통화의 보안에 큰 차이가 없을 수 있다.그러나 일반적인 경우에는snprintf()
ab ma 더전할 야야 일단 좀 더 형식 , 다른 길이를 수 있다 불가능에 가까울 수 있다). 변환에서는 출력 때문이다일단 다중 변환 규격을 가진 더 복잡한 형식 문자열을 갖게 되면, 특히 이전 변환에서 반드시 고정된 수의 출력 문자를 생성하지 않기 때문에 서로 다른 변환에서 버퍼 길이를 정확하게 설명하기 어려울 수 있다(또는 거의 불가능에 가까울 수 있음).
그래서, 난 계속 할거야snprintf()
.
에 대한 또 다른 작은 이점snprintf()
(보안과 관련된 것은 아니지만) 얼마나 큰 버퍼가 필요한지 알려준다는 것이다.
최종 노트 - 에서 실제 버퍼 크기를 지정하십시오.snprintf()
전화 - 귀하를 위한 null 터미네이터에 대한 회계 처리:
snprintf(buff, sizeof(buff), "%s", name);
이 둘 사이에는 중요한 차이점이 있다.snprintf
콜이 스캔을 할 것이다.name
정확한 반환 값을 알아내기 위해 끝까지의 인수(NUL 종료)그sprintf
, MOST .name
.
그래서 만약name
255자 이상의 비 NUL 종료 버퍼에 대한 포인터,snprintf
호출은 버퍼의 끝에서 실행되어 정의되지 않은 동작(충돌 등)을 트리거하는 동안sprintf
버전은 그렇지 않을 것이다.
당신의 스프린트f 진술은 정확하지만, 나는 그것을 안전 목적으로 사용할 자신이 없다(예: 하나의 암호문자를 놓치면 당신은 방패가 없다). 주변에 어떤 형식에도 적용될 수 있는 스프린트가 있다...oh wait snprintf는 ANSI C에 없다.(그냥?)C99. 다른 것을 선호하기 위한 (약한) 이유일 수도 있다.
음. 넌 할 수 있어.strncpy
너도 그럴 수 있었니?
예)
char buffer[MAX_LENGTH+1];
buffer[MAX_LENGTH]=0; // just be safe in case name is too long
strncpy(buffer,MAX_LENGTH,name); // strncpy will never overwrite last byte
둘 다 원하는 결과를 주겠지만snprintf
보다 일반적이며, 주어진 형식 문자열과 상관없이 오버런으로부터 문자열을 보호할 수 있다.
게다가 때문에snprintf
(또는)sprintf
그 문제에 대해서) 결승전을 추가하다.\0
, 당신은 끈 버퍼를 1바이트 더 크게 만들어야 한다.char buff[MAXLEN + 1]
.
참조URL: https://stackoverflow.com/questions/7315936/which-of-sprintf-snprintf-is-more-secure
'programing' 카테고리의 다른 글
랜드()를 사용할 때 이 특정 색상 패턴을 얻는 이유는? (0) | 2022.04.20 |
---|---|
람다를 연재하는 방법? (0) | 2022.04.20 |
루트 Vue 구성 요소의 Vue.use vs Vue.component (0) | 2022.04.20 |
Vuejs 계산된 속성 및 jquery ui 정렬 가능 문제 (0) | 2022.04.20 |
Vue 계산 세터를 통해 Vuex 작업 호출 (0) | 2022.04.20 |