Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

zlib循環到eof還不停?分辨未處理輸入與下一個gzip成員

28項本機檢查分辨結束後的尾部重放、只讀首個成員,以及第二成員已輸出全部明文卻仍未完整結束的情況。

原創示意圖:結束後保留尾部重放三次,輸出不變而unused_data增長。
原創示意圖:實測CPython 3.12.14/zlib 1.3.2;三次明確有界呼叫,未執行無限循環。 Watch at Ease

解壓物件eof=True時,gzip輸入仍可能含另一成員。我們安裝的CPython 3.12.14在eof之後還可能保留unconsumed_tail;將它反覆交給同一個已結束物件,會讓unused_data不斷追加尾部位元組,卻沒有新輸出。

這是兩種不同故障:循環在一個成員結束後繼續,或過早停止而漏掉後續成員。28項小型對照還發現更隱蔽的邊界:第二成員被截斷時,兩成員合計仍輸出全部9個預期明文位元組,但第二物件eof保持False。

1. 記錄解壓狀態,不只看輸出長度

記錄sys.version、zlib.ZLIB_VERSION、zlib.ZLIB_RUNTIME_VERSION、wbits,以及應用允許單成員或多成員的規則。本次實測CPython 3.12.14/Linux,建置及執行時zlib皆1.3.2。查閱的C函式庫上游手冊標為1.3.1,是參考版本,不是實際執行版本。

每次小型診斷呼叫記錄輸出長度、eof及unconsumed_tail、unused_data長度。eof之前,max_length限制輸出時可能需要再次處理未消耗輸入。到達eof後要依格式規則解釋尾部,不能將兩個屬性不加區分地交回同一物件。

2. 停止重放已結束的物件

zlib封裝的測試資料含1024個明文位元組與五位元組後綴extra。每次最多輸出100位元組,僅在not d.eof and d.unconsumed_tail時繼續,取得準確完整負載。本次安裝版本結束時,兩個尾部屬性都含extra,不能視為兩段獨立資料拼接。

接著明確只多呼叫三次,每次輸入保留尾部。輸出皆為零,unused_data由5增至20位元組,unconsumed_tail仍為5;未執行無限循環。上游問題已提供eof保護條件,且已關閉並連結修復。請測自己的執行版,不能說成所有目前Python版本尚未修復的新缺陷。

3. gzip成員結束只是交接點

49位元組gzip測試資料由25位元組alpha成員與24位元組beta成員拼接。一個zlib.decompressobj(31)只回傳alpha,eof=True,unused_data保留完整24位元組第二成員。此次未限制輸出的呼叫中,unconsumed_tail為空。

把unused_data交給新物件會得到beta,隨後eof=True且無後綴。gzip.decompress對完整小型資料直接回傳alphabeta,符合文件多成員行為。這些API與社群新物件方法不是新發現。大型或外部輸入應選擇符合規則與限制、持續維護的讀取器,不將這個記憶體測試當正式接入設計。

4. 空輸出與預期明文都不是完成證明

有效空gzip成員沒有明文輸出,仍會到達eof並保留下一成員。把空輸出區塊當作全部輸入結束的循環,可能漏掉後續有效資料。應追蹤成員完成與待處理輸入,不只看最新輸出是否非空。

從第二成員尾部移除四位元組後,兩物件仍輸出alphabeta,全部9個預期位元組出現,但第二物件eof=False。flush()也未建立缺失尾部的完成狀態。另一對照改壞第二成員CRC,首物件仍回傳alpha;直到第二物件處理該成員才出錯。

5. 明確允許哪些成員與尾部資料

協定可只允許一個完整成員並拒絕額外位元組,也可允許拼接成員並為每個建立新解碼物件。不能悄悄丟棄unused_data、假定任何後綴都是有效新成員,或把它與可能重疊的unconsumed_tail相加。我們的garbage後綴當作新gzip成員處理時失敗。

多成員輸出預算須累計,另依實際讀取器控制輸入、成員數、時間及上游緩衝。max_length限制單次呼叫,零表示不限制;flush(length)指定初始緩衝大小,不是上限。實驗中max_length=0輸出1024位元組,max_length=1輸出一位元組。未測量程序記憶體、CPU限制或網路用戶端。

6. 只提交完成檢查支持的結果

診斷迴歸測試使用小型已知資料:單一有效成員、兩個有效成員、空首成員、截斷第二成員尾部、錯誤第二成員CRC及非成員後綴。核對準確輸出、各獲准成員完成狀態及最終尾部規則;保留失敗,不能把有用前綴當完整結果發布。

全部28項斷言在所述版本通過,報告保留版本、平台、指令碼SHA與實際狀態。未實作通用串流讀取器、執行發布修復版本,或證明HTTP完整性、來源真實性與資源使用安全。正確成員交接是必要條件,應用仍須定義整個允許輸入何時算完成。

原創示意圖:首成員、有效第二成員與截斷第二成員的輸出及eof對照。
原創示意圖:輸出alphabeta不一定證明第二成員尾部驗證完整;須另查逐成員完成狀態。 Watch at Ease