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

时间:2011-11-26 21:51:07

标签: php html regex

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

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

这个正则表达式应该检测HTML中是否存在带有onclick或onload属性的标记。它在大多数情况下都这样做,但是“。+”部分在大文本上是一个巨大的性能问题(也是一些错误的来源,因为它太贪婪)。我试图修复它并让它变得更聪明但到目前为止失败了 - “更聪明”的人错过了一些这样的例子:

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

现在,我知道我不应该使用正则表达式和unmentionable horrors happen if I do 解析HTML。但是,在这种特殊情况下,我无法用正确的代码替换它(例如真正的HTML解析器)。是否仍然可以修复这个正则表达式,或者没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

我强烈建议您研究正则表达式匹配的替代方法 - onclick / load js处理程序代码可以包含任意出现的><作为relops或js注释。这也适用于onclick / load处理程序之前或之后的同一元素上的其他js处理程序的代码。包含匹配的整个标记可能位于html注释中(尽管您可能也希望匹配这些实例或之前删除html注释)。

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

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

并添加一些逻辑来搜索封闭标记的任何匹配项周围的文本。如果你很勇敢,试试这个:

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

它匹配标记开头<和onclick / load-attribute之间引号对内外的交替文本序列。最外层的替代方案适用于结束报价和onclick / load-attribute之间没有空格的特殊情况。

希望这会有所帮助