-
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를 고려해주기 위함이다.
'공부 > Algorithm' 카테고리의 다른 글
[BOJ] 16236번 아기 상어 (0) 2021.08.16 Hash, Hash function는 무엇일까? (해시 값 및 해시 함수 설명) (0) 2020.05.30 (Remote Sensing) Multispectral, Hyperspectral image의 차이 (0) 2020.05.05 (Remote Sensing) Pansharpening, Pansharpened image 는 무엇일까? (0) 2020.05.05