버퍼 오버런 버그

By | 2011/12/23

  수업 프로젝트 중 하나가 C++로 작성된 라이브러리를 이용하여 프로그램을 만드는 것이었습니다. 프로젝트 자체는 큰 어려움이 없었지만, 난감한 것이 하나 있었습니다. 학부 때는 C나 C++, Perl을 자주 썼으나 대학원 진학 후 Java와 Python을 쓰게 되어 C++을 오랜만에 사용한 것입니다. Visual Studio 2010을 비롯한 C/C++ 개발 환경이 제대로 갖추어지지 않은 상황이었기에 그런 것을 설정하는 것부터 하였습니다.

  그렇게 코딩을 하고 실험을 하는데 갑자기 버그가 발생한 것입니다.

c001

  갑자기 나타난 버그라서 왜 그런가 살펴보고자 디버그를 눌렀습니다. 사실 학부생 때에는 Windows XP를 쓰다가 대학원 진학 후 Windows 7을 쓰게 되어 저런 메시지 창도 어색하더군요.^^

c002

  메시지는 위와 같았습니다.

Grid_World.exe에서 버퍼 오버런이 발생하여 프로그램의 내부 상태가 손상되었습니다. 프로그램을 디버깅하려면 [중단]을 누르고 프로그램을 종료하려면 [계속]을 누르십시오.

c003

  그러면서 보여주는 화면의 코드는 잘 이해가 되지 않더군요.

 

  일단 버퍼 오버런? 그것이 무엇인지 잘 몰라서 찾아보았습니다.

In computer security and programming, a buffer overflow, or buffer overrun, is an anomaly where a program, while writing data to a buffer, overruns the buffer’s boundary and overwrites adjacent memory. This is a special case of violation of memory safety.

출처: http://en.wikipedia.org/wiki/Buffer_overflow

  Buffer overflow를 얘기한 것이군요. 그런데 왜 버퍼 오버플로우가 발생했는지 이해가 되지 않았습니다. 일단 step을 밟아가며 디버깅을 해보니 함수를 반환할 때 제대로 되지 않는 것을 알았습니다. 그 때 한 가지가 떠오르더군요.

버퍼 오버플로우 방법 중 하나로 함수 내부의 배열에 크기 이상을 할당하여 다른 메모리 공간에 덮어쓰게 되면, stack의 return address 등을 바꿀 수 있다.

 

  그래서 살펴보니 정말 그런 경우가 발생하였습니다.

c005

  위의 코드가 바로 문제의 코드입니다. 결과를 적기 위해 파일을 열어야 합니다. 그런데 실험의 파라메터마다 결과를 저장하기를 바라였기에 파일명을 조금 길게 하였습니다. 그런데 처음에는 output_num과 ep만을 파일명에 적었습니다. 따라서 %f로 출력하여도 50 bytes 안에 파일명이 다 들어갈 수 있었습니다.

  그러다가 필요에 의해 lambda를 추가하였고 그 덕분에 파일명이 50을 넘어가게 되었습니다. 즉, 할당된 배열의 크기 이상으로 값을 할당한 것입니다.

  버그의 문제점을 알아냈기에 간단히 buffer의 크기를 50에서 100으로 늘렸습니다. 그리고 작동시키니 문제 없이 프로그램이 작동하는 것을 확인하였습니다.

 

  개인적으로는 이번 버그를 보며 웃음이 많이 나왔습니다.

  C나 C++을 배울 때 여러 얘기를 들었습니다.

  • 해당 언어에서는 메모리 관리를 프로그래머가 하기에 프로그래밍을 하기에 피곤하다.
  • 해당 언어에서는 buffer overflow를 조심해야 한다.
  • 배열의 크기에 신경을 써서 할당을 해야 한다.

  이러한 얘기들을 들으면서 ‘알아서 조심하면 되는 것이 아닌가?’ 혹은 ‘너무 당연한 얘기를 하는 것 아닌가?’를 하면서 별 공감을 하지 않았습니다. 그런데 이제야 그 말이 공감이 된다는 것을 느끼게 되었던 것입니다.

 

  더하여 이러한 문제(?)가 발생한 이유를 생각해보니 그간 Java와 Python에서 문자열 처리를 자동으로 잘 해주었기 때문이 아닌가 하는 생각이 들었습니다. 사실 Perl을 쓸 때 문자열을 너무 편하게 쓸 수 있었기에 ‘이런 획기적인 프로그래밍 언어가 있다니!’라며 감탄을 하며 사용하였습니다.

  그러다 이제는 Java와 Python을 자주 쓰게 되었기에 그런 것은 너무나 당연한 것이 되어버린 것 같습니다. 사실 위에서 파일명을 설정하는 것은 Java로 작성한 프로그램으로 실험을 할 때 문제 없이 하던 짓(?)이라서 아무런 거리낌없이 C++에서도 한 것입니다. 조심해야 함에도 말입니다. 하지만 사실 String Class를 쓰면 문제가 없을 듯싶습니다. 다만, C++도 100% 객체지향적으로 사용한 것이 아니라 C의 확장판으로 인지하면서 사용하던 버릇이 남아있어 그렇게 짠 것도 문제 이유 중 하나일 것입니다.OTL

 

  여하튼 대학교 학부 1학년 때 흔히 하는 프로그래밍 실수 중 하나를 설마 하게 되리라고는 생각도 못했습니다. 그런 것을 보면서 웃을 수 밖에 없는 것 같습니다.

Leave a Reply