널리 사용되는 명령줄 데이터 전송 도구인 curl(컬)의 8.12부터 8.16 버전까지 약 9개월 동안, 의도치 않게 튜링 완전성(Turing Completeness)을 갖추고 있었다는 흥미로운 사실이 뒤늦게 밝혀졌습니다. 이는 curl의 설정 파일에서 변수 값 슬라이싱(slicing)과 깊이 제한 없는 설정 파일 포함(include) 기능이 결합되면서, 이론적으로 어떤 계산이든 수행할 수 있는 2카운터 민스키 머신(Minsky Machine)을 모방할 수 있게 되었기 때문입니다.
구체적으로, curl 설정 파일 내에서 변수 'x'의 개수로 카운터 값을 표현하고, 각 명령 상태를 별도의 설정 파일로 정의했습니다. 'expand-config' 명령으로 다음 실행할 설정 파일을 선택하고, 변수 확장 및 슬라이싱 기능을 활용해 카운터 증가(INC), 감소(DEC), 영(Zero) 검사 후 조건 분기(JZ), 그리고 점프(JMP)와 같은 민스키 머신의 핵심 연산을 구현할 수 있었습니다. 예를 들어, 'expand-variable = "r={{r}}x"'는 카운터 'r'을 증가시키고, 'expand-variable = "r[1-]={{r}}"'는 첫 바이트를 제거해 카운터를 감소시키는 방식입니다. 이러한 방식으로 2+3을 계산하거나 '99 Bottles of Beer on the Wall' 노래를 출력하는 개념 증명(PoC) 코드도 제시되었습니다.
물론 이러한 튜링 완전성은 이론적인 것으로, 실제 curl 바이너리에서는 확장 크기, 스택 메모리, 열린 파일 수 등 물리적인 자원 제약으로 인해 무한한 계산을 수행할 수는 없습니다. 예를 들어, 최소 카운트다운 반복 실험에서는 8MB 스택으로 922단계 실행 후 세그멘테이션 오류(Segmentation Fault)가 발생하기도 했습니다. curl 개발팀은 8.17 버전부터 설정 파일 포함 깊이를 5단계로 제한하여 이러한 의도치 않은 튜링 완전성 구현 경로를 차단했습니다. 이 제한의 주된 목적은 설정 파일이 자기 자신을 무한히 포함하는 무한 루프를 방지하는 것이었으며, 튜링 완전성 자체를 막기 위함은 아니었습니다.
이번 사례는 소프트웨어 개발에서 의도치 않게 강력한 계산 능력이 부여될 수 있음을 보여주는 좋은 예시입니다. 개발자 커뮤니티에서는 '우연히 생겨나는 튜링 완전성'에 대한 흥미로운 토론이 이어졌으며, 특히 문자열 재작성 시스템이 유연한 규칙을 반복 적용할 때 쉽게 튜링 완전성을 갖게 된다는 점이 강조되었습니다. 이는 보안 관점에서 '임의 코드 실행(Arbitrary Code Execution)' 가능성과 실제 악용 가능성을 구분하는 중요한 논의로 이어지기도 합니다. curl의 이번 사례는 직접적인 보안 위협은 없었지만, 소프트웨어의 복잡한 상호작용이 예상치 못한 결과를 낳을 수 있다는 점을 다시 한번 상기시켜 줍니다.