我有一个系统允许用户选择提供自己的XSLT来应用一些已检索的数据,作为指定数据应该如何呈现的方法。但是,如果用户在XSLT中包含的代码相当于:
<xsl:template match="/">
<xsl:element name="data">
<xsl:apply-templates select="." />
</xsl:element>
</xsl:template>
这会导致.NET无限递送尝试处理它,并产生堆栈溢出错误。我需要能够在崩溃应用程序之前捕获它,因为获取的数据有时非常耗时,并且在发生这种情况时数据会丢失。
有没有办法做到这一点?我知道理论上可以用“。”来识别xsl:apply-templates的任何出现。在select属性中,但这不是无限递归发生的唯一方法,我需要一种通常捕获它的方法。
答案 0 :(得分:4)
你在谈论halting problem。它是不可判定的:无法创建一个算法来确定任何程序(或者,在您的情况下,任何XSLT脚本)是否会因其可能的输入而无限期地停止或继续处理。
最好的办法是对用户提供的XSLT脚本的执行施加时间和/或内存限制。例如,浏览器通常会处理失控的JavaScript。
缺点是您偶尔会确定某些合法脚本占用了太多时间和/或内存,因此您必须仔细调整限制。
答案 1 :(得分:2)
我们通过创建一个处理XSLT转换的单独Web服务来“解决”这个问题。 (使用Saxon进行转换,因为它也知道XSLT 2)。如果XSLT脚本崩溃,它只会对xslt-tranformer服务造成损害(如果问题非常严重,无论如何都将使用IIS / mod_mono重新启动)。而且由于该服务在一个单独的受控环境中运行,这也解决了用户制作的XSLT可能带来的一些安全风险。
答案 2 :(得分:0)
正如@welbog
正确注意到,暂停问题是不可判定的!
一个实际的措施是为每个转换提供一个“生存时间”持续时间,并将超过此持续时间的任何转换视为“过度循环”。然后采取行动(例如杀死它)。
在集中式托管平台上实现这一点并不困难。