regex 预匹配():编译失败:字符类中偏移量的范围无效

nxagd54h  于 2023-01-21  发布在  其他
关注(0)|答案(5)|浏览(150)

提前感谢您花时间帮助解决这个问题。
预匹配():编译失败:第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");
     }
  }
yb3bgrhw

yb3bgrhw1#

这个问题确实是老问题了,但是有一些与PHP 7.3和更新版本相关的新开发需要介绍。PHP PCRE引擎迁移到PCRE2,PHP 7.3中使用的PCRE库版本是10.32,这就是向后不兼容更改的来源:

  • 内部库API已更改
  • 修改符“S”没有效果,模式是自动研究的。没有真实的的影响。
  • “X”修饰符是PCRE2中的默认行为。当前的补丁将行为还原为PCRE中“X”的含义,但使用新行为并默认打开“X”可能更好。因此目前也没有影响。
  • 由于新的Unicode引擎,发现了一些行为变化。PCRE2中的Unicode 10与PCRE中的Unicode 7。一些行为变化可以通过无效模式看到。

根据PHP 10.33更新日志:
1.设置PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL后,转义序列(如\s)在字符类中有效,但不能作为范围的结尾,因此被视为文本。[_-\s](但不是[\s-_],因为它在范围的 * 开始 * 处给出错误)就是一个示例。现在,“invalid range”错误与PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL无关。
在PHP 7.3之前,如果你将连字符转义,或者将连字符放在"in a position where it cannot be interpreted as indicating a range",你可以在字符类的任何位置使用连字符。在PHP 7.3中,似乎PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL被设置为false。所以,从现在开始,为了将连字符放在字符类中,总是只在开始或结束位置使用它
另请参见this reference
简而言之,
PCRE2在模式验证方面更为严格,因此在升级之后,一些现有的模式将无法再编译。
下面是www.example.com中使用的简单代码段php.net

preg_match('/[\w-.]+/', ''); // this will not work in PHP7.3
preg_match('/[\w\-.]+/', ''); // the hyphen need to be escaped

正如您从上面的示例中看到的,这两行之间有一个微小但实质性的差异。

2w2cym1i

2w2cym1i2#

字符类范围是通过在字符类中的两个值之间使用-来定义的(regex中为[])。[0-9]表示0到9之间的所有值,包括0和9。在代码的正则表达式中,您有几个字符类范围,a-z0-9。还有一个类,您可能不想放在那里,即_-\s

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

在PCRE(PHP使用的正则表达式库)的一些(大多数?)版本中,这显然不被认为是无效字符范围,但它最近可能发生了变化,如果PCRE库在服务器上升级,这可能是原因。
Debuggex是一个很好的工具,可以帮助调试错误(来自PHP的错误消息告诉您错误所在的行 * 和 * 字符,所以..),就像这样(我不是会员,只是一个粉丝)。

t1qtbnec

t1qtbnec3#

您的错误取决于正则表达式解释器。

您应该转义连字符以明确它是字符。因此使用\-而不是-

您的最终代码:

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

svujldwt4#

也许这个答案可以保存一些人与阿拉伯语/波斯语鼻涕虫创作:
如果php版本为7.3,请使用\-代替-
[^a-z0- 9_\s-
以及
/[\s-_]+/
所以对于php 7.3的阿拉伯语make_slug函数:

function make_slug($string, $separator = '-')
{
    $string = trim($string);
    $string = mb_strtolower($string, 'UTF-8');

    // Make alphanumeric (removes all other characters)
    // this makes the string safe especially when used as a part of a URL
    // this keeps latin characters and Persian characters as well
    $string = preg_replace("/[^a-z0-9_\s\-ءاآؤئبپتثجچحخدذرزژسشصضطظعغفقكکگلمنوهی]/u", '', $string);

    // Remove multiple dashes or whitespaces or underscores
    $string = preg_replace("/[\s\-_]+/", ' ', $string);

    // Convert whitespaces and underscore to the given separator
    $string = preg_replace("/[\s_]/", $separator, $string);

    return $string;
}
az31mfrm

az31mfrm5#

我有这个错误,我解决它通过这样做
Route::get('{path}','HomeController@index')->where( 'path', '([A-z]+)?' );
这对我来说是工作。

相关问题