在 Javascript 字符串文本中存储 null 字节

Storing null bytes in Javascript string literals

提问人:Timmmm 提问时间:10/31/2023 最后编辑:Timmmm 更新时间:11/13/2023 访问量:74

问:

请考虑以下 HTML:

<!DOCTYPE html>
<html>
    <body>
        <script>
            const a = " ... ";

            for (let i = 0; i < a.length; ++i) {
                console.log(a.charCodeAt(i));
            }
        </script>
    </body>
</html>

其中 in in the 实际上是 ASCII 字符 (0)、(1)、(2)。此文件保存为 UTF-8(唯一有效的 HTML5 编码)。...NULSOHSTX

当我在Firefox或Chrome中打开它时,它会打印以下内容:

32
65533
1
2
32

但是,根据我对规范的阅读,我应该能够存储一个空字节:

StringLiteral ::
    " DoubleStringCharactersopt "
    ' SingleStringCharactersopt '

DoubleStringCharacters ::
    DoubleStringCharacter DoubleStringCharactersopt

DoubleStringCharacter ::
    SourceCharacter but not one of " or \ or LineTerminator
    <LS>
    <PS>
    \ EscapeSequence
    LineContinuation

SourceCharacter ::
    any Unicode code point

在 ECMAScript 语法允许的情况下,从 U+0000 到 U+10FFFF 的所有 Unicode 码位值(包括代理码位)都可能出现在 ECMAScript 源文本中。

那么为什么它不允许我存储一个空字节呢?

(是的,我知道所有的含义,请不要告诉我我不应该这样做。

编辑:需要明确的是,字符串不是.它是这样的:" \x00\x01\x02 "

evil string

JavaScript HTML UTF-8

评论

0赞 Pointy 10/31/2023
你的字符串文字到底是什么样子的?我刚刚制作了一个带有字符代码 0 的字符串,它工作正常。
0赞 somethinghere 10/31/2023
在这种情况下,您确定是 UTF8 吗?因为为 charset 添加一个元通常可以确保这一点,而 CSS 默认不会这样做,所以它不会让我感到惊讶。
0赞 Timmmm 10/31/2023
@somethinghere:我试过添加;没什么区别。<head><meta charset="utf-8"></head>
0赞 Timmmm 10/31/2023
@Pointy 我更新问题;希望它应该澄清一些事情。
1赞 Pointy 10/31/2023
好吧,无论发生什么,显然都与词法分析器如何处理源代码和这些字节有关。JavaScript 字符串(解析后)是 UTF-16,而不是 UTF-8。

答:

0赞 Timmmm 10/31/2023 #1

如果您将 Javascript 移动到外部文件,那么它确实可以正常工作,因此这是 HTML 的限制,而不是 Javascript。.js

显然,HTML 解析器会发出一个意外的 null 字符错误,并忽略它或将其替换为 U+FFFD。

我相信相关状态是脚本数据状态,它明确地将空字节调用为不允许的。

-1赞 AmigoJack 11/13/2023 #2

我不希望文本文件能够携带代码点 NUL (以及其他几个控制字符)。这也与 U+0000 没有可用的命名字符引用(又称实体)一致。这很可能是一种预防措施,以免混淆处理以 NUL 结尾的字符串的(旧)实现。

甚至把你的部分封闭在<里!XHTML 中的 CDATA[ 不允许 U+0000。但话又说回来,XML 本身不允许 U+0000<script>

将 HTML 与 JS 分开是最好的方法,但即便如此,您可能也希望将 JS 与二进制数据分开。将控制字符视为一种做法也是值得怀疑的,因为您不能期望该文本将以哪种编码进行解释 - 最好使用字节数组String

var bytes= new Array( 0, 1, 2 );

评论

0赞 Timmmm 11/14/2023
文本文件可以很好地包含空字符。如果您阅读了我的答案以及其中的链接,则表明出于安全原因,HTML 中明确禁止使用它(有很多 C 代码不能正确处理字符串中的空字节)。
0赞 Timmmm 11/14/2023
“你不能指望用哪种编码来解释该文本”——是的,你可以;唯一有效的 HTML5 字符编码是 UTF-8,您甚至可以使用 meta 标记显式设置它
0赞 AmigoJack 11/14/2023
你为什么得出结论,我没有读过所有这些?文档只规定 - 我想出了一个潜在的原因。我的观点是文本文件中的 NUL 没有意义。不,我的意思是 JS 的内部文本编码,而不是您的文本文件中显而易见的编码 - JS 实现不同,可能使用 UTF-16 或字符串上的任何内容。这就是不将字符串与字节互换的意义所在——只有在 100% 清楚它在引擎盖下是如何工作的时才应该这样做的。另外,请编辑评论,而不是连续发布多个评论 - 这不是聊天。
0赞 Timmmm 11/14/2023
“文档只发号施令”——他们没有;他们提到了安全原因。
0赞 Timmmm 11/14/2023
JS 字符串的编码不是问题。这些始终是 UTF-16(实际上是 WTF-16,但在这种情况下没有区别)。它们可以毫无问题地存储代码点 0-255。