我遇到了 pdfTex 挂起问题,正在寻找解决方法(如果存在)。例如,我知道以下公式表达式输入错误,但我不知道为什么 pdfTex 被冻结(可能是无限循环)而不是很好地运行?有解决方法吗?因为如果输入错误,我不想重新启动服务器。
编辑:正如评论所建议的那样,问题已经澄清。
\documentclass{article}
\usepackage{graphicx}
\usepackage{draftwatermark}
\usepackage{breqn}
\usepackage{amsmath}
\SetWatermarkText{FAST MATH}
\SetWatermarkScale{2}
\SetWatermarkVerCenter{0.6\paperheight}
\SetWatermarkAngle{30}
\begin{document}
\section{Input}
$\left. \begin{array} { l } { a ) A = \{ 2 $
\section{Solution}
${a: 0}$
\end{document}
答案1
如果您使用-halt-on-error
命令行选项运行 pdflatex,则不会在出错时进入调试器。这对于 LaTeX 的“批处理模式”使用通常更为方便。
答案2
可以使用较小的示例重现该问题,表明它与已加载的包无关:
\documentclass{article}
\begin{document}
$\left. \begin{array} { l } { a ) A = \{ 2 $
\section{Solution}
${a: 0}$
\end{document}
数学公式中的错误,以及随后的章节标题,导致 TeX 进入无限循环,由
! LaTeX Error: \begin{array} on input line 7 ended by \end{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.12 \end{document}
?
! Improper \prevdepth.
\newpage ...everypar {}\fi \par \ifdim \prevdepth
>\z@ \vskip -\ifdim \prevd...
l.12 \end{document}
缺失的\end{array}
原因\par
仍然被定义为“不执行任何操作”,就像在 中一样array
。由于此处的错误恢复是尝试执行\end{document}
,因此 LaTeX 尝试完成页面发布\par
,但什么也不做。
如果我们\tracingmacros=1
在程序中断后的日志文件中看到最后一个错误消息后添加一串
\par ->
\par ->
\par ->
\par ->
\par ->
解决方法:不要在输入时犯愚蠢的错误。
另一个解决方案是pdflatex
使用选项运行-halt-on-error
,它会在第一次出现错误时停止它。
但是,这并非万无一失。如果用户\def\foo{\foo}
在序言中,那么\foo
在文档中第一次使用将启动一个无限循环,其中不错误。
答案3
这是对在包含您无法控制的用户提供的代码的文档上作为子进程运行 TeX 的实际问题的答案(而不是关注您提供的特定示例)。
正如其他人已经提到的,在 TeX 中触发无限循环很容易,而且不会产生任何错误。您的示例显示了一个合理的用户错误(忘记了环境的结束),但您还需要防止恶意用户故意触发无限循环。
当你有一个应用程序或脚本生成一个可能无限期运行的子进程时,最好包含超时。由于你使用的是 Python,你可能会找到以下问题的答案使用带有超时的模块“子进程”有用。
但是,你还需要考虑其他类型的恶意代码。2010 年,TeX Live 和 MikTeX 都进行了一些重大改进以提高安全性,但最近也有一些修复,例如:
因此请确保您拥有最新的 TeX 发行版。
TeX Live 的安全设置位于texmf.cnf
配置文件中。默认情况下有两个这样的文件,可以使用 找到它们的位置kpsewhich -a texmf.cnf
。一个包含不应修改的默认设置。另一个可用于在需要时覆盖特定设置。
MikTeX 的安全设置位于miktex.ini
文件。
主要需要关注的是 shell 转义 ( \write18
)。有三种模式:
- 已禁用(
shell_escape=f
在texmf.cnf
文件中或-no-shell-escape
在运行 TeX 时使用)。这将阻止 TeX 调用任何系统命令。这是最安全的模式。 - 受限制(
shell_escape=p
在文件中texmf.cnf
)。这对 施加了以下限制\write18
:- 禁止使用某些字符(例如
'
和;
),以防止注入。 - 仅可运行受信任列表中的应用程序。这些应用程序在文件中的设置中标识。
shell_escape_commands
您可以texmf.cnf
使用列出它们,目前kpsewhich -var-value=shell_escape_commands
有八个:bibtex
,,,,,,,,bibtex8
。这些已经由 TeX Live 安全团队评估并确定是安全的。(但是,仍然有可能滥用此设置并产生破坏性影响,正如我最近在英国 TUG 会议上所展示的那样。)extractbb
gregorio
kpsewhich
makeindex
repstopdf
texosquery-jre8
- 禁止使用某些字符(例如
- 不受限制(
shell_escape=t
在texmf.cnf
文件中或-shell-escape
运行 TeX 时使用)。这允许调用任何系统命令,因此不安全。
另一个值得关注的领域是文件 I/O 操作,这些操作对于常见的文档构建要求(例如生成目录、交叉引用和索引)至关重要,但可能会被滥用。除了操作系统的本机文件权限外,TeX 还具有确定是否允许读取或写入访问的设置。
该texmf.cnf
文件有两个设置openin_any
,openout_any
可采用以下值之一:
a
:任何允许的文件(如果操作系统允许);r
:(受限)不允许隐藏点文件;p
:(偏执)不允许隐藏点文件,并且不允许进入父目录(..
)并限制绝对路径在下$TEXMFOUTPUT
。
默认值为:
openin_any = a
openout_any = p
偏执的设置可以防止在当前工作路径(调用 TeX 的目录)之外访问文件。
例如,假设您在 Web 服务器上运行 TeX,并且假设该服务器上您的主目录是/home/foo
,而您的网站的根目录是/home/foo/public_html
(因此,例如,如果您的网站是www.example.com
,则www.example.com/index.php
对应于文件/home/foo/public_html/index.php
)。
如果您从主目录 ( /home/foo
) 运行 TeX,那么即使使用偏执设置,添加到文档中的恶意代码也会被覆盖public_html/index.php
(如果文档未受到文件系统的保护)。您的网站主页现已损坏。
通过文件读取操作,如果用户可以看到生成的 PDF,他们可以使用恶意 TeX 代码从您的系统中获取信息。假设您有一个/home/foo/public_html/foobar.php
访问数据库的脚本。这可以逐字输入到文档中,现在可以从 PDF 中读取数据库连接信息(包括密码)。
TeX 代码可以被混淆,所以不要依赖使用正则表达式来检查用户提供的代码中的某些命令。
概括:
- 确保您拥有最新的 TeX 安装。
- 调用 TeX 并设置超时时间,如果超时时间过长,将自动终止该进程。
- 使用 运行 TeX
-no-shell-escape
。 - 在没有任何指向重要文件的子目录的安全目录中运行 TeX。
- 确保
openout_any
和都openin_any
设置为p
。 - 如果您需要查看生成的 PDF,请确保您的 PDF 查看器已禁用 JavaScript。
答案4
您的环境/括号不平衡;\begin{array}
没有\end{array}
和\left.
没有\right..
。此外,breqn
在之后加载amsmath
并添加lmodern
以防止缺少字体大小替换。
\documentclass{article}
\usepackage{graphicx,lmodern}
\usepackage{draftwatermark}
\usepackage{amsmath}
\usepackage{breqn}
\SetWatermarkText{FAST MATH}
\SetWatermarkScale{2}
\SetWatermarkVerCenter{0.6\paperheight}
\SetWatermarkAngle{30}
\begin{document}
\section{Input}
$ \begin{array} { l } a) A = \{ 2 \end{array}$
\section{Solution}
${a: 0}$
\end{document}