# JY, 드래그 복사 금지

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C - strncat() 함수 제대로 사용하기 (버퍼 오버플로우 방지)
    공부/Algorithm 2021. 7. 22. 12:25

     

    • Dependency
    #include <string.h>

     

    • 내용 설명

    실무에서 strncat() 함수는 strcat()의 사용으로부터 발생할 수 있는 버퍼오버플로우를 방지하여 안전하게 사용하기 위해 사용한다.

     

    • 배경 지식
    char a[32] = "Hello"
    char b[32] = "World!"

    a는 1바이트씩 다음과 같이 저장되어 있다. -> H, e, l, l, o, \0(Null terminator)

    b는 1바이트씩 다음과 같이 저장되어 있다. -> W, o, r, l, d, \0(Null terminator)

     

    예를 들어 printf나 sprintf와 같은 문자열 출력 함수를 이용해 아래와 같은 구문으로 문자열을 출력한다고 하였을 때

    printf(a) // Hello
    printf(b) // World!

    컴파일러는 a, b의 시작주소로 부터 1바이트씩 스캔하며 Null terminator 를 만나기 직전까지를 하나의 문자열로 인식하게 된다. 따라서 위의 경우 Hello와 World! 까지만을 문자열로 인식하여 출력해주는 것이다.

     

    • Example
    strcat(a, b)

    위와 같이 strcat() 함수를 이용하면, a의 Null terminator 부터 b를 이어 붙여 준다. 

    즉, a는 다음과 같이 저장된다. -> H, e, l, l, o, W, o, r, l, d, !, \0(Null terminator)

     

    여기서 문제가 발생할 수 있는데, a의 크기에 상관없이 위와 같은 작업을 수행해주면

    a의 최초 배열 크기를 벗어난 영역에 데이터가 overwrite (버퍼 오버플로우) 될 수 있다는 문제가 있다.

     

    • 해결 방법

    strncat() 함수를 사용하여 버퍼 오버플로우를 방지하는 방법은 아래와 같다.

    strncat(a, b, sizeof(a)-strlen(a)-1)

    strncat() 함수의 마지막 인자는 버퍼 a에 대해 a의 Null terminator 로부터 몇 개(마지막 인자)의 바이트에만 버퍼 b의 문자열을 overwrite 할 것이냐는 것이다.

     

    a의 크기가 32이며 이미 32개의 바이트를 전부 문자열이 채우고 있을 때를 예로 들어보자.

    마지막번째 메모리에는 Null terminator가 존재할 것이므로 아래와 같다.

    a가 다음과 같이 저장되었을 때 -> A, B, C, ... X, Y, Z(31번째), \0(32번째)

    sizeof(a)-strlen(a)-1 은 32-31-1 = 0 이 된다. 즉, 0개의 문자열을 b로부터 string concat 함으로써 버퍼 오버플로우를 방지할 수 있다. 위의 식에 -1이 붙는 이유는 Null terminator를 고려해주기 위함이다.

     

     

     

    댓글

Designed by Tistory.