web-dev-qa-db-ja.com

preg_match():コンパイルに失敗しました:オフセットの文字クラスの範囲が無効です

この問題にご協力いただきありがとうございます。

preg_match():コンパイルに失敗しました:278行目のオフセット20 session.phpの文字クラスの無効な範囲

サーバーでのPHPアップグレード後、数か月の作業の後、これは突然動作しなくなりました。

ここにコードがあります

    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

文字クラスの範囲は、文字クラスの2つの値の間に-を使用して定義されます(正規表現では[])。 [0-9]は、0から9までのすべてを意味します。コードの正規表現には、いくつかの文字クラス範囲、a-z0-9があります。また、おそらくそこに置くつもりはなかったクラスが1つあります。それは_-\sです。

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

これは、PCREのいくつかの(ほとんどの?)バージョン(正規表現ライブラリPHP使用))で無効な文字範囲とは見なされませんが、最近変更された可能性があり、PCREライブラリがアップグレードされた場合サーバー上で、それが理由である可能性があります。

Debuggex は、エラーのデバッグに役立つ素敵なツールです(PHPからのエラーメッセージは、行andエラーがあった場所の文字、つまり..)このように(私は提携していない、ただのファンです)。

23
MatsLindh

エラーは正規表現インタープリターに依存しています。

その使用法を明確にするためにハイフンをエスケープできます\-の代わりに-を使用する意味。

最終コード:

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

問題は本当に古いですが、PHP 7.3以降のバージョンをカバーする必要があることに関連するいくつかの新しい開発があります。PHP PCREエンジンはPCRE2に移行します PHP 7.3は10.32で使用され、それは 後方互換性のない変更 の起源です:

  • 内部ライブラリAPIが変更されました
  • 「S」修飾子は効果がなく、パターンは自動的に調査されます。実質的な影響はありません。
  • 「X」修飾子は、PCRE2のデフォルトの動作です。現在のパッチは、PCREでの動作を「X」の意味に戻しますが、新しい動作を使用し、デフォルトで「X」をオンにする方がよい場合があります。そのため、現時点では影響もありません。
  • より新しいUnicodeエンジンによるいくつかの動作の変更が確認されました。 PCRE2のUnicode 10とPCREのUnicode 7です。無効なパターンを使用すると、一部の動作の変更を確認できます。

Acc。 PHP 10.33 changelog:

  1. PCRE2_EXTRA_BAD_ESCAPE_IS_LITERALを設定すると、\sなどのエスケープシーケンスは文字クラスで有効ですが、範囲の終わりとしてではなく、リテラルとして扱われていました。例は[_-\s]です(ただし、範囲のstartでエラーが発生したため、[\s-_]ではありません)。 「無効な範囲」エラーがPCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL。とは別に与えられます

PHP 7.3より前では、文字クラスでハイフンを使用する場合、エスケープする場合、または "を示すと解釈できない位置に配置する場合があります。範囲」 。PHP 7.3では、PCRE2_EXTRA_BAD_ESCAPE_IS_LITERALがfalseに設定されたようです。したがって、今後は、ハイフンを文字クラスに入れるために、- 常に開始位置または終了位置でのみ使用する

このリファレンス も参照してください:

簡単に言えば、

PCRE2はパターンの検証がより厳密であるため、アップグレード後、既存のパターンの一部はコンパイルできなくなりました。

これは、php.netで使用される簡単なスニペットです。

preg_match( '/ [\ w-。] + /'、 ''); //これはPHP7.3では機能しません
 preg_match( '/ [\ w \-。] + /'、 ''); //ハイフンをエスケープする必要があります

上記の例からわかるように、2つの行にはわずかではありますが実質的な違いがあります。

4