在golang中utf8第二字节下限
我最近正在浏览utf8解码的go源代码。 显然,当解码utf8字节时,第一个字节的值为224 (0xE0)它映射到[0xA0;0xBF]的接受范围。在golang中utf8第二字节下限,go,unicode,utf-8,Go,Unicode,Utf 8,我最近正在浏览utf8解码的go源代码。 显然,当解码utf8字节时,第一个字节的值为224 (0xE0)它映射到[0xA0;0xBF]的接受范围。 如果我正确理解utf8规范(),则每个延续字节的最小值为0x80或1000 0000。为什么0xE0开头字节的最小值更高,即0xA0而不是0x80?如果UTF-8序列的第一个字节是0xE0,这意味着它是一个表示/编码Unicode码点的3字节序列(因为0xE0=1110 0000b) 使用3字节UTF-8序列编码的第一个Unicode码点是U+
如果我正确理解utf8规范(),则每个延续字节的最小值为0x80或1000 0000。为什么0xE0开头字节的最小值更高,即0xA0而不是0x80?如果UTF-8序列的第一个字节是
0xE0
,这意味着它是一个表示/编码Unicode码点的3字节序列(因为0xE0=1110 0000b
)
使用3字节UTF-8序列编码的第一个Unicode码点是U+0800,因此该码点是0x0800
,二进制:0000 1000 0000
如果您试图将这些位插入标有x
的位中:
1110xxxx 10xxxxxx 10xxxxxx
11110000 10100000 10000000
如您所见,第二个字节是
1010 0000
,它是0xa0
。因此,以0xe0
开头的有效UTF-8序列:其第二个字节不能低于0xa0
(因为即使是UTF-8编码序列以0xe0
开头的最低Unicode码点也有第二个字节0xa0
)。原因是为了防止所谓的超长序列。引用RFC:
上述解码算法的实现必须防止
解码无效序列。例如,一个简单的实现可能会
将过长的UTF-8序列C080解码为字符U+0000,
或者替代项对ED A1 8C ED B4到U+233B4。解码
无效序列可能会产生安全后果或导致其他后果
问题
[……]
这种攻击的一种特别微妙的形式可以针对
一种解析器,它对
UTF-8编码其输入的形式,但解释某些非法的八位字节
序列作为字符。例如,解析器可能会禁止
编码为单个八位字节序列00时的NUL字符,但
错误地允许非法的两个八位组序列C080并解释
它是一个NUL字符。另一个例子可能是一个解析器
禁止八位组序列2F 2E 2E 2F(“///”),但允许
非法八位组序列2F C0 AE 2E 2F。这最后一次攻击已经成功
事实上,它被广泛应用于攻击中国网络服务器的病毒中
2001; 因此,安全威胁是非常真实的
还要注意第4节中的语法规则,其中明确地只允许E0之后的字符A0-BF:
UTF8-2=%xC2 DF UTF8尾部
UTF8-3=%xE0%xA0 BF UTF8尾/%xE1 EC 2(UTF8尾)/
%X%x80-9F UTF8尾部/%xEE EF 2(UTF8尾部)
UTF8-4=%xF0%x90 BF 2(UTF8尾部)/%xF1-F3 3(UTF8尾部)/
%xF4%x80-8F 2(UTF8尾部)
1110xxxx 10xxxxxx 10xxxxxx
11110000 10100000 10000000
UTF8-2 = %xC2-DF UTF8-tail
UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
%xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
%xF4 %x80-8F 2( UTF8-tail )