Soluzione attorno a StackOverflowException

html-agility-pack stack-overflow

Domanda

Sto utilizzando HtmlAgilityPack per analizzare circa 200.000 documenti HTML.

Non riesco a prevedere il contenuto di questi documenti, tuttavia uno di questi documenti causa il fallimento della mia applicazione con StackOverflowException . Il documento contiene questo HTML:

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

Ci sono circa 10.000 elementi <li> nidificati in questo modo. A causa del modo in cui HtmlAgilityPack analizza l'HTML, viene generata una StackOverflowException .

Sfortunatamente una StackOverflowException non è catchable in .NET 2.0 e versioni successive.

Mi sono interrogato sull'impostazione di una dimensione più grande per lo stack del thread, ma l'impostazione di una dimensione dello stack più grande è un hack: farebbe in modo che il mio programma utilizzasse molta più memoria (il mio programma avvia circa 50 thread per l'elaborazione di HTML, quindi tutti questi thread avrebbe la maggiore dimensione dello stack) e avrebbe bisogno di una regolazione manuale se si fosse imbattuto in una situazione simile di nuovo.

Ci sono altre soluzioni alternative che potrei impiegare?

Risposta accettata

Idealmente, la soluzione a lungo termine è quella di applicare una patch a HtmlAgilityPack per utilizzare un heap-stack anziché lo stack di chiamate, ma sarebbe un'impresa troppo grande per me. Ho temporaneamente perso i dettagli del mio account CodePlex, ma quando tornerò li invierò un rapporto di problema sul problema. Rilevo inoltre che questo problema potrebbe presentare una vulnerabilità di attacco Denial-of-Service a qualsiasi sito che utilizza HtmlAgilityPack per disinfettare l'HTML inviato dall'utente: un documento HTML sovradimensionato creato causerebbe la morte del processo w3wp.exe.

Nel frattempo, ho capito che il modo migliore per superare manualmente la dimensione massima dello stack di thread. Ho sbagliato nella mia precedente affermazione che una maggiore dimensione dello stack significa che tutti i thread consumano automaticamente quella memoria (sembra che le pagine di memoria siano allocate per uno stack di thread man mano che cresce, non tutto in una volta).

Ho fatto una copia della pagina <ol><li> e ho fatto alcuni esperimenti. Ho scoperto che il mio programma falliva quando le dimensioni dello stack erano inferiori a 2^21 byte di dimensione, ma una dimensione massima di 2^22 riuscita - cioè 4 MB e nel mio libro passa come un attacco "accettabile" ... per ora.


Risposta popolare

Ho appena corretto un errore che credo sia lo stesso di quello che hai descritto. Carica la patch sul sito del progetto hap ...

http://www.codeplex.com/site/users/view/sjdirect (guarda la patch il 3/8/2012)

O vedi più documentazione del problema e risultato qui ....

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

La correzione effettiva era ... Aggiunta di HtmlDocument.OptionMaxNestedChildNodes che può essere impostata per impedire StackOverflowException causata da tonnellate di tag nidificati. Lancia una ApplicationException con il messaggio "Il documento ha più di X tag nidificati. Ciò è probabilmente dovuto al fatto che la pagina non chiude i tag correttamente."

Come sto usando 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);
}


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché