programing

sprintf/snprintf 중 어느 것이 더 안전한가?

prostudy 2022. 4. 20. 21:47
반응형

sprintf/snprintf 중 어느 것이 더 안전한가?

다음 두 가지 옵션 중 어떤 옵션을 더 안전하게 사용할 수 있는지 알고 싶다.

#define MAXLEN 255
char buff[MAXLEN + 1]
  1. sprintf(buff, "%.*s", MAXLEN, name)

  2. 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다음과 같은 이유로 만족스러운 해결책이 아니다.

  1. 형식 지정자가 길이를 가리킬 때, 그것은 같은 길이를 가리킨다.strlen; 이 값은 문자열의 문자 수를 측정하는 척도로, 메모리의 길이가 아니다(즉, null terminator를 계산하지 않음).
  2. 형식 문자열을 변경하면(예를 들어, 새 줄을 추가하면) 의 동작이 변경된다.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.

그래서 만약name255자 이상의 비 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

반응형