2012-05-17 4 views
6

Я не очень хорошо с регулярным выражением, так что я даже не знаю, что это один делает, а именно:preg_match терпит неудачу в PHP> 5,3

echo preg_match('/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/', 'example12345678.com>'); 

Я взял его из старой версии Zend Framework - 1.5, который устарел и в последней стабильной версии фреймворка это регулярное выражение больше не представлено. Однако его поведение любопытно, потому что я не нашел документального объяснения или отсталой несовместимости в официальных ресурсах php.

Дело в том, что на php 5.2. * Он отлично работает: возвращает 0. На php 5.3.10, 5.4.0 (скорее всего 5.3. , 5.4. Предполагаю), он возвращает FALSE, что означает «ошибка ».

Мой вопрос: почему? и какова ошибка? Это регулярное выражение, какая-то рекурсия или неоднозначность правил? Почему это работает на php 5.2, если это так?


Интересно, что если я изменю «example12345678.com>» на «example1234567.com>» (что делает его один или несколько голец короче) - он начинает работать и возвращает 0. Если изменить его на «123123123123123123123123123 'он тоже работает и возвращает 1.

UPD: пока не знаю, если это имеет значение, но версии PCRE здесь 8,02 (PHP 5.2) против 8,12 (PHP 5,3)


UPD2: Я понимаю, для чего это ... более или менее ... и нет никаких проблем с тем, чтобы что-то работало прямо сейчас. Как я уже сказал, обновление Zend_Validate_ * решает. Я попытаюсь описать свою озабоченность другими словами:

скажите, я обновляю важную часть программного обеспечения, создавая php5.2> php5.3. Я пытаюсь найти информацию обо всех проблемах, с которыми я мог столкнуться (в основном, читая это: http://php.net/manual/en/migration53.php). Программное обеспечение немного устарело, но оно не является древним, например. Zend Framework может быть версии 1.5. Я проверяю/исправляю/анализирую и исправляю каждую разрыву bc и устаревшую функцию. Даже мои модульные тесты работают нормально.

К моему удивлению, что описано в вопросе. (Если быть точным, Zend_Validate_Hostname выдает исключение). Итак, теперь я хочу знать, почему я пропустил это при обновлении и, что более важно, должен ли я перепроверять все «preg_match» (и другие функции использования PCRE) в приложении, которые пытаются использовать различные воображаемые входные данные, пытаясь найти похожие «исправления ошибок» ».

Если это «ошибка исправления». Потому что это похоже на новую ошибку - она ​​работала так, как ожидалось, в php5.2 и больше не работает.

Была надежда найти некоторые подсказки, чтобы сузить область поиска.

+1

Как вы используете его, если вы не знаете, что он делает , в точку? – ilanco

+0

И из какого файла вы его взяли? –

+0

@ilanco, я использую его как часть рамки. Однако это оффтоп. – lcf

ответ

2

Это уродливое регулярное выражение. Проблема в том, что существует слишком много способов, чтобы строка могла соответствовать, и поэтому у двигателя заканчивается память, пробуя их все до того, как он выяснит, что это действительно не соответствует.

Кроме того, похоже, что он пытается сопоставить действительные доменные имена, и это не так.Я хотел бы заменить этот вызов preg_match с вызовом этой функции вместо:

function is_valid_domain_name($string) { 
    if (strlen($string) > 253) { 
     return false; 
    } 
    $label = '(?!-)[a-zA-Z0-9-]{0,63}(?<!-)'; 
    return preg_match("/^(?:$label\.){0,126}$label$/", $string); 
} 

Он быстро выходит из строя на проблемной строки:

echo is_valid_domain_name('example12345678.com>'),"\n"; 
+0

Это действительно уродливо. Как и большинство других регулярных выражений. :) Спасибо за ваш ответ Марк. Однако проблема с этим конкретным регулярным выражением была решена. Я спросил о: почему он работал с php5.2? Я уточнил свой вопрос с некоторыми деталями. – lcf

+0

Вы никогда не поймаете все в апгрейде, без матерства, насколько вы осторожны. Если бы у вас был тест, который вызвал эту проблему, отлично, но вы этого не сделали. Вам просто нужно быть готовым к повторению и исправлению того, что вы найдете сломанным впоследствии. Я предполагаю, что произошел сбой в движке pcre, который установил более жесткое ограничение (или, может быть, просто ограничение, где раньше не было), чтобы попытаться избежать проблем с бесконечной рекурсией. –

+0

Вы правы, я не могу все поймать. Но я могу попытаться поймать как можно больше. И те вещи, которые я действительно поймаю, должны иметь объяснение, что-то реальное, а не просто «о, вздох, неудача, что ты собираешься делать». Если это ошибка, я могу сообщить об этом, если это функция, мы могли бы добавить ее в список несовместимых обратных. – lcf