02-05-2013, 09:41 PM
Finalement, si j'en crois stack overflow (quel beau site!), le problème semble être du à la façon dont Apache est compilé pour Windows.
Si j'ai bien compris, mais j'en suis pas certain à 100%:
"Apache is compiled with a small stacksize", et une regex comme "#(/\*([^\*]|\*[^/])*\*/)|(@@.*$)#m" dépasse ce stack.
Il semblerait que ce soucis de stack viennent du mode "greedy" (gourmand) des regex: les quantificateurs + et * des regex PHP sont gourmands c'est à dire que pour X* ou X+, php essaye de mettre un maximum de caractères possibles dans le X (par exemple, dans .*x, php essayera de mettre le plus de caractères possibles dans le ., et de faire suivre l'ensemble de ces caractères par un x).
Mais ce caractère gourmand pose soucis: pendant l'évaluation de la regex, php peut être "trop" gourmand, et la regex ne marche plus. PHP "revient" alors en arrière, et devient moins gourmand. Par exemple, si ma chaine est "0123456789abcdef", pour la regex "#.*\w+#", php fait le travail suivant:
- .*, je mets un max de caractères dedans: 0123456789abcdef (le caractère après "f" est la fin de chaine, non-couvert par ".", donc je ne peux pas le manger)
- le pattern demande maintenant \w+... zut, mon caractère courant, la fin de chaine ($), n'est pas bon...
- je "démange" un caractère: 0123456789abcde, et je suis actuellement sur f
- le pattern demande maintenant \w+... oui! f est un \w, je le mange: 0123456789abcdef, et je suis sur le caractère $
- le pattern est fini, la regex est machée.
Dans ce mécanisme, le "démangeage" implique de stocker les caractères sur une pile (le stack). Or, si on n'a pas réservé assez de palce sur cette pile (lors de la compilation d'Apache), boum! C'est le drame, stack overflow (littéralement).
Du coup, avec une regex non-gourmande (option "U"), le problème disparait (pas de "démangeage" possible, pas de stack overflow). Le problème disparait aussi si la regex est mieux structurée (là, j'ai pas vraiment de précision à donner sur ce point).
Après, j'en suis vraiment, mais alors vraiment pas certain.
En tous cas, un serveur Apache qui crashe sous windows avec une erreur de type "unknown exception" ou similaire (pas de message d'erreur explicite) peut venir d'une regex dont l'entrée est trop longue. Le remède est donc soit de réduire l'entrée, soit de changer la regex, soit de changer d'OS.
Résolu.
Si j'ai bien compris, mais j'en suis pas certain à 100%:
"Apache is compiled with a small stacksize", et une regex comme "#(/\*([^\*]|\*[^/])*\*/)|(@@.*$)#m" dépasse ce stack.
Il semblerait que ce soucis de stack viennent du mode "greedy" (gourmand) des regex: les quantificateurs + et * des regex PHP sont gourmands c'est à dire que pour X* ou X+, php essaye de mettre un maximum de caractères possibles dans le X (par exemple, dans .*x, php essayera de mettre le plus de caractères possibles dans le ., et de faire suivre l'ensemble de ces caractères par un x).
Mais ce caractère gourmand pose soucis: pendant l'évaluation de la regex, php peut être "trop" gourmand, et la regex ne marche plus. PHP "revient" alors en arrière, et devient moins gourmand. Par exemple, si ma chaine est "0123456789abcdef", pour la regex "#.*\w+#", php fait le travail suivant:
- .*, je mets un max de caractères dedans: 0123456789abcdef (le caractère après "f" est la fin de chaine, non-couvert par ".", donc je ne peux pas le manger)
- le pattern demande maintenant \w+... zut, mon caractère courant, la fin de chaine ($), n'est pas bon...
- je "démange" un caractère: 0123456789abcde, et je suis actuellement sur f
- le pattern demande maintenant \w+... oui! f est un \w, je le mange: 0123456789abcdef, et je suis sur le caractère $
- le pattern est fini, la regex est machée.
Dans ce mécanisme, le "démangeage" implique de stocker les caractères sur une pile (le stack). Or, si on n'a pas réservé assez de palce sur cette pile (lors de la compilation d'Apache), boum! C'est le drame, stack overflow (littéralement).
Du coup, avec une regex non-gourmande (option "U"), le problème disparait (pas de "démangeage" possible, pas de stack overflow). Le problème disparait aussi si la regex est mieux structurée (là, j'ai pas vraiment de précision à donner sur ce point).
Après, j'en suis vraiment, mais alors vraiment pas certain.
En tous cas, un serveur Apache qui crashe sous windows avec une erreur de type "unknown exception" ou similaire (pas de message d'erreur explicite) peut venir d'une regex dont l'entrée est trop longue. Le remède est donc soit de réduire l'entrée, soit de changer la regex, soit de changer d'OS.
Résolu.