Apache/PHP на Windows падает с регулярным выражением

Я обнаружил, что при работе на сервере Windows Apache происходит сбой следующего кода PHP:

Интересно, что код работает, если строка немного короче - если я прокомментирую последнюю часть строки, код работает и работает как ожидалось.

Однако, поскольку код представлен здесь, код заставляет Apache сбой и респаун - ошибка не регистрируется. Если я пытаюсь запустить код напрямую через PHP, он работает так, как ожидалось, поэтому проблема как-то связана с Apache.

Я экспериментировал с параметром "pcre.recursion_limit" и обнаружил, что если я опустил его до 689, он не умрет, но вместо этого вызов preg_match() завершился неудачно с помощью PREG_RECURSION_LIMIT_ERROR. Для более высоких значений pcre.recursion_limit Apache умирает.

Apache 2.2.11 PHP 5.3.0

Я также тестировал это на сервере Debian, где я НЕ вижу ошибку, и с разными версиями PHP и Apache в Windows, где ошибка происходит, как описано выше, поэтому кажется, что это может быть связано с Windows.

У кого-нибудь это есть? Мне бы очень хотелось кое-что сказать!

ОБНОВЛЕНИЕ: Я из-за "ошибки" в Apache для Windows - ну, на самом деле это не ошибка, но кажется, что Apache скомпилирован с небольшим стекированием, и это вызывает эту ошибку в PCRE, когда PHP использует его. См. http://bugs.php.net/bug.php?id=47689

3 ответа

Всегда полезно понизить "pcre.recursion_limit", потому что по умолчанию высокое значение может повредить стек процесса (см. http://php.net/manual/en/pcre.configuration.php) - это именно то, что происходит с вашей установкой mod_php. Поскольку функции preg не выбрасывают ошибку при достижении пределов рекурсии/обратного отслеживания, может оказаться полезным иметь оболочку типа

function match($re, $text) {
 preg_match($re, $text, $m);
 if(preg_last_error())
 trigger_error("preg: " . preg_last_error());
 return $m;
 }

По крайней мере, это позволяет узнать, когда что-то пойдет не так.

Кроме того, попробуйте упростить ваши шаблоны, когда это возможно, например /^\d[\d,]*\d$/ делает то же, что и выше, но с нулевой рекурсией.


Увеличьте стек Apache, и проблема исчезнет, ​​или используйте httpd config, чтобы увеличить его.

Большинство сборок Apache имеют слишком маленький размер стека, в то время как у нас есть нормальный для PHP-сборки. Это объясняет, почему одни и те же выражения будут работать в CLI, а не в Apache (стек для каждого процесса и процесс принадлежит/определяется Apache).


Авария обычно означает, что вы попали в ошибку PHP. Время от времени это случается. Если вы не сможете обновить свою установку PHP, вам придется переписать свой код. Во всяком случае, высокий уровень рекурсии предполагает, что вы не должны использовать регулярные выражения или, по крайней мере, вы должны сначала разделить входную строку на более мелкие части.

licensed under cc by-sa 3.0 with attribution.