Выпуск новостей завершён 15 сентября 2026. Материалы сохранены на дату публикации. Перейти к инструкциям →

Архив · Полный материал · Tproger

libheif 1.23.4 закрыла уязвимости при чтении и декодировании HEIF

libheif 1.23.4 чинит квадратичный разбор iinf (23 МБ файла дают 1,5 ГБ памяти), рекурсию в проверке ссылок, вечный дедлок декодера и падение WebAssembly-сборки. — Читать дальше « libheif 1.23.4 закрыла уязвимости при чтении и декодировании HEIF »

Безопасность · TprogerИгорь Плотников4 минуты
Перейти к тексту ↓
libheif 1.23.4 закрыла уязвимости при чтении и декодировании HEIF
Tproger
Коротко о главномРазвернутьСвернуть
  1. 4, библиотека для чтения и записи HEIF и AVIF, которую используют для работы с изображениями.
  2. Выпуск закрывает шесть уязвимостей , три из них с высокой оценкой, и объявлен ABI- и API-совместимой заменой 1.
  3. 3: релиз сохраняет интерфейсы предыдущей версии.

Вышла libheif 1.23.4, библиотека для чтения и записи HEIF и AVIF, которую используют для работы с изображениями. Выпуск закрывает шесть уязвимостей , три из них с высокой оценкой, и объявлен ABI- и API-совместимой заменой 1.23.3: релиз сохраняет интерфейсы предыдущей версии. Это уже третий выпуск безопасности подряд после 1.23.2 и 1.23.3, все шесть проблем нашёл один исследователь под ником hackerman70000.

Уязвимости затрагивают разные этапы обработки файла. Для ошибки iinf/max_items достаточно чтения контейнера через heif_context_read_from_file , без декодирования изображения. Отдельная проблема возникает при обходе ссылок на этапе декодирования, а взаимная блокировка потоков связана с параллельным декодированием grid-тайлов. Поэтому проверка только загрузки метаданных не воспроизводит все три проблемы с высокой оценкой.

Как одна неучтённая ветка отключила лимит на число элементов

В отчёте описана классическая ошибка перегруженного параметра. Функция Box::read_children принимает max_number , у которого два смысла: со значением-сентинелом READ_CHILDREN_ALL она читает до конца бокса и проверяет лимит max_items , а с любым другим числом читает ровно столько детей и ничего не проверяет. Box_iinf::parse передавала туда счётчик из самого файла, поэтому проверка, написанная специально для iinf, никогда не выполнялась.

Дальше цена растёт квадратично: для каждого элемента вызывается полный проход по списку ссылок iref без раннего выхода. Исследователь измерил на одном ядре 1,7, 6,0 и 23 секунды для файлов в 1,0, 2,0 и 4,1 МБ; абсолютные цифры различаются вдвое между машинами, но рост в 3–4 раза на каждое удвоение стабилен против 2 раз у линейного парсера. Всё это происходит внутри вызова, который затем возвращает heif_error_Ok , без коллбэка отмены и прогресса. В 1.23.4 лимит проверяется заранее, объявленное число ограничено оставшимся входом, а запросы к iref индексируются по идентификатору элемента: на файле с 1 000 элементов и 160 000 ссылок dimg время чтения упало с 1,83 до 0,26 секунды.

Сборка под WebAssembly страдала отдельно. Два вспомогательных метода в Emscripten-обвязке выделяли массив идентификаторов через alloca с размером из того же счётчика. Скрипт сборки не задаёт ни размер стека, ни проверку его переполнения, поэтому использовался стек по умолчанию в 64 КБ: 16 000 элементов занимают 64 000 байт и декодируются, 17 000 прерывают вызов, а с 18 000 переполнение уходит в сегмент статических данных и экземпляр модуля перестаёт работать до перезагрузки страницы. Хелпер вызывается при каждом HeifDecoder.decode() .

Рекурсия и дедлок: две другие высокие уязвимости

Вторая проблема : проверка на циклы ссылок между производными элементами была рекурсивной, и длинная цепочка исчерпывала стек. Без лимита на число элементов глубина ничем не ограничена. Исправленный обход на этапе декодирования использует явный рабочий список в куче вместо рекурсии.

Третья проблема затрагивает серверы с параллельным декодированием: параллельное декодирование тайлов grid включено по умолчанию, а ImageItem::decode_image() держит нерекурсивный мьютекс элемента на время вложенных декодирований. Два рабочих потока, чьи элементы ссылаются друг на друга, берут два мьютекса в противоположном порядке и зависают навсегда; процесс не падает и не освобождает ресурсы. Исправление отклоняет циклические графы декодирования, включая рёбра dimg и alpha auxl, до старта.

Кому обновляться в первую очередь

Всем, кто принимает HEIC и AVIF от пользователей: это серверные конвертеры, бэкенды фотохостингов и мессенджеров, CI-пайплайны с ImageMagick, а также веб-приложения, которые декодируют HEIC на клиенте через libheif-js или собственную Emscripten-сборку. Для последних важно, что обрушение WebAssembly-модуля необратимо в рамках страницы. Мейнтейнеры советуют обновиться всем пользователям; в дистрибутивах смотрите на пакет libheif1 или libheif в вашем менеджере. Уязвимость средней важности в плагине WebCodecs касается только Emscripten-сборок с WITH_WEBCODECS=ON , по умолчанию выключенной опции, и только без libde265.

Отдельный отчёт о расходе ресурсов опубликован для Go-библиотеки Excelize: файл на 3 КБ заставляет библиотеку выполнять произвольное число итераций хеширования, и патча пока нет (исправление в сохранённом отчёте не указано). Из недавних выпусков безопасности того же масштаба мы разбирали curl 8.22.0 с девятью уязвимостями и внеочередные релизы PostgreSQL от Postgres Pro .

Источники: libheif v1.23.4 – security maintenance, release notes , GHSA-vg7w-rp49-4fc2: The max_items security limit is not enforced for iinf child boxes , GHSA-xrp2-63fq-jm8q: Unbounded iref entry list and unbounded recursion , GHSA-prgh-72vc-3xmc: Lock-order inversion in parallel grid tile decoding