变量字符串导致浏览器崩溃

8

我发现了一些非常奇怪的事情。当你在 HTML 页面中放置类似这样的内容时,浏览器(在 FF 和 Chrome 上测试过)会在此处停止渲染页面:

        <script type="text/javascript">
        // var Crash = "<!--<SCRIPT>";
        </script>

显然,您也可以执行以下操作:
        <script type="text/javascript">
        var Crash = "<!--<SCRIPT>";
        </script>

或者:

        <script type="text/javascript">
         var Crash = "<!-- WHATEVER YOU WANT HERE <SCRIPT>";
        </script>

有什么想法,这是为什么发生的?

这是因为在HTML中<!--用于注释,但它从未关闭,所以它后面的任何内容都将被视为注释。如果您在页面下方添加另一个脚本标签,但使用var Crash = "WHATEVER YOU WANT HERE <SCRIPT>-->";,您会发现这结束了注释,并且之后的任何内容都将显示在浏览器中。 - NewToJS
当你只是这样做时,页面仍然可以工作。请查看此链接:https://jsfiddle.net/7td2nqcp/1/。请记住,浏览器确实会在那里停止执行任何操作。因此,这真的很糟糕。 - Simon Siegenthaler
我认为你不理解我的意思。<!--将注释掉任何文本/HTML/数据,直到使用-->关闭。请参见https://jsfiddle.net/7td2nqcp/2/和https://jsfiddle.net/7td2nqcp/3/。 - NewToJS
2
有趣的问题。我知道在脚本块中不能使用字面字符串“</script>”,因为浏览器解析器会将其视为脚本块的结尾。似乎注释的开头和<script>标签的组合也会引起问题。需要深入研究规范以找出原因。 - James Thorpe
@SimonSiegenthaler 哦,没错,我不是在说这是同样的问题 - 只是想说我知道还有其他不能使用的字符串。我现在正在规范的相关部分,只是试图跟进它(它会跳来跳去)。 - James Thorpe
显示剩余4条评论
2个回答

7

简而言之:

不要这样做——这会让解析器遵循一些奇怪的规则来双重转义脚本数据,使其在到达 </script> 时处于"错误"的状态(从您的角度来看)。有方法可以转义脚本数据,以确保它将按您希望的方式运行,而不会破坏解析器。


解析器在解析页面时遵循严格的规则。在这种情况下:

我们从看到开头的<script>标签开始,在: 脚本数据状态
在这个阶段,<触发: 脚本数据小于号状态
然后,!触发: 脚本数据转义开始状态
接着,-触发: 脚本数据转义开始破折号状态
然后,-触发: 脚本数据已转义破折号破折号状态
然后,<(立即或在“脚本数据已转义状态”中)触发: 脚本数据已转义小于号状态
然后,任何a-z或A-Z(即“SCRIPT”中的“S”)都将存储在“临时缓冲区”中,并且我们进入: 脚本数据双转义开始状态。我们将停留在此状态直到script结束,然后使用临时缓冲区与>组合相等触发: 脚本数据双转义状态
这只是持续发出字符(在您的情况下),直到我们到达</script><,这会触发: 脚本数据双转义小于号状态</script>中的/然后清除临时缓冲区,我们切换到: 脚本数据双转义结束状态。这再次将字符附加到临时缓冲区,直到我们看到>,此时临时缓冲区等于“script”,这将触发我们进入: 脚本数据已转义状态

现在浏览器认为它仍处于一些转义的脚本数据中,而不是原始的<script>标签已经关闭,因此任何进一步的HTML都不会被视为HTML - 它仍然认为它是要交给脚本引擎处理的脚本数据,而不是HTML。

解析器采用这种工作方式的原因并不清楚,但随着时间的推移,可能是由于一些可怕的向后兼容性原因。


3
过去,常见的处理浏览器无法识别脚本标签的方法是在脚本块中添加HTML注释:
<script language="javascript">
<!--
   // code here
//-->
</script>

正如您所看到的,javascript中的第一个<!--是无效的,但浏览器仍然需要忽略它以兼容这个老技巧。当我们添加一个<script>时,这似乎会触发某些浏览器中的奇怪行为,就像您在这个fiddle中看到的:https://jsfiddle.net/bjeLh5Ln/ 因此,在您的脚本中,您需要通过添加// -->来关闭html注释,或者将</script>放两次。

这看起来很有趣! - Simon Siegenthaler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接