C++ 프로그래머의 일상: 모종의 디버깅

Berryz WebShare의 RAR 다운로드 플러그인에서 생기던 버그를 수정하는데 성공. + 약간의 버그를 추가로 잡았음.

Format 문자열이 당신을 속일지라도 노여워 말라

vsnprinf_s를 이용해서 로그 문자열을 출력하는 코드가 있다. 이걸 래핑한 함수가

WriteLog(const char* fmt, ...);

처럼 생겼는데, 포맷 문자열인 fmt 값으로 HTTP 요청으로 들어온 URI를 넣는 부분이 있더라. (WriteLog(URI) 모양)

  • URI에 ASCII 영역을 벗어나는 문자가 있다면 이 문자는 “%e3%80%90…” 하는 모양이 된다.
  • vsprinf 류의 함수들은 %s 처럼 %와 일부 영문자가 연속으로 오는 것을 어떤 “형식화된 출력” 문자로 간주한다.

이 두 가지가 합쳐지면? VS 2005가 부적절한 문자열 형식화라고 프로그램을 죽인다[…].

Buffer 길이를 잘 확인하자

문제가 좀 어이없을만큼 간단했는데(…), HTTP 요청에 대한 응답을 보낼 때 HTTP header의 각 행1 을 전송하는데, 이 때 고정길이 버퍼를 사용한게 문제. HTTP요청에 대한 응답으로 Content-Disposition이나 Location 같은 값은 굉장히 길어질 수 있는데(URI가 들어가서), 이게 다국어 문자가 많이 포함된 꽤 긴 문자열이면 4000바이트는 우습지도 않은 크기가 되는 경우가 생겼다. 이런 경우에 헤더가 짤려서 전송되는 문제 때문에 특정 웹부라우져에서 다운로드된 파일의 이름이 이상하거나 / 다운로드 자체가 안되거나 하는 문제가 있었다. 이 부분을 수정.2

STL 디버깅 + IE의 알 수 없는 동작

VS 2003에서 VS 2005로 넘어오면서 STL 디버깅 기능3 덕분에 몇 가지 버그를 더 잡았는데, 아마도 IE의 비표준 행위 때문에 생기는 듯하다. 대충 다음과 같은 작업을 하면 생기는데,

  1. IE에서 HTTP 요청을 보낸다. 일부가 POST method로 전송되야 한다.
  2. IE에서 F5로 refresh
  3. 다시 HTTP요청을 보낸다. 이때는 GET으로…
  4. POST로 0bytes가 전송된다. (정확히는 2bytes의 \r\n 가 가지만 이건 구분자)

이런 현상이 생기는듯하다. 그래서 some_vector<char> v 에 대해서 v[2]의 주소를 얻는 코드에서 STL 디버깅 코드가 assert-fail을 낸다.


  1. HTTP 요청/응답은 모두 \r\n 을 기준으로 구분되는 행들로 이루어져 있다. 예를 들어

    Content-Type: application/x-rar-compressed\r\n
    Content-Disposition: attachment; filename="SomeFile.rar"\r\n
    

    하는 식이다. (근데 이건 IE의 응답에 대한 요청이라 content-disposition이 좀 특이하다. FF/Opera쪽으로 보내는 응답형태가 표준인듯?) ↩︎

  2. 물론 길이를 체크하는 문자열 함수를 사용했기 때문에 overflow 오류같은 것은 없다 :p ↩︎

  3. index 체크나 iterator가 살아있는지 여부 등등을 검사해준다. 무척 맘에 드는 기능이다. VS 2005이상을 써야하는 이유 중 하나라고 생각함 ↩︎