web-dev-qa-db-fra.com

preg_match (): échec de la compilation: plage non valide dans la classe de caractères à l'offset

Merci d'avance pour le temps que vous avez consacré à ce problème.

preg_match (): échec de la compilation: plage non valide dans la classe de caractères à l'offset 20 session.php sur la ligne 278

Cela a cessé de fonctionner tout à coup après des mois de travail, après une mise à niveau PHP sur notre serveur.

Voici le code

    else{
     /* Spruce up username, check length */
     $subuser = stripslashes($subuser);
     if(strlen($subuser) < $config['min_user_chars']){
        $form->setError($field, "* Username below ".$config['min_user_chars']."characters");
     }
     else if(strlen($subuser) > $config['max_user_chars']){
        $form->setError($field, "* Username above ".$config['max_user_chars']."characters");
     }


     /* Check if username is not alphanumeric */
    /* PREG_MATCH CODE */

     else if(!preg_match("/^[a-z0-9]([0-9a-z_-\s])+$/i", $subuser)){        
        $form->setError($field, "* Username not alphanumeric");
     }


    /* PREG_MATCH CODE */


     /* Check if username is reserved */
     else if(strcasecmp($subuser, GUEST_NAME) == 0){
        $form->setError($field, "* Username reserved Word");
     }
     /* Check if username is already in use */
     else if($database->usernameTaken($subuser)){
        $form->setError($field, "* Username already in use");
     }
     /* Check if username is banned */
     else if($database->usernameBanned($subuser)){
        $form->setError($field, "* Username banned");
     }
  }
24
user3841888

Une plage de classes de caractères est définie en utilisant - entre deux valeurs dans une classe de caractères ([] en regex). [0-9] signifie tout entre 0 et 9 inclus. Dans l'expression régulière de votre code, vous disposez de plusieurs plages de classes de caractères, a-z, 0-9. Il y a aussi une classe que vous n'aviez probablement pas l'intention d'y mettre, à savoir _-\s.

"/^[a-z0-9]([0-9a-z_-\s])+$/i"
                   ^^^^ 

Cela n'est apparemment pas considéré comme une plage de caractères non valide dans certaines versions (la plupart?) De PCRE (la bibliothèque d'expressions régulières PHP utilise), mais cela pourrait avoir changé récemment, et si la bibliothèque PCRE a été mise à niveau sur le serveur, cela pourrait être la raison.

Debuggex est un outil sympa qui peut aider à déboguer les erreurs (enfin, le message d'erreur de PHP vous a dit à la fois la ligne et le personnage où l'erreur était, alors ..) comme ça (je ne suis pas affilié, juste un fan).

23
MatsLindh

Votre erreur dépend de votre interprète regex.

Vous pouvez échapper le trait d'union pour être clair sur son utilisation. Signification en utilisant \- au lieu de -.

Votre code final:

/^[a-z0-9]([0-9a-z_\-\s])+$/i
14
Moradnejad

Le problème est vraiment ancien, mais il existe de nouveaux développements liés à PHP 7.3 et les versions plus récentes qui doivent être couverts. Le moteur PHP PCRE migre vers PCRE2 , et la version PCRElibrary utilisée dans PHP 7.3 est 10,32, et c'est là que Backward Incompatible Changes proviennent de:

  • L'API de la bibliothèque interne a changé
  • Le modificateur "S" n'a aucun effet, les motifs sont étudiés automatiquement. Aucun impact réel.
  • Le modificateur "X" est le comportement par défaut dans PCRE2. Le correctif actuel rétablit le comportement à la signification de "X" comme c'était dans PCRE, mais il pourrait être préférable de suivre le nouveau comportement et d'activer "X" par défaut. Donc, actuellement, pas d'impact non plus.
  • Un changement de comportement dû au nouveau moteur Unicode a été aperçu. C'est Unicode 10 dans PCRE2 vs Unicode 7 dans PCRE. Certains changements de comportement peuvent être observés avec des modèles non valides.

Acc. vers le PHP 10.33 changelog:

  1. Avec PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL set, séquences d'échappement telles que \s qui sont valides dans les classes de caractères, mais pas à la fin des plages, étaient traités comme des littéraux. Un exemple est [_-\s] (mais non [\s-_] car cela a donné une erreur au début d'une plage). Maintenant, une erreur "plage non valide" est donnée indépendamment de PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL.

Avant PHP 7.3, vous pouvez utiliser le trait d'union dans une classe de caractères dans n'importe quelle position si vous l'avez échappé, ou si vous le mettez "dans une position où il ne peut pas être interprété comme indiquant une plage " . Dans PHP 7.3, il semble que le PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL a été défini sur false. Donc, à partir de maintenant, afin de mettre un trait d'union dans une classe de caractères, utilisez-le toujours aux positions de début ou de fin uniquement .

Voir aussi cette référence :

En termes simples,

PCRE2 est plus strict dans les validations de modèle, donc après la mise à niveau, certains de vos modèles existants n'ont plus pu être compilés.

Voici l'extrait simple utilisé dans php.net

preg_match ('/ [\ w -.] + /', ''); // cela ne fonctionnera pas en PHP7.3 
 preg_match ('/ [\ w\-.] + /', ''); // le tiret doit être échappé

Comme vous pouvez le voir dans l'exemple ci-dessus, il y a une petite mais substantielle différence entre les deux lignes.

4
Wiktor Stribiżew