Is std::regex safe for user-defined expressions?
使用EDCOX1(0)的用户定义表达式(如服务器端搜索)是否安全?标准库是否保证了被破坏的表达式的安全?
基本上不行,不安全。完全合法的正则表达式可以被制作出来,计算时间非常长,导致拒绝服务。
来自维基百科的Redos
The regular expression denial of service (ReDoS)[1] is an algorithmic complexity attack that produces a denial-of-service by providing a regular expression that takes a very long time to evaluate. The attack exploits the fact that most regular expression implementations have exponential time worst case complexity: the time taken can grow exponentially in relation to input size. An attacker can thus cause a program to spend an unbounded amount of time processing by providing such a regular expression, either slowing down or becoming unresponsive.
标准要求,当传递的regex无效时,实现将引发错误。
[regex.construct-3]:
1 explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript);Requires:
p shall not be a null pointer.Throws:
regex_-error ifp is not a valid regular expression.Effects: Constructs an object of class basic_-regex; the object's internal finite state machine is constructed from the regular expression contained in the array of
charT of lengthchar_-traits whose first element is designated by::?length(p) p , and interpreted according to the flagsf .Ensures:
flags() returnsf .mark_-count() returns the number of marked sub-expressions within the expression.
甚至还有一张表格详细说明了各种可能的错误。
因此,只要不传递空指针,就不应在从用户提供的字符串创建regex时出现未定义的行为。
请注意,任何实际的实现可能仍然有可能导致安全漏洞的错误。这个标准也显然不能保证恶意用户无法通过提交一个非常复杂/自引用的regex来完成系统任务,因为该regex产生了太多的匹配项,使用了太多的内存/cpu等,所以您必须自己考虑。但是如果你只是担心一个无效的regex是否可以自由地引导到ub,答案是"不,你很好"。
C++标准定义了正确行为的含义。即使在抛出异常的函数的情况下,标准也定义了哪些函数抛出,哪些异常将被抛出,以及在什么情况下会导致抛出这些异常。此类代码具有标准定义良好的行为。
如果一个实现正在对标准定义的行为进行操作(即:是"中断的"),则标准不会也不能指定会发生什么。如果标准要定义这样的行为,那么根据定义,实现不会违背标准。所以它们不会再被"破坏"。
因此,regex实现是否能够避免由外部提供的字符串引起的病理行为,而您没有对这些字符串进行清理,这是实现质量的问题,而不是标准定义的行为。