GN⁺: Malloc이 Serenity의 JPGLoader를 망가뜨린 사건, 또는: 복권 당첨 비법 (2021)
(sin-ack.github.io)-
malloc이 SerenityOS의 JPGLoader를 망가뜨린 이유
-
SerenityOS에서 JPG 이미지를 디코딩할 때 색상이 잘못 표시되는 버그를 조사함
- RGB와 BGR의 혼동으로 보였으나, 코드 수정 후에도 문제가 해결되지 않음
-
Bisecting을 통한 문제 추적
- 최근 1000개의 커밋을 bisecting하여 문제의 원인을 찾기 시작함
- SerenityOS는 자체 표준 라이브러리 AK를 사용하며, 이는 C++의 STL과 유사하지만 더 읽기 쉬움
- AK의 변경이 전체 운영 체제에 영향을 미쳐 빌드 시간이 길어짐
-
Bisect 결과
- 문제를 일으킨 커밋을 찾아냄: malloc_good_size()를 구현한 커밋
- 이 커밋은 메모리 할당 크기를 최적화하여 메모리 낭비를 줄이는 기능을 추가함
-
놀라운 발견
- HashTable과 Vector가 문제의 원인일 가능성을 조사함
- HashTable의 용량을 변경한 후 문제가 해결됨
-
비결정적 시리얼 컴포넌트 반복
- JPGLoader는 JPG 파일의 컴포넌트를 HashTable에 저장하고 반복적으로 사용함
- 컴포넌트의 순서가 비결정적이어서 문제가 발생함
-
버그의 원인
- HashTable에 순서가 필요한 객체를 저장하고 기본 반복자를 사용함
- 컴포넌트 ID의 해시 값이 우연히 올바른 순서로 정렬됨
- HashTable의 크기 변경으로 인해 순서가 바뀌면서 문제가 발생함
-
해결책
- JPGLoader가 컴포넌트를 결정적으로 반복하도록 수정함
- HashTable 대신 순서가 보장되는 자료 구조를 사용함
-
최종 생각
- 간단한 문제도 큰 실수를 드러낼 수 있음
- 문제를 근본적으로 해결하여 재발을 방지함
-
감사의 말
- 디버깅에 도움을 준 동료들에게 감사함
- 버그를 발견하고 해결하는 과정에서 많은 것을 배움
GN⁺의 정리
- 이 글은 SerenityOS에서 발생한 JPG 이미지 디코딩 버그를 추적하고 해결하는 과정을 다룸
- HashTable의 비결정적 순서로 인해 발생한 문제를 결정적 순서로 변경하여 해결함
- 이 글은 소프트웨어 디버깅 과정의 중요성과 복잡성을 잘 보여줌
- 비슷한 기능을 가진 프로젝트로는 Linux의 libjpeg 등이 있음