Регулярные выражения убегающих: катастрофическое возвращение назад
Рассмотрим регулярное выражение (x + x +) + y.
Прежде чем кричать от ужаса и сказать
этот надуманный пример должен быть
записывается как xx + y, чтобы точно соответствовать
то же самое без тех ужасно вложенных
квантификаторы: просто предположим, что каждый «х»
представляет собой нечто более сложное,
с определенными строками, которые сопоставляются
оба "х". Смотрите раздел на HTML
файлы ниже для реального примера.
Посмотрим, что произойдет, когда вы подадите заявку
это регулярное выражение в xxxxxxxxxxy. Первый
х + будет соответствовать всем 10 х символов.
второй х + терпит неудачу. Первый х + потом
возвращается к 9 матчам, а
второй забирает оставшиеся х.
Группа сейчас подобрана один раз.
группа повторяется, но терпит неудачу при первом
х +. Так как одно повторение было
достаточно, группа совпадает. Y
соответствует y и общее совпадение
найденный. Регулярное выражение объявлено
функциональный код доставляется на
клиент, и его компьютер взрывается.
Почти.
Вышеуказанное регулярное выражение становится ужасным, когда вы
отсутствует в строке темы.
Когда у не получается, двигатель регулярных выражений
откатывается. В группе есть один
итерация, в которую он может вернуться.
второй х + соответствует только один х, так что
не могу вернуться. Но первый х + может
отказаться от одного х. Второй х + быстро
соответствует хх. У группы снова есть один
итерации, не выполнит следующую, и
у меня не получается. Возвращаясь снова,
второй х + теперь имеет один возврат
положение, уменьшая себя, чтобы соответствовать х.
Группа пробует вторую итерацию.
Первый х + соответствует, но второй
застрял в конце строки.
Снова возвращаемся, первый х + в
первая итерация группы уменьшает
сам до 7 символов. Второй х +
соответствует ххх. Сбой у, второй х +
уменьшается до хх, а затем х. Теперь
группа может соответствовать второй итерации,
с одним х для каждого х +. Но это
(7,1), (1,1) комбинация тоже терпит неудачу. Так
оно переходит к (6,4), а затем (6,2) (1,1)
а затем (6,1), (2,1) и затем
(6,1), (1,2) и тогда я думаю, что вы начинаете
чтобы получить дрейф.
Если вы попробуете это регулярное выражение для строки 10x
в отладчике RegexBuddy, это займет
2558 шагов, чтобы выяснить окончательный у
пропал, отсутствует. Для строки 11x это
нужно 5118 шагов. За 12 требуется
10238 шагов. Очевидно, у нас есть
экспоненциальная сложность O (2 ^ n) здесь.
В 21x отладчик кланяется в 2.8
миллион шагов, диагностирование плохого случая
катастрофического возврата.
RegexBuddy прощает
обнаруживает, что он идет по кругу , и
прерывает попытку матча. Другие регулярные выражения
движки (например .NET) будут продолжать работать
навсегда , в то время как другие потерпят крах с
переполнение стека (как Perl, перед
версия 5.10). Переполнения стека
особенно неприятно на винде, так как
они имеют тенденцию делать ваше заявление
исчезают без следа или объяснения.
Будьте очень осторожны, если вы запускаете веб
сервис, который позволяет пользователям предоставлять
их собственные регулярные выражения. люди
с небольшим опытом регулярных выражений есть
удивительное умение придумывать
экспоненциально сложный регулярный
выражения.
Полагаю, вам придется обрабатывать это в коде. Я бы посоветовал вам связаться с автором Regexbuddy и спросить, что нужно для обнаружения этого сценария.