Unicode UTF-8相对于ASCII字符如何安全

Unicode UTF-8相对于ASCII字符如何安全,unicode,utf-8,character-encoding,ascii,Unicode,Utf 8,Character Encoding,Ascii,我在维基百科上读到了以下内容: "Since ASCII bytes do not occur when encoding non-ASCII code points into UTF-8, UTF-8 is safe to use within most programming and document languages that interpret certain ASCII characters in a special way, such as "/" in filenames,

我在维基百科上读到了以下内容:

"Since ASCII bytes do not occur when encoding non-ASCII code points into UTF-8, 
UTF-8 is safe to use within most programming and document languages that 
interpret certain ASCII characters in a special way, such as "/" in filenames, 
"\" in escape sequences, and "%" in printf."

我不明白的是,即使发生了,这怎么会成为一个问题。如果处理字节的应用程序支持utf-8,那么这是一种简单的情况,不会有问题,因为它知道如何在其他前置/后续字节的上下文中解释它们。如果它不这样做,那么它就没有必要首先处理它,而且它可能会遇到像“\”这样的格式字符组合,这一事实并不比首先处理它更有害。

以PHP为例。PHP对编码没有本地的理解,这里有一些星号和脚注,但我们可以说它没有。它在源代码中寻找某些特定的字节,这些字节对它来说意味着什么,并且大多数情况下只传递其他没有特定含义的字节。例如:

$foo=bar$baz 42; 这会触发字符串插值;PHP将尝试在这个字符串中插入变量$baz。它通过查找字节0x24 ASCII$和字符串中的下一个非单词字节来实现这一点,从而在字符串中找到变量名$baz。字符串中的任何其他内容都会按原样通过

您可以在PHP上执行此操作:

回响意味分からない; PHP在这里看到的只是一些二进制blob,它对此不感兴趣。它不支持或理解这些字符,但也不试图对它们做任何事情。它只是按原样传递二进制数据,从而碰巧输出所需的日语句子

现在,如果我们用一些非ASCII安全编码(比如ISO-2022-JP-3)来写这句话,那将是:

1b24 4230 554c 234a 2c24 2b24 6924 4a24 241b 2842
你会注意到里面有24个字节。如果您可以生成一个有效的PHP文件,其中包含双引号之间的这些字节,PHP将尝试将这些0x24字节解释为$,并尝试在其中插入变量

$cat/tmp/foo.php
以PHP为例。PHP对编码没有本地的理解,这里有一些星号和脚注,但我们可以说它没有。它在源代码中寻找某些特定的字节,这些字节对它来说意味着什么,并且大多数情况下只传递其他没有特定含义的字节。例如:

$foo=bar$baz 42; 这会触发字符串插值;PHP将尝试在这个字符串中插入变量$baz。它通过查找字节0x24 ASCII$和字符串中的下一个非单词字节来实现这一点,从而在字符串中找到变量名$baz。字符串中的任何其他内容都会按原样通过

您可以在PHP上执行此操作:

回响意味分からない; PHP在这里看到的只是一些二进制blob,它对此不感兴趣。它不支持或理解这些字符,但也不试图对它们做任何事情。它只是按原样传递二进制数据,从而碰巧输出所需的日语句子

现在,如果我们用一些非ASCII安全编码(比如ISO-2022-JP-3)来写这句话,那将是:

1b24 4230 554c 234a 2c24 2b24 6924 4a24 241b 2842
你会注意到里面有24个字节。如果您可以生成一个有效的PHP文件,其中包含双引号之间的这些字节,PHP将尝试将这些0x24字节解释为$,并尝试在其中插入变量

$cat/tmp/foo.php
那很有趣。可能需要注意的是,根据定义,对ASCII范围0-127之外的Unicode字符进行编码的UTF-8序列中的所有字节都完全由大于或等于128的字节组成,因此不可能在UTF-8编码的文件中的其他地方出现游离的24。确切地说,这就是UTF-8 ASCII兼容的原因……重读这个问题,我发现这里已经提到了这一点:我理解UTF-8是如何实现ASCII安全的机制,但我无法想象的是,在这样一种情况下,情况可能并非如此,即一种理解Unicode、包含ASCII但不支持ASCII的编码。假设utf-8在编码其他非ascii码点时产生类似ascii的字节,那么处理解码算法自然会知道如何从角度解释这些字节,而不会将它们混淆为不同的ASCI。如果它产生了ASCII八位字节,就必须有一些逻辑来区分它们并正确解释它们@正如我试图证明的那样,有些天真的系统不解码任何东西。它们查找特定的字节序列,而忽略其他任何内容。他们只知道ASCII或ASCII兼容编码,根本不需要从透视图中解释。它们只是字节,这些字节在很久以前就已经被神决定了,你只需要寻找那些对你有意义的字节,你可以忽略其他任何东西。或者说这些系统的咒语是这样的。这很有趣。可能需要注意的是,根据定义,UTF-8序列中的所有字节都编码Unicode字符
ASCII范围0-127之外的字符完全由大于或等于128的字节组成,因此不可能在UTF-8编码文件的其他地方出现游离的24。确切地说,这就是UTF-8 ASCII兼容的原因……重新阅读问题,我看到这里已经提到了这一点:我理解utf-8是如何实现ascii安全的机制,但我无法想象的是,在这样的环境中,情况可能并非如此,即,一种理解Unicode(包括ascii)但不支持ascii安全的编码。假设utf-8在编码其他非ascii码点时产生类似ascii的字节,那么处理解码算法自然会知道如何从角度解释这些字节,而不会将它们混淆为不同的ASCI。如果它产生了ASCII八位字节,就必须有一些逻辑来区分它们并正确解释它们@正如我试图证明的那样,有些天真的系统不解码任何东西。它们查找特定的字节序列,而忽略其他任何内容。他们只知道ASCII或ASCII兼容编码,根本不需要从透视图中解释。它们只是字节,这些字节在很久以前就已经被神决定了,你只需要寻找那些对你有意义的字节,你可以忽略其他任何东西。或者说这些系统的咒语是这样的。