공부/C언어, C++

[C언어] 입력 함수 scanf, gets 버퍼 오버플로우

이니셜P 2023. 3. 8. 18:54
반응형
#include <stdio.h>

int main()
{
	char str_3[5];
	char str_2[5];
	char str_1[5];

	printf("Input str_3 : ");
	scanf("%s", str_3);

	printf("Input str_2 : ");
	scanf("%s", str_2);

	printf("Input str_1 : ");
	scanf("%s", str_1);

	printf("%s\n", str_3);
	printf("%s\n", str_2);
	printf("%s\n", str_1);

	return 0;
}

위와 같은 코드에

 


Input str_3 : aaa
Input str_2 : bbb
Input str_1 : ccc

이렇게 입력을 했다고 했을때

 

보통 정상적인 상황이라면

각 문자열 변수의 상태는 이럴 것이고

위와 같이 출력 되었을 것이다.

 


Input str_3 : aaa
Input str_2 : bbb
Input str_1 : abcdefgijklmnop

하지만 이렇게 입력하면 어떻게 될까?

 

난리난다.

 

표로 정리하면(PC 또는 태블릿 모드 추천)

 

str_1 메모리 영역 str_2 메모리 영역 str_3 메모리 영역 다른곳에서 쓰는 메모리 영역
c c c \0 \0 b b b \0 \0 a a a \0 \0          
↑ 시작 주소    끝 주소  ↑ 시작 주소    끝 주소  ↑ 시작 주소    끝 주소   

위와 같은 정상적인 상황의 메모리가

 

str_1 메모리 영역 str_2 메모리 영역 str_3 메모리 영역 다른곳에서 쓰는 메모리 영역
a b c d e f g h i j k l m n o p \0      
↑ 시작 주소    끝 주소  ↑ 시작 주소    끝 주소  ↑ 시작 주소    끝 주소  (메모리 영역 침범)

str_1의 버퍼 오버플로우로 이렇게 바뀐 것이다.

 

str_1에 입력한 문자열이 str_2와 str_3을 덮어썼고 각 문자열 변수에 담겨있던 문자열의 끝을 알려주는 문자(\0)도 덮어씌어져 먼저 출력을 하는 str_3는 덮어씌어진 시작 주소 k부터 다른곳에서 쓰는 메모리 영역에 있는 \0까지 출력하여 klmnop를 출력한다.

두번째 출력하는 str_2도 덮어씌어진 시작 주소 f부터 똑같이 \0까지 출력하여 f부터 p까지 출력한다.

마지막으로 출력하는 str_1 역시 마찬가지로 a부터 p까지 출력한다.

 

이것이 버퍼 오버플로우다.

 

나 같이 현재 배우고 있는 입장에서는 별거 아니네 할 수 있지만 현업에서는 큰 문제로 이어질 수 있다고 한다.

 

협업 프로젝트로 프로그램을 만들고 있는데 내 실수로 다른 팀원이 쓰는 메모리 영역에 침범하여 값을 바꿔서 나에게는 문제가 일어나지 않지만 그 팀원 코드에서만 문제점이 생긴다던지

게임을 예를 들면 맵에 있는 몬스터들의 피가 실행된 게임의 메모리 영역에서 관리되고 있는데 난 1번 몬스터를 때려서 피를 깎았는데 2번 몬스터의 피에도 영향을 미친다는 것이다.

 

모두 버퍼 오버플로우로 인한 버그다.

 

gets 함수도 마찬가지다.

 

해결법에 대한 글은 기회가 된다면 쓰는걸로

 

스택 오버플로우도 비슷한 원리로 일어나는 문제인데 이것도 기회가 된다면 쓰는걸로..

반응형