用正则表达式检测带有onclick或onload属性的HTML标签太贪婪了


Regex to detect HTML tags with onclick or onload attributes is too greedy

我有以下用于检查HTML代码的正则表达式:

 /<.+(onclick|onload)[^=>]*=[^>]+>/si

这个正则表达式应该检测HTML中是否有带有onclick或onload属性的标签。它在大多数情况下是这样做的,然而"。部分在大文本上是一个巨大的性能问题(也是一些bug的来源,因为它太贪婪了)。我试着修复它,让它更聪明,但到目前为止失败了——"更聪明"的人错过了一些例子,比如:

<img alt="<script>" src="http://someurl.com/image.jpg"; onload="alert(42)" width="1" height="1"/>

现在,我知道我不应该用正则表达式解析HTML,如果我这样做,就会发生不可言说的恐怖事件。然而,在这种特殊情况下,我不能用适当的代码(例如真正的HTML解析器)替换它。是否仍然有可能修复这个正则表达式或没有办法做到这一点?

我强烈建议你研究regex匹配的替代方案- onclick/load js处理程序代码可能包含任意出现的><作为重写或在js注释中。这也适用于onclick/load处理程序之前或之后的同一元素上的其他js处理程序的代码。包含匹配项的整个标记可能位于HTML注释中(尽管您可能也想匹配这些事件,或者去掉之前的HTML注释)。

然而,已经暗示了可怕的困境,你似乎意识到,标准的免责声明反对'html正则表达式匹配'不完全适用,因为你只需要在标签内匹配。尝试扫描

on(click|load)[[:space:]]*=[[:space:]]*('[^']*'|"[^']*")

,并添加一些逻辑来搜索包含标签的匹配项周围的文本。如果你够勇敢,试试这个:

<(([^'">]+(('[^']*'|"[^"']*")[^'">]+)*)|([^'">]+('[^']*'|"[^"']*"))+)on(click|load)[[:space:]]*=[[:space:]]*('[^']*'|"[^']*")

它匹配标记打开器<和onclick/load-attribute之间的双引号内外的交替文本序列。最外层的选项用于在结束引号和onclick/load-attribute之间没有空格的特殊情况。

希望能有所帮助