#1349·leveldb

ReadBlock 在验证之前分配由攻击者控制的 snappy/zstd 未压缩长度

作者: h-t-m创建于 2026年8月19日更新于 2026年8月19日

ReadBlock的解压分支中(HEAD 7ee830d 的 table/format.cc 中):

cpp
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()` 触发块加载