Конфигурационные файлы curl с версии 8.12 по 8.16 обладают полнотой по Тьюрингу — и это вышло случайно.
Исследователи обнаружили, что конструкции в конфигурационных файлах утилиты curl позволяют реализовать любые вычислимые функции. Причина — два механизма: извлечение байтовых диапазонов из значений переменных и неограниченная глубина вложенности при подключении внешних конфигурационных файлов. Вместе они дают возможность строить машины Тьюринга, чего разработчики не планировали.
В качестве демонстрации через curl смоделировали двухсчётчиковую регистровую машину (машину Минского), сложение чисел и учебную программу «99 бутылок пива». Запуск — распаковать архив и выполнить команду «curl -q -s -K 99_bottles/main.conf». Значение счётчика представляется строкой из «n» символов «x»: инкремент и декремент реализуются через конкатенацию и усечение строк (синтаксис «[0-0]» оставляет только первый байт, «[1-]» — всё кроме первого байта), а переходы между состояниями управляются директивой «expand-config», динамически подгружающей следующий файл конфигурации по имени-метке. Так, INC(R) записывается как «expand-variable = «r={{r}}x»», DEC(R) — как «expand-variable = «r[1-]={{r}}»», а JMP(S) — как «expand-config = «S.conf»».
Практический потолок вычислений задаёт размер стека: каждый шаг программы требует загрузки нового вложенного файла конфигурации, и при стеке в 8 МБ переполнение наступает примерно после 922 шагов. Ограничивают возможности и лимит на размер раскрываемых переменных (параметр MAX_EXPAND_CONTENT — 10 МБ), и высокий расход памяти из-за хранения всех старых версий переменных.
Уязвимостью это не считается, но с curl 8.17 трюк больше не сработает: глубину вложенности конфигурационных файлов ограничили пятью уровнями ради защиты от бесконечной рекурсии.
