Проблеми з відмовою в обслуговуванні
Найпоширеніша проблема, пов'язана з регулярними гексами, - це атака відмови в обслуговуванні через патологічні зразки, що переходять у експоненціальний - або навіть суперекспоненційний! - і так, здається, вічно вирішити. Вони можуть відображатися лише на певних вхідних даних, але загалом можна створити такі, де це не має значення.
Які з них є, залежатиме дещо від того, наскільки розумним буде компілятор регулярних виразів, який ви використовуєте, оскільки деякі з них можна виявити під час компіляції. Компілятори Regex, які реалізують рекурсію, зазвичай мають вбудований лічильник глибини рекурсії для перевірки непрогресування.
Відмінна праця Русса Кокса про збіг регулярних виразів 2007 року може бути простою і швидкою (але у Java, Perl, PHP, Python, Ruby, ...) розповідає про способи, якими більшість сучасних NFA, які, як видається, походять від коду Генрі Спенсера , зазнають серйозної деградації продуктивності, але там, де у НФА у стилі Томпсона таких проблем немає.
Якщо ви визнаєте лише шаблони, які можуть бути вирішені DFA, ви можете скласти їх як такі, і вони працюватимуть швидше, можливо, набагато швидше. Однак для цього потрібен час . У документі Кокса згадується такий підхід та супутні питання. Все зводиться до класичної торгівлі часом-простором.
З DFA ви витрачаєте більше часу на його створення (і виділення більше станів), тоді як з NFA ви витрачаєте більше часу на його виконання, оскільки він може бути одночасно декількома станами, а зворотний трек може з'їсти ваш обід - і ваш процесор.
Рішення про відмову в обслуговуванні
Напевно, найрозумніший спосіб вирішити ці зразки, які втрачають кінець гонки з тепловим смертю Всесвіту, - це обернути їх таймером, який фактично відводить максимальний час, дозволений для їх виконання. Зазвичай це буде набагато, набагато менше, ніж час очікування за замовчуванням, яке надає більшість серверів HTTP.
Існують різні способи їх застосування, починаючи від форми простої alarm(N)
на рівні С, до якогось 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
модулем через модуль дозволив би контролювати видимість простору імен. Інші мови пропонують подібні технології пісочниці. Якщо такі пристрої доступні, ви, можливо, захочете їх вивчити, оскільки вони спеціально розроблені для обмеженого виконання ненадійного коду.