오픈소스 개발자 하르멘 스토펠스가 지난 7일 블로그를 통해 하나의 GNU tar 명령어로 생성된 아카이브가 다양한 추출 도구에서 8가지 상이한 방식으로 처리되는 사례를 공개했다. 이 아카이브는 ‘file’, ’empty’ 두 파일을 포함하며 ‘file’은 하드 링크로 중복 저장된다.
핵심은 pax 헤더에 추가된 size=512 기록이다. 이는 tar 헤더 하나의 크기와 정확히 일치하는 값으로 하드 링크의 기본 크기인 0을 덮어쓴다. 여기에 UTF-8 인코딩을 위해 파일명이 ‘café’로 변경되면서 pax 헤더가 생성되는 구조가 더해졌다.
POSIX 규격은 pax 아카이브에서 하드 링크에 데이터 블록이 포함될 수 있다고 명시하지만 그 의미는 명확하지 않다. 이 모호성 때문에 도구마다 해석이 갈린다. GNU tar, BusyBox, Python, Go, Perl은 하드 링크의 size 값을 무시하고 세 파일을 모두 정상적으로 추출한다.
반면 bsdtar는 512바이트 데이터를 하드 링크 내용으로 간주해 쓴다. 그 결과 원본 ‘file’ 내용이 tar 헤더 정보로 오염된다. 7-Zip, node-tar, Rust의 tar 라이브러리 등은 데이터를 건너뛰고 ‘file’과 ‘café’만 남긴다.
Java의 Commons Compress, PHP의 PharData, RubyGems 등도 각기 다른 동작을 보인다. .NET, Julia, uv의 tar-codec는 아카이브 자체를 거부한다. 이 테스트 케이스는 haampie/tar-minefield 스위트에 포함된 134개의 어려운 tar 파일 중 하나다.
개발자 커뮤니티에서는 엄격한 보안 지향적 추출과 관대한 최선 노력 추출 사이의 긴장감이 논의되고 있다. 일부는 데이터 손상을 감수하더라도 정보를 추출하는 것이 낫다는 의견을 제시하기도 했다.
현재로서는 POSIX 표준의 불명확한 부분이 해결되지 않은 상태다. 아카이브 추출 로직을 구축하거나 테스트하는 개발자들은 이러한 엣지 케이스 행동을 지속적으로 추적해야 한다.
