개발&Development/프로그래밍 일반

IsUTF8의 버그를 잡아라

겐도 2006. 3. 14. 03:26
이전에는 euc-kr을 쓰다가 어느 순간 많은 곳에서 Unicode를 사용하고 있다. 리눅스도 기존 데이터를 부었더니 한글이 제대로 안보이는 경우가 있고 구 터미널 프로그램들도 사용하기 어렵다. 어플리케이션도 슬슬 옮겨지는 듯 하고 웹페이지도 utf-8로 판별되는 경우가 많다. 이런 전환의 시점에서 필요한 함수중 하나가 utf-8 판별 함수. 이름하여 isUTF8.

bytesbitsrepresentation
17 0bbbbbbb
211 110bbbbb 10bbbbbb
3 16 1110bbbb 10bbbbbb 10bbbbbb
4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb

위의 표는 php의 헬프에서 참조하였다. 대부분의 구현은 크게 위를 벗어 나지 않는다. 10bbbbbb로 시작하지 못한다와 첫바이트에서 전체 길이가 정해지면 그 안의 데이터는 10bbbbbb로 되어야 한다는 것을 확인한다. 구글에서 찾아본 몇가지 구현에서도 위와 크게 다르지 않다.(참고 : Kdecore isUtf8 함수)

많은 곳에서 저정도 확인하고 잘 쓰고 있다. 허나.... 이번에 한번 된통 당했다. 바로 ""!

euc-kr에서 "웹"의 표현은 0xC0A5, 이것을 비트로 풀면 11000000 10100101. 매우 UTF-8 스럽다. 위의 로직에 따라 Unicode를 풀어보면 0x25가 나오니 이 유니코드에 해당하는 문자는 "%"가 된다. 즉 위의 로직만으로 확인하면 unicode라고 인식을 하게 되고 "%"를 보여주는 많은 프로그램들이 있다. 파일에 "웹"이란 글자만 적고 저장한 후 여러 에디터에서 테스트 해 보기 바란다.

이런 충돌상황이 발생하였을 때 가장 먼저 해 볼만한 것은 바로 표준을 확인하는 것. RFC 3629를 찬찬히 읽어 보기로 하였다. 그리고 바로 첫 페이지에서 구세주는 나타나셨도다.

o US-ASCII octet values do not appear otherwise in a UTF-8 encoded
character stream. This provides compatibility with file systems
or other software (e.g., the printf() function in C libraries)
that parse based on US-ASCII values but are transparent to other
values.

즉 %는 "웹"처럼 나타나서는 안된다. 그럼 UTF-8을 번역하는 루틴을 추가할 것인가? 아니다. 좀더 읽어보면 진정한 구세주가 있다.
o The octet values C0, C1, F5 to FF never appear.

즉 위의 수로 문자가 시작될 수 없다는 것이다. Ascii 영역에 대한 고려나 실제 Unicode의 코드 등을 종합해 보면 위의 결론에 도달할 수 있다. 아무튼 이런 조건을 통해 "웹"은 이 세상에 제대로 표시될 수 있는 것이다. (0xC0로 시작하기 때문에 UTF8이 아니다)


PS. 사실 전에도 한번 당했던 문제긴 하다. 다른 영역에서 다른 프로그래밍 언어였다 보니 기억이 안났다.
PS2. 많은 프로그램들이 저 버그를 가지고 있다. 따라서 권장사항으로.. 절대 "웹"을 처음에 쓰지 말것. --;
PS3. 어떤 코드를 보니 111110bb 즉 5바이트 케릭터도 처리하려는 노력을 보이기도 한다. 나름대로 노력이 가상하지만 잘!못!짠!거!다! 더불어 F5~FF라는 영역에 대해 Invalid라고 명확히 구분하는 경우도 거의 없다. 0xF8 정도 확인하는게 대부분이다.(4바이트 이하 확인)

참고자료 : Unicode는 http://unicode.org 가면 자료가 왕창 있다. UTF-8은 위에 적어둔 링크 따라가면 RFC를 볼 수 있다.