BabelDOC 发布了新版本,将 PDF 处理流程迁移至 Rust,并为读取文档时的资源使用设置默认上限。翻译外部 PDF 的服务可借此降低小型恶意文件大量占用内存、导致任务停止的风险。

1. 将 PDF 读取与重写流程迁移至 Rust

本版本不仅在 Rust 中执行 PDF 解析,还涵盖扫描文档识别、图文布局、段落与样式处理、翻译协调、将页面元素安排为印刷形式的排版,以及 PDF 写入。布局模型、用于确定文档元素位置的模型及翻译服务集成仍保留在 Python 中,Python 也继续作为使用入口。

据项目公告,PDF 读取速度较 0.6.4 更快,内存用量也有所降低。目标是让默认处理路径的文档输出与旧版本保持一致,预期变化则是水印调整和新增资源上限。

2. 阻断小型输入耗尽内存的路径

0.7.0 默认启用资源上限,以防读取输入 PDF 时资源用量过度增长。超限时会停止处理,并抛出包含被触发限制的名称、数值及发生位置的异常。可以一次性关闭所有限制,但此时会记录警告。

第一份安全公告涉及解压 PDF 数据时未限制输出大小、从而耗尽内存的问题。这就像打开压缩包后,小包裹膨胀成了巨大的货物。

根据公告中的复现记录,Python 3.11 精简容器内的 BabelDOC 0.6.4 将 1,043,644 字节解压为 1,073,741,824 字节。解压耗时 2.70 秒,进程峰值内存从 1,068,544KiB 增至 2,116,024KiB。

复现的部分核心代码如下。

stream = PDFStream(attrs={"Filter": LIT("FlateDecode")}, rawdata=payload)

mem_before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
print(f"\nProcess RSS before decode(): {mem_before} KiB")

start = time.time()
stream.decode()  # <-- the real, unmodified vulnerable call: zlib.decompress(data), no max size
elapsed = time.time() - start

第二份公告涉及将字体字符代码映射到实际字符的 ToUnicode 映射问题。逐一展开并存储字符代码范围会消耗资源。在 BabelDOC 0.6.4 中,将相同输入传给原有 Python 解析器及后续 Python 解析器的复现记录如下。

表:ToUnicode 范围展开复现结果

条件:BabelDOC 0.6.4,Docker 内的 Python,断网,直接以输入字节调用解析器(2026年10月16日运行结果)

单位:时间为秒,条目数为个

阻断小型输入耗尽内存的路径
解析器·范围终值时间条目数
原有 Python 解析器·000000FF0.0004—
原有 Python 解析器·000FFFFF0.41—
原有 Python 解析器·00FFFFFF6.72—
后续 Python 解析器·000000FF0.0256
后续 Python 解析器·000FFFFF0.541048576
后续 Python 解析器·00FFFFFF18.4416777216

表中范围均从 00000000 开始。在同一解析器中扩大范围后,处理时间随之增加。另一次在 1GiB 内存限制下展开 00000000~FFFFFFFF 范围的测试以退出码 137 被强制终止。新 Rust 解析器以区间而非单个条目存储范围,并对保留的映射数据施加默认上限。

3. 安全改进的代价是超限文档处理失败

两份公告均将受影响版本标为 0.6.4 及以下,修复包含在 0.7.0 中。此次于 2026年11月7日发布的版本,以 Rust 实现替换了会引发资源放大、即输入处理过程中资源用量大幅增长的 Python 解析器实现。维护者表示,安全修复仅提供给最新版本,不会正式向旧版本回移修复,即将修复应用到旧版本。

资源上限降低了恶意输入过度占用内存的风险,但即使是正常文档,超限也会被拒绝翻译。服务运营者需要准备向用户说明失败原因的流程。对于必须处理的文档,项目介绍了关闭上限并施加外部限制的方法。

复现数值来自直接调用解析器,并非完整翻译流程或新 Rust 实现的性能测量结果。维护者建议,在处理不可信 PDF 时,同时为翻译进程设置时间限制和容器内存限制。

4. 使用预构建包,并用自有文档核验结果

预构建包是预先构建、可直接安装的软件包,面向 Linux x86-64、ARM64,Windows x86-64,以及 Mac Intel、Apple Silicon 五个平台提供。支持的 Python 版本为 3.10~3.13。在其他平台安装源码发行包,即包含源代码和构建配置的分发文件,或从仓库直接构建时,需要 Rust 工具链,也就是编译和构建所需的工具集合。

公开入口保持不变,但直接导入已删除内部 Python 模块的外部代码需要修改。维护者建议,在升级生产环境前,先用自有文档核验结果。

不再添加首页水印。相关设置仍被接受,但只会改变输出文件的名称和数量,因此核验结果时也需留意这一变化。

0.7.0 限制了 PDF 解析器中危险的资源放大路径,但也可能导致部分文档处理失败,因此升级的关键是事先准备好如何在运营中应对超限任务。