programing

C에서 scanf가 버퍼 오버플로를 발생시키지 않도록 하려면 어떻게 해야 합니까?

copysource 2022. 7. 16. 13:28
반응형

C에서 scanf가 버퍼 오버플로를 발생시키지 않도록 하려면 어떻게 해야 합니까?

다음 코드를 사용합니다.

while ( scanf("%s", buf) == 1 ){

랜덤 길이의 문자열을 전달할 수 있도록 버퍼 오버플로를 방지하는 가장 좋은 방법은 무엇입니까?

다음과 같이 호출하여 입력 문자열을 제한할 수 있습니다.

while ( scanf("%20s", buf) == 1 ){

다만, 유저가 입력하는 것은 무엇이든 처리할 수 있으면 좋겠다고 생각하고 있습니다.아니면 scanf로 안전하게 할 수 없고 fget으로 해야 하나요?

Kernighan과 Pike는 그들의 책 "The Practice of Programming" (읽을 가치가 충분히 있는 책)에서 이 문제에 대해 논의하고, 그들은 그것을 이용하여 해결한다.snprintf().scanf()★★★★★★★★★★★★★★★★★★:

int scanner(const char *data, char *buffer, size_t buflen)
{
    char format[32];
    if (buflen == 0)
        return 0;
    snprintf(format, sizeof(format), "%%%ds", (int)(buflen-1));
    return sscanf(data, format, buffer);
}

이 경우에도 입력은 '버퍼'로 제공되는 크기로 제한됩니다.공간이 더 필요한 경우 메모리 할당을 수행하거나 메모리 할당을 수행하는 비표준 라이브러리 기능을 사용해야 합니다.


POSIX 2008 (2013) 버전의 함수 패밀리는 형식 수식자를 지원합니다.m입력용(할당 문자)%s,%c,%[)를 하는 대신char *「」가 합니다.char **인수에 필요한 공간을 할당합니다.

char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
    printf("String is: <<%s>>\n", buffer);
    free(buffer);
}

경우,sscanf()가 모든 하지 못한 "에된 모든 가 ""에 할당됩니다.%ms가 반환되기 like 변환은 함수가 반환되기 전에 해제됩니다.

를 사용하고 는, GNU gcc 를 할 수 .a에 의해 :scanf()를 유지할 수 합니다.

int main()
{
  char *str = NULL;

  scanf ("%as", &str);
  if (str) {
      printf("\"%s\"\n", str);
      free(str);
  }
  return 0;
}

편집: Jonathan이 지적한 바와 같이scanf가 다를 수 있는 (man pages%m컴파일할 때 특정 정의를 활성화해야 할 수 있습니다.

의 경우, 「」의 입니다.fgets ★★★★★★★★★★★★★★★★★」sscanf그 일을 해냅니다.다른 하나는 입력 형식이 올바른 경우 파서를 직접 작성하는 것입니다.또한 두 번째 예제를 안전하게 사용하려면 약간의 수정이 필요합니다.

#define LENGTH          42
#define str(x)          # x
#define xstr(x)         str(x)

/* ... */ 
int nc = scanf("%"xstr(LENGTH)"[^\n]%*[^\n]", array); 

입력 되지 않습니다(「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」).\n의 문자의 문자입니다. 때 '어울리다'를 넣어야 .getchar()이것을 소비합니다.끝에 하십시오.

if (!feof(stdin)) { ...

이게 끝입니다.

directly 를 직접 scanf(3)그리고 그 변형은 많은 문제를 일으킵니다.일반적으로 사용자와 비인터랙티브 사용 사례는 입력 라인의 관점에서 정의됩니다. 번째 줄에 몰랐을 과 세 번째 되지 않을 수 (사용자가 첫 번째 줄에 숫자를 입력하는 것을 몰랐을 경우 두 번째 줄과 세 번째 줄은 도움이 되지 않을 수 있습니다.)

적어도 당신이fgets(3)프로그램에 필요한 입력 라인의 수를 알고 버퍼 오버플로우가 발생하지 않습니다.

입력의 길이를 제한하는 것은 확실히 간단합니다.루프를 사용하여 한 번에 비트를 읽고 필요에 따라 문자열을 위한 공간을 재할당함으로써 임의의 길이의 입력을 받아들일 수 있습니다.

하지만 많은 작업이 필요하기 때문에 대부분의 C 프로그래머는 임의의 길이로 입력을 잘라냅니다.이미 알고 계실 거라고 생각합니다만, fgets()를 사용하면 임의의 양의 텍스트를 받아들일 수 없습니다.아직도 제한을 설정할 필요가 있습니다.

문자열에 필요한 메모리를 할당하는 함수를 만드는 것은 그다지 어렵지 않습니다.그건 내가 얼마 전에 쓴 작은 c-함수야, 난 항상 그걸 현악기로 읽을 때 쓰거든.

읽기 문자열이 반환되거나 메모리 오류가 발생할 경우 NULL이 반환됩니다. 단, 문자열을 해제()하고 반환 값을 항상 확인해야 합니다.

#define BUFFER 32

char *readString()
{
    char *str = malloc(sizeof(char) * BUFFER), *err;
    int pos;
    for(pos = 0; str != NULL && (str[pos] = getchar()) != '\n'; pos++)
    {
        if(pos % BUFFER == BUFFER - 1)
        {
            if((err = realloc(str, sizeof(char) * (BUFFER + pos + 1))) == NULL)
                free(str);
            str = err;
        }
    }
    if(str != NULL)
        str[pos] = '\0';
    return str;
}

언급URL : https://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c

반응형