簡體   English   中英

我應該在霍夫曼樹的DEFLATE算法中提供一致性檢查嗎?

[英]Should I provide consistency checks in the Huffman tree building algorithm for DEFLATE?

在RFC-1951中,有一種簡單的算法可從代碼長度列表中還原霍夫曼樹,方法如下:

     1)  Count the number of codes for each code length.  Let
         bl_count[N] be the number of codes of length N, N >= 1.

     2)  Find the numerical value of the smallest code for each
         code length:

            code = 0;
            bl_count[0] = 0;
            for (bits = 1; bits <= MAX_BITS; bits++) {
                code = (code + bl_count[bits-1]) << 1;
                next_code[bits] = code;
            }

     3)  Assign numerical values to all codes, using consecutive
         values for all codes of the same length with the base
         values determined at step 2. Codes that are never used
         (which have a bit length of zero) must not be assigned a
         value.

            for (n = 0;  n <= max_code; n++) {
                len = tree[n].Len;
                if (len != 0) {
                    tree[n].Code = next_code[len];
                    next_code[len]++;
                }

但是該算法中沒有任何數據一致性檢查。 另一方面,長度列表顯然是無效的。 長度值不會因為4位編碼而無效,但是例如,對於某些代碼長度,可能存在比可以編碼的更多的代碼。

提供數據驗證的最少檢查是什么? 還是由於錯過了某些原因而不需要此類檢查?

我認為檢查next_code[len]不會溢出其各自的位就足夠了。 所以在tree[n].Code = next_code[len]; ,您可以進行以下檢查:

if (tree[n].Code & ((1<<len)-1) == 0)
    print(Error)

如果tree[n].Code & ((1<<len)-1)達到0,則意味着長度為len代碼多於應有的長度,因此長度列表中有錯誤。 另一方面,如果為樹的每個符號分配了有效(唯一)代碼,則您已創建了正確的霍夫曼樹。

編輯:這只是我的曙光:您可以簡單地在第一步結束時進行相同的檢查:您只需要檢查bl_count[N] <= 2^N - SUM((2^j)*bl_count[Nj])對於所有1<=j<=N以及對於所有N >=1 (如果二叉樹在級別N-1具有bl_count[N-1]葉子,則它的2^N - 2*bl_count[N-1]不能超過2^N - 2*bl_count[N-1]離開級別N ,級別0為根。

這樣可以保證您創建的代碼是前綴代碼,但不能保證它與原始創建者的意圖相同。 例如,如果長度列表無效(仍然可以創建有效的前綴代碼),則無法證明這是霍夫曼代碼,僅僅是因為您不知道每個符號的出現頻率。

zlib檢查代碼長度列表是否完整,即是否用完了所有位模式,並且沒有溢出位模式。 一個允許的例外是當單個符號的長度為1時,在這種情況下,允許代碼不完整(位0表示該符號,未定義1位)。

這有助於zlib以更高的概率並且在流中更早地拒絕隨機,損壞或不正確編碼的數據。 這與此處的另一個答案所建議的健壯性不同,在健壯性中,您可以允許不完整的代碼,並且僅在壓縮數據中遇到未定義的代碼時才返回錯誤。

要計算完整性,請從代碼k=1的位數開始,然后從可能的代碼n=2 有兩種可能的一位編碼。 您從n減去長度為1的代碼數n -= a[k] 然后,將k遞增以查看兩位代碼,然后將n加倍。 減去兩位代碼的數量。 完成后, n應該為零。 如果在任何時候n變為負數,則可以在此處停止,因為您有一組無效的代碼長度。 如果完成后n大於零,則您的代碼不完整。

您需要確保沒有輸入會導致您的代碼執行非法或未定義的行為,例如索引數組末尾,因為此類非法輸入可能會被用來攻擊您的代碼。

我認為,您應該嘗試盡可能優雅地處理非法但不是危險的輸入,以便與其他人編寫的程序進行互操作,這些程序可能以不同於您的方式解釋規范,或者犯了一些小錯誤,只有一種合理的解釋。 這是魯棒性原則-您可以從http://en.wikipedia.org/wiki/Robustness_principle開始對此問題進行討論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM