2 votes

Expression régulière crashe Apache en raison des limitations de PCRE

Je suis actuellement en train de créer un moteur d'analyse de bbcode et j'ai rencontré une situation que je ne peux pas résoudre seul.

Le problème est que je me suis retrouvé face à un problème exactement similaire à celui-ci : Apache / PHP on Windows crashes with regular expression

Cela signifie que si je fais quelque chose comme l'exemple ci-dessous, Apache plante à cause du compteur de récursion qui atteint 690 (limite de mémoire de 1 Mo pour PCRE) :

$txt = '[b]'.str_repeat('a', 338).'[/b]';  // si je réduis la valeur de la répétition, ça fonctionne
$regex = '#\[(?P(?P[a-z0-9_]*?)(?:=.*?|\s.*?|))](?P(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)\[/(?P=tag)]#mi';

echo preg_replace_callback($regex, function($matches) { return $matches['content']; }, $txt);

Je dois donc somehow minimiser le besoin de * et de + dans mon regex, mais c'est là que je suis à court d'idées, donc je pensais que vous pourriez suggérer quelque chose.

D'autres approches pour l'analyse du bbcode (qui pourraient gérer les balises imbriquées) sont les bienvenues. Cependant, je n'aimerais pas utiliser une classe déjà existante ou autre. J'aime faire les choses par moi-même !

J'ai également jeté un œil à PECL et Pear HTML_BBCodeParser. Mais je ne veux pas que mon application dépende d'extensions. Il est plus probable que je fasse un script qui vérifie si cette extension existe et si ce n'est pas le cas, utilise l'analyseur BBCode que j'essaie de faire ici.

Désolé si mes descriptions sont sombres, je ne suis pas un pro en anglais ^^

EDIT. Ainsi, le regex expliqué :

\[(?P(?P[a-z0-9_]*?)(?:=.*?|\s.*?|))]

Ceci est ma balise d'ouverture. J'ai utilisé des groupes nommés. Avec 'tag', j'identifie la balise et avec 'attributes', j'identifie les attributs de balises. Pensez à la balise comme un attribut aussi. Que se passe-t-il ici ? J'essaie de faire correspondre une balise, lorsque la balise est trouvée, j'essaie de faire correspondre tout ce qui se trouve après le signe de = ou après \s (espaceur) jusqu'à ce qu'il atteigne la fermeture de la balise ].

(?P(?:[^[]|\[(?!/?(?P=tag)])|(?R))+?)

Maintenant, ici j'essaie de faire correspondre le contenu. C'est la partie délicate. Je recherche un caractère qui n'est pas [ et si j'en trouve un, alors je vérifie s'il ne s'agit pas de ma balise de fin ou de récursion, et je dis au moteur de regex de le faire jusqu'à ce que....

\[/(?P=tag)]

... la balise de fin soit trouvée.

3voto

NullUserException Points 42268

Votre regex, en particulier les assertions de largeur zéro (lookaround), font reculer le moteur regex de manière catastrophique. Moral de l'histoire: Regex ne peut pas ne devrait pas être utilisé pour analyser des langues qui ne sont pas régulières. Si vous avez des structures imbriquées, ce n'est pas un langage régulier.

En fait, je pense que BBCode est maléfique. BBCode est un langage de balisage inventé par des programmeurs paresseux qui ne voulaient pas filtrer le HTML de la bonne manière. En conséquence, nous avons maintenant un "standard" lâche qui est difficile à implémenter. Filtrez votre HTML correctement:

http://htmlpurifier.org/

2voto

Vivin Paliath Points 40975

J'allais suggérer un BBCodeParser...

J'ai également examiné PECL et Pear HTML_BBCodeParser. Mais je ne veux pas que mon application dépende d'extensions

Je trouve cela très étrange. Pourquoi réinventer la roue? Un des principes du bon génie logiciel est DRY (Don't Repeat Yourself). Vous essayez de résoudre un problème qui a déjà été résolu.

J'aime faire les choses par moi-même!

Ce n'est pas mal en soi, mais il y a des moments où il vaut mieux utiliser une solution éprouvée; une solution mieux testée et plus robuste que la vôtre (comme vous le constatez). De cette manière, vous passerez du temps sur le problème que vous voulez réellement résoudre au lieu de résoudre un problème qui a déjà été résolu. Ne tombez pas dans le piège de réinventer la roue. :)

Ma suggestion (et solution) pour vous est d'utiliser un parseur BBCode.

EDIT

Autre chose, vous analysez quelque chose qui ressemble à du HTML. Ce genre de choses ne se prêtent pas facilement à être analysées par des expressions régulières.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X