Проблемы, связанные с отказом в обслуживании
Наиболее частая проблема с регулярными выражениями - это атака отказа в обслуживании через патологические шаблоны, которые становятся экспоненциальными - или даже суперэкспоненциальными! - и, похоже, на решение уходит вечность. Они могут отображаться только для определенных входных данных, но обычно можно создать такие, в которых это не имеет значения.
Какие из них будут в некоторой степени зависеть от того, насколько умным будет компилятор регулярных выражений, который вы используете, потому что некоторые из них могут быть обнаружены во время компиляции. Компиляторы регулярных выражений, которые реализуют рекурсию, обычно имеют встроенный счетчик глубины рекурсии для проверки отсутствия прогрессии.
Отличная статья Расса Кокса 2007 года о сопоставлении регулярных выражений может быть простым и быстрым (но медленным в Java, Perl, PHP, Python, Ruby и т. Д.) Рассказывает о том, как большинство современных NFA, похоже, происходят из кода Генри Спенсера. , страдают от серьезного снижения производительности, но там, где NFA в стиле Томпсона не имеет таких проблем.
Если вы допускаете только шаблоны, которые могут быть решены с помощью DFA, вы можете скомпилировать их как таковые, и они будут работать быстрее, возможно, намного быстрее. Однако на это нужно время . В статье Кокса упоминается этот подход и связанные с ним проблемы. Все сводится к классическому компромиссу между пространством и временем.
С DFA вы тратите больше времени на его создание (и выделение большего количества состояний), тогда как с NFA вы тратите больше времени на его выполнение, так как это может быть несколько состояний одновременно, а возврат с возвратом может съесть ваш обед - и ваш процессор.
Решения отказа в обслуживании
Вероятно, наиболее разумный способ справиться с этими паттернами, которые находятся на проигрыше в гонке с тепловой смертью вселенной, - это обернуть их таймером, который эффективно устанавливает максимальное количество времени, разрешенное для их выполнения. Обычно это намного меньше тайм-аута по умолчанию, предоставляемого большинством HTTP-серверов.
Существуют различные способы их реализации, начиная от простого alarm(N)
на уровне C и заканчивая своего рода try {}
блокировкой перехвата исключений тревожного типа, вплоть до порождения нового потока, специально созданного с встроенным в него ограничением времени.
Выноски кода
В языках регулярных выражений, которые допускают обозначения кода, должен быть предусмотрен некоторый механизм для разрешения или запрещения их из строки, которую вы собираетесь скомпилировать . Даже если выноски кода предназначены только для кода на языке, который вы используете, вы должны ограничить их; им не обязательно иметь возможность вызывать внешний код, хотя, если они могут, у вас есть гораздо более серьезные проблемы.
Например, в Perl нельзя иметь обозначения кода в регулярных выражениях, созданных путем интерполяции строк (как это было бы, поскольку они компилируются во время выполнения), если use re "eval";
в текущей области не активна специальная прагма с лексической областью видимости.
Таким образом, никто не сможет прокрасться в вызове кода для запуска таких системных программ, как rm -rf *
, например. Поскольку выноски кода очень чувствительны к безопасности, Perl по умолчанию отключает их для всех интерполированных строк, и вам придется изо всех сил, чтобы снова включить их.
Пользовательские \ P {roperties}
Там остается еще одна защиты чувствительной проблемы , связанная со свойствами Unicode-стиль - как \pM
, \p{Pd}
, \p{Pattern_Syntax}
или \p{Script=Greek}
- что может существовать в некоторых регулярных выражениях компиляторов, поддержка, нотация.
Проблема в том, что в некоторых из них набор возможных свойств может быть расширен пользователем. Это означает, что вы можете иметь настраиваемые свойства, которые представляют собой фактические вызовы кода для именованных функций в некотором конкретном пространстве имен, например \p{GoodChars}
или \p{Class::Good_Characters}
. Возможно, стоит посмотреть, как ваш язык обрабатывает их.
Песочница
В Perl изолированное отделение через Safe
модуль дает контроль над видимостью пространства имен. Другие языки предлагают аналогичные технологии песочницы. Если такие устройства доступны, вы можете изучить их, потому что они специально разработаны для ограниченного выполнения ненадежного кода.