Les RegExp dans preg_match fonction de retour d'erreur de navigateur
La fonction suivante rompt avec les regexp, que j'ai fourni dans le $motif variable. Si je change la regexp, je suis bien, donc je pense que c'est le problème. Je ne vois pas le problème, cependant, et je ne suis pas la réception d'un standard d'erreur PHP, même s'ils sont sous tension.
function parseAPIResults($results){
//Takes results from getAPIResults, returns array.
$pattern = '/\[(.|\n)+\]/';
$resultsArray = preg_match($pattern, $results, $matches);
}
Firefox 6: La connexion a été réinitialisée
Chrome 14: Erreur 101 (net::ERR_CONNECTION_RESET): La connexion a été
réinitialiser.IE 8: Internet Explorer ne peut pas afficher la page web
Mise à JOUR:
Apache/PHP peut être de s'écraser. Voici le journal des erreurs d'Apache à partir de quand je lance le script:
[Sam Oct 01 11:41:40 2011] [avis] Parent de l'enfant: processus est sorti avec
le statut de 255 -- le Redémarrage.
[Sam Oct 01 11:41:40 2011] [avis]
Apache/2.2.11 (Win32) PHP/5.3.0 configuré -- reprise normale
les opérations de
L'exécution de WAMP 2.0 sur Windows 7.
- si vous recherchez une . ou une nouvelle ligne?
- Je suis à la recherche d'un . ou une nouvelle ligne à l'intérieur des parenthèses. L'expression rationnelle vérifie sur regexpal.com
- Vous avez peut-être droit. Voici le journal des erreurs d'apache à partir du moment où je lance le script: [Sam Oct 01 11:41:40 2011] [avis] Parent de l'enfant: processus terminé avec le statut de 255 -- le Redémarrage.
- L'incident que vous voyez n'est pas nouvelle et est due suis non gérée débordement de pile dans la librairie PCRE en raison d'une certaine classe de regex être appliquée à un largish chaîne. La mise à niveau de PHP vers la version la plus récente (5.3.8) ne va pas aider. Je suis actuellement en train de travailler sur une réponse détaillée à cette question en ce moment (il n'est pas trivial). Veille... En attendant, vous pouvez jeter un oeil à la façon dont ce problème a affecté le projet Drupal un moment de retour: Optimiser le CSS causes de php en mode cgi pour erreur de segmentation dans pcre de la fonction "match"
- Oui. Histoire courte: PHP
pcre.recursion_limit
par défaut est de 100 000 qui est trop élevé. Cette valeur doit être réglée à la taille de la pile divisé par 500 selon la PCRE de la Documentation. Pour une version Win32 dehttpd.exe
, (avec ses 256 ko de pile),pcre.recursion_limit
doit être mis à 524. Sur les systèmes *nix, (avec exécutables généralement avoir une 8MB de la pile), il doit être réduit à 16777.
Vous devez vous connecter pour publier un commentaire.
Simple question. Réponse complexe!
Oui, cette classe de regex va augmenter de façon répétée (et en silence) crash Apache/PHP avec un non gérée erreur de segmentation en raison d'un débordement de pile!
De fond:
Le PHP
preg_*
famille de fonctions regex utiliser le puissant Librairie PCRE par Philip Hazel. Avec cette bibliothèque, il y a une certaine catégorie de regex qui requiert un grand nombre d'appels récursifs à sonmatch()
fonction et cela utilise beaucoup d'espace de pile, (et de l'espace de pile utilisé est directement proportionnelle à la taille de la chaîne en cours d'appariement). Ainsi, si la chaîne est trop longue, un débordement de pile et correspondant à l'erreur de segmentation se produit. Ce comportement est décrit dans le PCRE de la documentation à la fin dans la section intitulée: pcrestack.PHP Bug 1: PHP définit:
pcre.recursion_limit
trop grand.Le PCRE de la documentation explique comment éviter un débordement de la pile faute de segmentation en limitant la profondeur de récursivité à une valeur sûre à peu près égale à la taille de la pile de l'application liée divisé par 500. Lorsque la profondeur de récursivité est bien limitée, comme recommandé, la bibliothèque n'est pas de générer un débordement de la pile et la place gracieusement quitte avec un code d'erreur. En vertu de PHP, ce maximum profondeur de récursion est spécifié avec le
pcre.recursion_limit
variable de configuration et (malheureusement) la valeur par défaut est fixé à 100 000. Cette valeur est TROP GRANDE! Voici un tableau des valeurs sûres depcre.recursion_limit
pour une variété de pile exécutable tailles:Ainsi, pour la version Win32 de du serveur web Apache (
httpd.exe
), qui a une (petite) taille de la pile de 256 KO, la valeur correcte depcre.recursion_limit
doit être réglé à 524. Ceci peut être accompli avec la ligne suivante de code PHP:Lorsque ce code est ajouté au script PHP, le débordement de la pile ne se produit PAS, mais au lieu de cela génère un code d'erreur explicatif. C'est, il DEVRAIT générer un code d'erreur! (Mais malheureusement, à cause d'un autre bogue de PHP,
preg_match()
ne le fait pas.)PHP Bug 2:
preg_match()
ne retourne pas FALSE en cas d'erreur.La documentation PHP pour
preg_match()
dit qu'elle retourne FALSE en cas d'erreur. Malheureusement, les versions de PHP 5.3.3 ci-dessous et avoir un bug (#52732) oùpreg_match()
ne retourne PASFALSE
sur l'erreur (au lieu renvoieint(0)
, qui est la même valeur renvoyée dans le cas d'un non-match). Ce bug a été corrigé dans la version de PHP 5.3.4.Solution:
En supposant que vous continuerez à l'aide de WAMP 2.0 (avec PHP 5.3.0) la solution doit prendre les deux bugs en considération. Voici ce que je recommande:
pcre.recursion_limit
à une valeur sûre: 524.preg_match()
renvoie autre chose queint(1)
.preg_match()
retourneint(1)
, le match a été un succès.preg_match()
retourneint(0)
, le match n'était pas réussi, ou il y avait une erreur.Ici est une version modifiée de votre script (conçu pour être exécuté depuis la ligne de commande) qui détermine le sujet de la longueur de la chaîne qui aboutit à la limite de la récursivité d'erreur:
Lorsque vous exécutez ce script, il permet une lecture de la longueur actuelle de la chaîne. Si le
pcre.recursion_limit
est laissé à sa trop élevée valeur par défaut, cela vous permet de mesurer la longueur de la chaîne qui provoque l'exécutable à l'écrasement.Commentaires:
preg_match()
ne parvient pas à retournerFALSE
lorsqu'une erreur se produit dans la librairie PCRE. Ce bug certainement remet en question BEAUCOUP de code qui utilisepreg_match
! (Je vais certainement aller faire un inventaire de ma propre code PHP.)httpd.exe
) est construit avec un stacksize de 256 KO. Le PHP en ligne de commande exécutable (php.exe
) est construit avec un stacksize de 8 mo. La valeur sûre pour lespcre.recursion_limit
doivent être mis en conformité avec le fichier exécutable que le script est en cours d'exécution en vertu de l' (524 et 16777 respectivement).pcre.recursion_limit
une valeur sûre.preg_match()
correction de la version de PHP 5.2.httpd.exe
exécutable. (Cela ne fonctionne que sous XP mais Vista et Win7 pourraient se plaindre.)<?php ini_set("pcre.recursion_limit", "524"); $contents = 'd' . str_repeat('a', 1900) . 'b'; $contents = preg_replace('/d(a)+b/', '\1', $contents);
se bloque sur Win7, PHP v5.3.9/d(a)+b/
résultats dans le même comportement que décrit dans ma réponse. Il semble que(x)+
résultats dans une récursivité par rep. Bon à savoir.Je suis tombé sur le même problème. Merci beaucoup pour la réponse posté par ridgerunner.
Bien qu'il est utile de savoir pourquoi le php se bloque, pour moi cela ne résout pas vraiment le problème. Pour résoudre le problème, je dois ajuster mon regex afin d'économiser de la mémoire, donc php ne tombent pas en panne anylonger.
La question est donc comment faire pour modifier la regex. Le lien vers le manuel PCRE posté ci-dessus déjà décrit une solution pour un exemple regex qui est assez semblable à la vôtre.
Donc comment réparer votre regex?
Tout d'abord, vous dites que vous voulez correspondre à "un . ou un retour à la ligne".
Notez que le "." est un caractère spécial dans une regex qui n'est pas seulement un point, mais n'importe quel caractère, vous devez donc vous échapper. (J'espère que je n'ai pas vous tromper ici, et ce qui était prévu.)
Prochaine, on peut copier le quantificateur entre parenthèses:
Cela ne change pas le sens de l'expression. Maintenant, nous utilisons les quantificateurs possessifs à la place de ceux normale:
Donc, ce qui devrait avoir le même sens que l'original de votre regex, mais le travail en php sans s'écraser dessus.
Pourquoi? Les quantificateurs possessifs "manger" les personnages et ne permettent pas de revenir en arrière. Par conséquent, PCRE ne pas avoir à utiliser la récursivité et pile de ne débordera pas. L'aide à l'intérieur des parenthèses semble être une bonne idée car nous n'avons pas besoin de la quantification de l'alternative à cette fréquence.
Pour résumer, la meilleure pratique semble être:
La suite de ces règles, j'ai pu résoudre mon problème, et j'espère que cela va aider quelqu'un d'autre.
J'ai eu le même problème et que vous avez besoin pour change le modèle de quelque chose comme
Le " s " à la fin signifie traiter la chaîne de caractères sur une seule ligne.
preg_match renvoie le nombre de correspondances trouvées pour le modèle. Quand vous avez un match, il est à l'origine d'une erreur fatale en php (
print_r(1)
, par exemple, provoque l'erreur). print_r(0) (pour quand vous changer le motif et sans correspondance) ne l'est pas et se contente d'afficher 0.Vous voulez
print_r($matches)
En aparté, votre modèle n'est pas échappé correctement. À l'aide de guillemets signifie que vous avez besoin pour échapper à la antislashs devant de vos supports de.