有效 LZMA stream 的最小 initial Code 值是多少?
结论
有效 LZMA stream 的 initial Code 最小值可以是 0。由此可知:
- 存在
Code <= 0xffff的有效 stream。 - 以 3 个 NUL bytes 开头的数据也可能是有效的 LZMA stream。
- autodetect 逻辑不能仅凭前三个 bytes 是
00 00 00就排除 LZMA。
这里所说的“有效”,是指在给定正确 LZMA properties 的情况下,range decoder 能完成解码并读到 end-of-stream marker。数据无须由特定编码器以某种规范化形式生成。
initial Code 为什么不会一直很小
LZMA range decoder 的核心判断可以简化为:
bound = (range >> 11) * probability;
if (code < bound) {
bit = 0;
range = bound;
} else {
bit = 1;
code -= bound;
range -= bound;
}
当 range 太小时,需要执行 normalization:
range <<= 8;
code = (code << 8) | next_byte;
所有运算均按 32-bit unsigned integer 处理。
initial Code 只包含编码数据最前面的 32 bits,并不会限制后续进入 Code 的内容。即使初始值是 0,normalization 仍会不断从 stream 中读取新的 byte。经过若干次左移,后续 byte 可以进入 Code 的高位,使 code >= bound,此后 range decoder 就能返回 1 bit。
所以下面的推断不成立:
initial Code 很小
=> Code 永远很小
=> decoder 永远只能读出 0 bit
initial Code 只决定解码开始时的状态,并非整个 stream 中 Code 的上界。
initial Code 为什么可以等于 0
可以先编码一段足够长的全零决策,例如多个值为零的 literals:
literal 0x00
literal 0x00
literal 0x00
...
end-of-stream marker
每个 0x00 literal 的 8 个 literal bits 都是 0,前面的 IsMatch bit 也可以是 0。连续的零决策会反复选择当前 range 的低区间。这个区间的下界始终为零,宽度则不断缩小。
等到该区间完全落入 initial 32-bit prefix 为零的范围,再编码 end-of-stream marker。即使 end marker 包含非零决策,最终选中的子区间仍在这个很小的低区间内,因此可以选到前 32 bits 全为零的 code point:
00 00 00 00 00
│ └─────────┘
│ Code = 0
└─ range coder 要求的首个 0 byte
这种 stream 通常需要刻意编码一段较长且效率较低的 literal 序列。只包含 end-of-stream marker 的最短 stream 未必能得到相同的 initial Code,但所有有效 stream 中的最小值仍然是 0。
以 3 个 NUL bytes 开头的有效示例
下面是一个 raw LZMA1 stream:
00 00 00 2e 09 60 89 ff ec 32 80 00
它使用以下外部 properties:
lc = 0
lp = 0
pb = 0
dict_size = 4096
前 5 bytes 是 range decoder 的初始化数据:
00 00 00 2e 09
对应的 initial Code 为:
initial Code = 0x00002e09 = 11785
11785 < 65536,并且整个 stream 的前三个 bytes 都是 NUL。
可以用 Python 验证:
import lzma
raw = bytes.fromhex(
"00 00 00 2e 09 60 89 ff ec 32 80 00"
)
filters = [{
"id": lzma.FILTER_LZMA1,
"dict_size": 4096,
"lc": 0,
"lp": 0,
"pb": 0,
}]
initial_code = int.from_bytes(raw[1:5], "big")
output = lzma.decompress(
raw,
format=lzma.FORMAT_RAW,
filters=filters,
)
assert raw[:3] == b"\x00\x00\x00"
assert initial_code == 0x00002E09
assert initial_code <= 0xFFFF
assert output == b"\x00\x00"
print(initial_code) # 11785
print(output.hex()) # 0000
这个例子足以证明,以 3 个 NUL bytes 开头的数据也可能是 LZMA,无须依赖 initial Code == 0 的极端构造。
autodetect 时的注意事项
Raw LZMA stream 本身不包含完整的 lc、lp、pb 和 dictionary size 信息,decoder 必须从外部获得这些参数。同一组 bytes 在不同参数下也可能产生不同的结果。
如果 autodetect 只检查:
if (data[0] == 0 && data[1] == 0 && data[2] == 0) {
/* assume not LZMA */
}
它就会拒绝实际存在的有效 LZMA stream。前三个 NUL bytes 可以作为启发式特征,但不能作为可靠的排除条件。
备注:内容仅供参考。
