Преобразование проблем переполнения стека с помощью пользовательского xslt - PullRequest
3 голосов
/ 01 июня 2010

У меня есть система, которая позволяет пользователю предоставлять собственный XSLT для применения к некоторым данным, которые были извлечены, чтобы указать, как эти данные должны быть представлены. Однако, если пользователь включает код в XSLT, эквивалентный:

<xsl:template match="/">
  <xsl:element name="data">
    <xsl:apply-templates select="." />
  </xsl:element>
</xsl:template>

это приводит к тому, что .NET бесконечно рекурсивно пытается обработать его, и выдает ошибку переполнения стека. Я должен быть в состоянии перехватить это до того, как приложение выйдет из строя, поскольку извлекаемые данные иногда занимают довольно много времени, и при этом данные теряются.

Есть ли способ сделать это? Я знаю, что теоретически возможно идентифицировать любые вхождения xsl: apply-templates с помощью "." в атрибуте select, но это не единственный способ бесконечной рекурсии, мне нужен способ ее общего перехвата.

Ответы [ 3 ]

4 голосов
/ 01 июня 2010

Вы говорите о проблеме остановки . Это неразрешимо: невозможно создать алгоритм, который может определить, будет ли какая-либо программа (или, в вашем случае, любой сценарий XSLT) останавливать или продолжать обработку на неопределенный срок для ее возможных входных данных.

Лучше всего установить ограничения по времени и / или памяти для выполнения пользовательских сценариев XSLT. Вот как браузеры обычно обрабатывают неуправляемый JavaScript, например.

Недостатком является то, что вы время от времени определяете, что некоторые законные сценарии занимают слишком много времени и / или памяти, поэтому вам придется тщательно настраивать свои ограничения.

2 голосов
/ 01 июня 2010

Мы «решили» эту проблему, создав отдельный веб-сервис, который обрабатывает преобразования XSLT. (использовал Saxon для преобразования, потому что он тоже знает XSLT 2). В случае сбоя XSLT-скрипта он будет вредить только службе xslt-tranformer (и если проблема действительно серьезная, она все равно будет перезапущена с использованием IIS / mod_mono). А поскольку эта служба работает в отдельной контролируемой среде, это также позволило устранить некоторые риски безопасности, которые могут возникнуть при использовании пользовательских XSLT.

0 голосов
/ 01 июня 2010

Как правильно заметил @welbog, проблема остановки неразрешима!

Одна практическая мера - дать каждому преобразованию длительность "время жизни" и рассматривать любое преобразование, которое превышает эту продолжительность, как "чрезмерно повторяющееся" Затем выполните действие (например, убейте его).

Это не должно быть сложно реализовать на платформе централизованного хостинга.

...