Обходное исключение StackOverflowException

html-agility-pack stack-overflow

Вопрос

Я использую HtmlAgilityPack для анализа примерно 200 000 документов HTML.

Я не могу предсказать содержимое этих документов, однако один такой документ заставляет мое приложение терпеть неудачу с помощью StackOverflowException . Документ содержит этот HTML-код:

<ol>
    <li><li><li><li><li><li>...
</ol>

Есть примерно 10 000 <li> элементов, вложенных таким образом. Из-за того, как HtmlAgilityPack анализирует HTML, он вызывает исключение StackOverflowException .

К сожалению, StackOverflowException не уловимо в .NET 2.0 и более поздних версиях.

Я действительно задавался вопросом о том, как установить большой размер для стека потока, но установка большего размера стека - это взломать: это заставит мою программу использовать намного больше памяти (моя программа запускает около 50 потоков для обработки HTML, поэтому все эти потоки будет иметь увеличенный размер стека) и потребуется ручная корректировка, если она снова столкнется с подобной ситуацией.

Есть ли какие-нибудь другие способы обхода?

Принятый ответ

В идеале, долгосрочное решение заключается в том, чтобы патч HtmlAgilityPack использовать кучу-стек вместо стека вызовов, но это было бы слишком большим для меня событием. Я временно потерял данные учетной записи CodePlex, но когда я верну их, я отправлю отчет о проблеме по этой проблеме. Я также отмечаю, что эта проблема может представлять уязвимость атаки «отказ в обслуживании» на любом сайте, который использует HtmlAgilityPack для дезинфекции отправленного пользователем HTML - обработанный чрезмерно вложенный HTML-документ приведет к смерти процесса w3wp.exe.

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

Я сделал копию страницы <ol><li> и провел несколько экспериментов. Я обнаружил, что моя программа завершилась неудачно, когда размер стека был меньше 2^21 байта, но максимальный размер 2^22 преуспел - это 4 МБ, и в моей книге прошло как «приемлемый» взлом ... пока.


Популярные ответы

Я просто исправил ошибку, которая, как я считаю, такая же, как и описание. Загрузили патч на сайт проекта hap ...

http://www.codeplex.com/site/users/view/sjdirect (см. патч 3/8/2012)

Или посмотрите дополнительную документацию по проблеме и результат здесь ....

https://code.google.com/p/abot/issues/detail?id=77

Фактическое исправление было ... Добавлен HtmlDocument.OptionMaxNestedChildNodes, который можно настроить для предотвращения StackOverflowExceptions, вызванных множеством вложенных тегов. Он выкинет ApplicationException с сообщением «Документ имеет более X вложенных тегов. Вероятно, это связано с тем, что страница не закрывает теги».

Как я использую Hap After Patch ...

HtmlDocument hapDoc = new HtmlDocument();
hapDoc.OptionMaxNestedChildNodes = 5000;//This is what was added
string rawContent = GETTHECONTENTHERE
try
{
    hapDoc.LoadHtml(RawContent);    
}
catch (Exception e)
{
    //Instead of a stackoverflow exception you should end up here now
    hapDoc.LoadHtml("");
    _logger.Error(e);
}


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow