ReadBlock 在验证之前分配由攻击者控制的 snappy/zstd 未压缩长度
作者: h-t-m创建于 2026年8月19日更新于 2026年8月19日
在ReadBlock的解压分支中(HEAD 7ee830d 的 table/format.cc 中):
case kSnappyCompression: {
size_t ulength = 0;
if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { ... }
char* ubuf = new char[ulength];
if (!port::Snappy_Uncompress(data, n, ubuf)) { ... }
}
`Snappy_GetUncompressedLength` 仅解析块的前缀 varint,并接受最多 ~4 GiB 的值;`new char[ulength]` 在任何解压验证之前执行。`kZstdCompression` 分支具有相同的模式(`Zstd_GetUncompressedLength` 后跟`new char[ulength]`)。
**重现** (90 字节的手工 SSTable,不需要进行漏洞扫描):
- 数据块的全部内容是 5 个 snappy 头部字节 `FE FF FF FF 0F`(声明为未压缩长度 4294967294),尾部类型为 `kSnappyCompression`;索引块中有一个指向该数据块的单个条目;标准尾部具有魔法数字
- `Table::Open` 成功;`NewIterator()` + `SeekToFirst()` 触发块加载内容来源: google/leveldb