Rust製zlib実装がIntel CPUバグを回避。C言語なら黙って壊れていた
zlibのRust実装「zlib-rs」の最新版0.6.4が6月21日にリリースされた。AArch64のチェックサム修正やAVX-512の最適化も含まれる。だが今回の本題は別にある。Intel Raptor Lake世代のCPUバグに対する回避策だ。
Raptor Lakeが引き起こしたクラッシュ
zlib-rsは、Trifecta Tech Foundation(オランダ)が開発するRust製のzlib互換実装で、ISRGのProssimoプロジェクトが初期の開発を支援した。2024年4月の初版から採用が広がり、2026年5月にリリースされたFirefox 151.0.0でgzip圧縮・展開のデフォルトバックエンドに採用されている。
問題が起きたのは、Firefoxがzlib-rsを統合した直後だった。Nightly版でクラッシュレポートが上がり始め、ログには「論理的にありえない境界チェックの失敗」が残っていた。開発者はローカルでは再現できず、レポートが積み重なるにつれてパターンが見えてきた。クラッシュの報告元が、Intel第13・14世代Core(Raptor Lake)に集中している。
zlib-rsの開発を率いるフォルケルト・デ・フリース(Folkert de Vries)氏は、Trifecta Tech Foundationのブログでこう振り返っている。「自分たちの実装がこの悪名高いRaptor Lake CPUバグを踏んでいた」。だが何がバグを引いているのか、どう追い詰めればいいのか、手がかりがなかった。
1バイトの書き込みが化ける
転機は、RAD Game Toolsのファビアン・ギーゼン(Fabian Giesen)氏が公開したブログ記事だった。同氏はゲーム向け圧縮ライブラリOodleで同じCPUバグに直面し、問題の正体を特定していた。ハフマン符号化の結果をメモリに書き込む際に使われる、特定のMOVB命令がバグの引き金になる。
RCXレジスタのビット8〜15(ch)をメモリに書き込む命令が、Raptor Lakeでは稀にビット0〜7を書き込んでしまう。ハードウェアレベルの不具合で、ソフトウェアから見れば1バイトの値が無言で化ける。zlibもハフマン符号化を使う。zlib-rsがまさにこの命令を生成していた。
ここでRustの特性が効いた。C言語のzlibなら、壊れたデータはそのまま処理されていただろう。検出できるのは、展開後のデータが運良くチェックサム不一致を起こした場合だけだ。zlib-rsでは、Rustの境界チェックが不正な値を即座に捕まえ、クラッシュとして表面化させた。デ・フリース氏もブログで「C言語なら黙ってデータが壊れるだけだった。境界チェックの失敗として表面化したのは幸運だった」と書いている。
修正は、コンパイラ(LLVM)が問題の命令を生成しないよう、メモリ書き込みの方法を変えるワークアラウンドだ。FirefoxではMozillaのマイク・オメ(Mike Hommey)氏がパッチを実装し、zlib-rs本体にもアップストリームされた。LLVM 23ではこの命令自体が生成されなくなるというが、開発者によれば偶然の副産物であり意図的な修正ではない。zlib-rsは当面このワークアラウンドを維持する。
0.6.4のその他の変更
Raptor Lake対応以外にも、0.6.4には実質的な修正と最適化が含まれる。
AArch64のAdler32修正では、NEONコードパスでpair変数の剰余演算がテール処理後に抜けていた問題を直している。整数オーバーフローにより、特定の入力でチェックサムが不正になっていた。x86_64のAVX2/AVX-512実装やスカラー実装には影響しない。
AVX-512のVNNI最適化では、命令レベル並列性(ILP)を活かすトリックを標準AVX-512に適用した。少なくともAMD Zen 5では、Adler32チェックサムの計算でわずかな性能向上が確認されている。
LoongArch64向けCRC32実装が新たに追加された。LoongArchは中国Loongsonが開発するCPUアーキテクチャで、独自のCRC32命令を持つ。
「Cより速い」先の現実
zlib-rsは2025年2月の0.4.2リリース時点で、展開速度でC実装のzlib-ngやChromium版zlibを上回ったと発表している。開発元のベンチマークでは、x86_64 Linuxの展開でzlib-ngを6〜10%以上上回る結果が出ており、CPython経由でストックzlibと比較した別のテストでは最大32倍の速度差が記録されている。
だがRaptor Lakeの一件は、性能とメモリ安全性だけでは語れない現実を突きつけた。ハードウェアバグはソフトウェア側の正しさとは無関係に発生し、デバッガも再現手順も効かない。zlib-rsのチームは数か月間、何をすべきかわからないまま過ごしたと明かしている。
Rustの境界チェックがなければ、このバグはデータ破損として静かに広がっていた可能性が高い。「安全」とは、バグを防ぐことだけではない。バグが起きたとき、それを見えるようにすることでもある。
参照元
他参照
関連記事
- Firefox 151.0.1がRaptor Lakeクラッシュを修正、調査開始から1年
- Linux 7.0リリース——Rust正式採用、AIが新常態へ
- RustとAIで1からX11サーバーを書き直す。yserverが問いかけるもの
- Firefox 150.0.1配信、Relay無料枠が10倍に
- Ubuntu 26.04、完全Rust化先送り44件のCVE
- Firefox 150配信、分割ビューとPDF編集が本格化
- Redox OSがLLM生成コードを全面拒否、議論の余地なし
- トーバルズ、Linux 7.0来週リリースへ rc7で最終確認
- Linuxカーネルからstrncpyが消えた。6年362コミットの結末
- Flatpak次世代はsystemd依存へ。怒りが消した妥協