zlib 1.4 發布 修補逾十個記憶體安全問題並帶來破壞性變更

zlib 專案於 2026 年 11 月 4 日發布 zlib 1.4,是自 2026 年 2 月 1.3.2 以來首個版本更新。這個幾乎所有作業系統與應用程式都直接或間接依賴的壓縮庫,在新版本中修補了多個緩衝區溢出、越界讀寫與未初始化記憶體問題,同時亦包含若干會影響建置與行為的破壞性變更[1][2]。

安全修補涵蓋多個核心函式

新版本處理的安全問題橫跨 gzip 檔案操作、inflate 解壓與 minizip 三個層面,當中最受注目的是非阻塞模式 gzwrite() 的緩衝區溢出,獲分配編號 CVE-2026-85091[1]。

在解壓路徑方面,inflateGetDictionary() 在特定 zlib 標頭(window size 不合法)配合 inflateReset() 或 inflateSync() 的情況下,最多可以寫入超出呼叫者 32K 緩衝區達 8MB,影響 1.3.1 與 1.3.2。inflateSync() 在 window size 尚未確定之前會配置一個只有 1 位元組的 window,之後可被越界覆寫;inflatePrime() 可能令 inflate() 讀取輸入緩衝區起始位置之前的資料;inflateBack() 未能偵測過遠的回溯距離,會把未初始化記憶體複製到輸出[1]。

壓縮路徑亦有同類問題:重複呼叫 deflatePrime() 可寫出 pending buffer 之外;gzseek() 在尚未寫入任何資料前向前 seek,會把未初始化記憶體寫入 gzip 輸出;deflateResetKeep() 在串流中途使用時會讀取 window 以外的記憶體。另外 gzdopen() 現時以正確的旗標設定 close-on-exec,避免檔案描述符意外外洩至子程序[1]。

minizip 的修正同樣值得注意。block_central_name() 有 double free;zipAlreadyThere() 在中央目錄損壞後重複呼叫會出現 NULL 解引用;解壓時不再從 extra-field 記錄以外讀取 Zip64 數值,亦只採用緊貼中央目錄結束記錄之前的那個 Zip64 locator,避免特製壓縮檔令 minizip 回報與其他工具不同的檔案清單。更嚴重的是 miniunz 以往可以建立解壓目錄以外的資料夾,在 Windows 上更可寫入任意位置,現已改為逐段處理路徑名稱[1]。

contrib/infback9 的越界指標運算獲分配 CVE-2026-4738。官方在公告中補充,該些指標在使用前已回到合法範圍,亦沒有已知編譯器會處理錯誤,因此認為 critical 評級有所誇大,但在 CHERI 這類 capability 硬體上仍可能觸發 trap[1]。

行為與 ABI 層面的破壞性變更

升級時最需要留意的是 z_off_t 在未另行決定的情況下回復為 long(與 1.3.1 相同),而非 1.3.2 的 long long。以 1.3.2 標頭建置的 Windows 應用程式需要重新編譯,否則 64 位元偏移的處理會出錯[1]。

deflateReset() 現在會重設由 deflateSetHeader() 設定的 gzip 標頭,與 zlib.h 長久以來的描述一致;依賴標頭持續存在的程式碼必須重新設定。若 raw deflate 剛好在輸出緩衝區末端完成,現時會回傳 Z_STREAM_END 而非 Z_OK。gzopen() 使用 "x" 模式時,在沒有 O_EXCL 的平台上會直接失敗,不再改為截斷既有檔案[1]。

另外,gzip 讀取遇到錯誤時,會先交付已解壓的資料,然後才回報錯誤;以往的做法是直接放棄。這項改動對依賴「一出錯就沒有輸出」的流程可能造成差異[1]。

建置系統與平台支援

CMake 最低版本要求由 3.12 提升至 3.15。MSVC 下的函式庫檔名由 z 改為 libz,即 libz.dll、libz.lib 與靜態版 libzs.lib,minizip 亦同步改名;Cygwin 上則統一加上 lib 前綴。contrib 目標與測試的名稱改為 zlib_ 前綴,ENABLE_BZIP2 選項更名為 ZLIB1_DLL_ENABLE_BZIP2。這些改動會令既有建置腳本與打包規則失效,發行版維護者需要同步更新[1]。

功能方面,Windows 上的 MSVC 或 MinGW 建置現可透過 _FILE_OFFSET_BITS=64 或 _LARGEFILE64_SOURCE 取得 64 位元偏移,函式庫本身毋須改動;Android 加入大檔案支援,AIX 有匯出清單,Win32 Makefile.msc 支援 ARM64。minizip 的傳統加密標頭亦由 rand() 改用 PCG 產生器[1]。

升級前要注意的遺留問題

官方在已知問題一節明確指出,contrib/iostream2 對不可信輸入並不安全:讀取字串時直接採用壓縮資料內儲存的長度而沒有檢查,特製檔案可以寫出目的緩衝區之外,建議改用 contrib/iostream3[1]。

對於發行版與下游專案,較穩妥的做法是先確認自身有否使用上述被改動的介面,特別是自行處理 gzip 標頭、依賴 z_off_t 大小,或直接呼叫 minizip 解壓不受信任壓縮檔的程式,再安排建置測試。由於 zlib 被大量元件靜態連結,應用程式層面亦應留意是否已重新連結至 1.4[2]。

參考資料

[1] zlib 1.4 Release Notes(2026-11-04)

[2] zlib Home Site

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*