我承认这是一个复杂的例子,但我喜欢用 TikZ 和 LaTeX 绘画,这个特殊的问题不止一次出现在我身上。
最小工作示例需要几个文件,但简而言之 - 每次编译时都会生成一个 PDF,其中包含当前文件大小在其中。在包含一定数量的图像后,一些查看器 ( evince
、okular
、acroread*
) 无法显示深度嵌套的图像,而其他查看器则出现段错误 ( xpdf
),只有一个 ( gs
) 可以正确显示完整图像。
*请注意,acroread
下面的示例不会失败,但如果您继续加快迭代速度,则会失败。
第一个文本文件
\documentclass{standalone}\begin{document}start\end{document}
下一个.tex
\documentclass{standalone}
\usepackage{graphicx}
\IfFileExists{\jobname.pdf}
{\edef\Size{\pdffilesize{\jobname.pdf}}}
{\def\Size{0}}
\renewcommand{\arraystretch}{0}
\setlength\fboxsep{1pt}
\newcommand{\X}{\includegraphics{first.pdf}}
\begin{document}%
\begin{tabular}{@{}l@{}}%
\framebox{\Size} \\ \X
\end{tabular}
\end{document}
Makefile
all:
make first
make block
make block
make block
evince next.pdf
gs next.pdf
first:
pdflatex first.tex
next:
pdflatex next.tex
cp next.pdf first.pdf
block:
make next
make next
make next
make next
make next
make next
make next
make next
make next
make next
示例 ( gs
vs evince
)
问题:
为什么查看器无法显示深层嵌套的图像?
通过运行,
pdf2ps -> ps2pdf
问题已修复,但是否存在更复杂的图像被破坏的风险(即使用 TikZ 或带有 ConTeX 的字体)?
答案1
evince、okular 和 xpdf 的 pdf 解析功能具有共同的传统(evince 基于 poppler,而 poppler 基于 xpdf;okular 基于 kpdf,而 kpdf 基于 xpdf),它们都明确限制了表单递归深度,以避免在损坏的 pdf 上出现无限递归,这些 pdf 的表单包含自身(可能通过复杂的路径)。这也可能是恶意构造的 pdf 发起的 DoS 攻击。这里是 poppler 的一个最新补丁,用于将递归深度从 20 增加到 100,但您安装的 evince 可能使用了较旧的限制 20。
PDF 规范 PDF 32000-1:2008 似乎没有明确限制表单 XObjects 允许的递归级别,但第 8.10.1 节确实说
当
Do
运算符应用于表单 XObject 时,符合要求的读取器应执行以下任务:
a) 保存当前图形状态,如同通过调用运算q
符(参见 8.4.4,“图形状态运算符”)
[....]
e) 恢复已保存的图形状态,如同通过调用运算Q
符(参见 8.4.4,“图形状态运算符”)
q
并且在附录 C.2 表 C.1 中,它给出了/嵌套深度的限制Q
为 28 级,这是基于这些运算符在将 PDF 转换为 PostScript 时映射到 PostScriptgsave
和grestore
运算符的事实(PostScript 规范第 3 版的表 B.1 给出了最大 gsave
级别为 31,并且可能其中有几个用于其他目的,剩下 28 个用于 PDF q
/Q
和表单 XObjects)。