Необходимо предотвратить повторное выражение PHP regex

Почему следующий segfault и как я могу его предотвратить?

<?php $str = ' <fieldset> <label for="go-to">Go to: </label> ' . str_repeat(' ', 10000) . '<input type="submit" value="Go" /> </fieldset> </form>'; preg_match_all("@ </?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags (?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* #allow text and some inline tags [\?\!\.]+ @ix", $str, $matches); ?> 

Я считаю, что это вызывает … ожидание … переполнение стека.

РЕДАКТИРОВАТЬ:

Вышеприведенная версия представляет собой упрощенную версию шаблона, демонстрирующего проблему. Более полная версия:

 @ </?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags (?:[^<]|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* # continue, allow text content and some inline tags # normal sentence ending [\?\!\.]+ # valid ending characters -- note elipses allowed (?<!\b[ap]m\.)(?<!\b[ap]\.m\.)(?<!digg this\!)(?<!Stumble This\!) # disallow some false positives that we don't care about \s* (?:&apos;|&\#0*34;|'|&lsquo;)?\s* # closing single quotes, in the unusual case like "he said: 'go away'". (?:"|&quot;|&\#0*34;|&\#x0*22;|&rdquo;|&\#0*8221;|&\#x0*201D;|''|``|\xe2\x80\x9d|&\#0*148;|&\#x0*94;|\x94|\))?\s* # followed by any kind of close-quote char (?=\<) # should be followed by a tag. @ix 

Цель состоит в том, чтобы найти html-блоки, которые, кажется, заканчиваются на том, что выглядит как окончательное английское предложение. Я обнаружил, что этот метод очень хорошо говорит о различии между текстом «контент» (например, телом статьи) и текстом «layout» (т. Е. Как навигационные элементы). Однако, если между ярлыками, которые он взрывает, есть огромное количество пробелов.

Первое, что я постараюсь сделать, – сделать все кванторы собственниками и все группы атомарными:

 "@</?+(?![bisa]\b)(?!em\b)[^>]*+> (?>[^<]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+ [?!.]+ @ix" 

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

РЕДАКТИРОВАТЬ: чтобы разрешить пунктуацию, заканчивающуюся предложением, вы могли бы добавить еще одну альтернативу второй строке:

 (?>[^<?!.]++|(?![^?!.\s<]++<)[?!.]++|</?+(?>(?>[bisau]|em|strong|sup)\b)[^>]*+>)*+ 

Добавление соответствует одному или нескольким указанным символам, если они не являются последними символами без пробелов в элементе.

Я уверен, что еще более новые версии PHP связаны с PCRE 7.0, который имеет проблемы с сегментами. Я не думаю, что есть какие-то намерения по исправлению проблемы, поскольку это технически проблема PCRE, а не проблема с PHP.

Если вы скажете нам, что вы пытаетесь сделать, вы должны попытаться написать альтернативное выражение.

Исправлена ​​ошибка: http://bugs.php.net/bug.php?id=40909

Это все еще делает то, что вы хотите?

 </?(?![bisa]\b)(?!em\b)[^>]*> # starting tag, must not be one of several inline tags (?:(?>[^<\?\!\.]*)|</?(?:(?:[bisau]|em|strong|sup)\b)[^>]*>)* #allow text and some inline tags [\?\!\.]+ 

Ваше регулярное выражение вызывает огромное количество обратного отслеживания. С посещением 10000 персонажей он становится довольно грязным и медленным. Тем не менее, я бы не ожидал, что он рухнет …!