Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск

C++ отправляют на заслуженный отдых. Chrome переходит на Rust для спасения от старых дыр

Картинки на веб-страницах выглядят безобидно, но именно то, как их обрабатывают, годами остаётся одним из слабых мест браузеров. Разработчики Chromium постепенно переводят декодеры изображений с C++ на Rust, чтобы сократить число уязвимостей, связанных с повреждением памяти, и при этом не сделать сайты медленнее.

Браузер получает изображения напрямую из интернета и начинает разбирать их ещё до того, как файл загрузится полностью. Специально подготовленная картинка может использовать ошибки в декодере, вызвать сбой или запустить вредоносный код. Особенно часто такие проблемы возникают в крупных и сложных компонентах на C++, где трудно полностью исключить, что программа обратится к неверным участкам памяти.

Первым рабочим примером стал декодер PNG на Rust. Он показал, что в Chromium можно внедрить более безопасный язык, не теряя в совместимости и быстродействии. Позже к проекту присоединилась Microsoft и помогла превратить единичный эксперимент в общую схему, которую можно применять к другим форматам.

Следующим форматом стал BMP. Специалисты Microsoft создали новый декодер на основе библиотеки image для Rust и доработали её так, чтобы браузер мог обрабатывать файл частями по мере того, как он загружается. Такой режим обязателен для Chromium, поскольку браузер не ждёт, пока получит всю картинку, и начинает обрабатывать её сразу.

Новый декодер BMP уже работает в браузерах на основе Chromium. Перейти на него удалось примерно за шесть месяцев, тогда как над PNG команда работала значительно дольше на раннем этапе. Разработчики повторно использовали готовые механизмы связи с Chromium и графической библиотекой Skia, а также применяли существующие тесты, проверяли совместимость и испытывали декодер на реальных пользователях.

Когда декодер BMP перевели на Rust, это не только повысило безопасность, но и ускорило работу с изображениями. По данным испытаний, время, за которое декодируется BMP, в среднем сократилось на 20–50% в зависимости от платформы. Разработчики связывают прирост скорости не с самим языком, а с более простыми современными библиотеками и с тем, что отказались от устаревших участков кода.

Пока команда перерабатывала декодер, она также убрала поддержку PNG и JPEG, встроенных внутрь BMP. Chromium сохранял такой механизм ради старых принтеров Windows, которые могли самостоятельно обрабатывать вложенные изображения. Современной пользы функция почти не приносила, зато увеличивала поверхность для атак.

Rust помогает сократить и число труднообъяснимых сбоев. Ошибка памяти в декодере на C++ может повредить данные, а браузер завершит работу позже и совсем в другом месте. В результате система собирает множество разрозненных отчётов. Более строгая работа Rust с памятью блокирует значительную часть таких сценариев ещё внутри декодера.

Сейчас разработчики готовят декодеры ICO и JPEG. Позже команда планирует заняться WebP, TIFF, JPEG 2000 и SVG. Формат JPEG XL уже поддерживается с помощью кода на Rust, а GIF в Chromium обрабатывает написанный на безопасном языке декодер Wuffs.

Главным результатом проекта стало не то, что заменили отдельные компоненты, а готовая схема того, как постепенно переходить на новый код. Каждый новый декодер теперь можно подключать через общую архитектуру, проверять в испытаниях и включать в браузер после того, как оценят его скорость, стабильность и совместимость.

SecurityLab