安全地连接多字节字符串

6

我越来越关注PHP应用程序的多字节安全性,这主要涉及将字符串操作函数替换为它们的等效mb_*函数。

然而,字符串连接让我有些犹豫。

一些字符编码(如UTF-16 unicode)可能在开头包含一个字节顺序标记。如果您连接了两个UTF16字符串,那么您可能会在结果字符串的其他位置引入BOM。我怀疑还有其他编码也可以包含“头”信息,使得拼接相同编码的两个字符串也成为问题。PHP在进行多字节字符串连接时能够聪明地丢弃BOM等吗?我怀疑不能,因为PHP传统上只将字符串视为字节序列。是否有一个多字节安全的连接等价物?我在mbstring文档中没有找到任何内容。

显然,连接不同编码的字符串永远不安全,所以我现在不用担心。


"PHP够聪明吗" - 不够。正如预期的那样,解决方案是在连接字符串之前修剪BOM。 - deceze
两年九个月,始终没有确切的答案,那么对于普通的UTF-8多字节字符串来说呢? - Anthony Rutledge
1个回答

0
PHP传统上只将字符串视为字节序列。它仍然是这样。PHP没有其他语言中存在的“字符串”概念。因此,所有字符串始终都是字节字符串,您需要手动跟踪哪些是二进制字符串,哪些是字符字符串以及使用哪种编码。尝试将Unicode字符串引入PHP的努力导致了PHP 6的放弃和未发布。但是,即使具有本地字符字符串的语言也不会自动执行您要求的操作。

请查看关于BOM的Unicode FAQ,以下信息直接来自该FAQ。

如果字节顺序标记出现在字符串中间,Unicode规定应将其解释为零宽度非换行空格。我得出结论,这通常不是问题,因此忽略BOM并不可怕。

但是,如果这让您感到困扰,我的建议如下:

  • 尽量避免使用BOM,并相应地标记数据流。例如,在使用HTTP时,可以使用头部将编码设置为UTF-16BEUTF-16LE
  • 尽早对应用程序使用的所有输入(用户输入、加载的文件等)进行清理,删除这些BOM并转换编码。如果可用,甚至可以使用Normalizer类。使用您喜欢的框架功能。
  • 内部只使用一种编码。使用mb_internal_encoding()设置所有mb_*()函数的默认值。
  • 在输出字符串时,如果必须添加任何所需的BOM,则将其添加回字符串中。同样,最好正确标记数据流。

话虽如此,请注意,连接多字节字符串可能会引起许多意外情况,字符串中的BOM只是其中之一。在使用双向文本时也可能会出现问题,其中第一个被连接字符串中的RTL或LTR代码点可能会影响第二个字符串中的文本。此外,使用其他字符串操作也可能会出现许多问题,例如在双向文本上使用mb_substr()也可能产生意外结果。涉及组合变音符号的文本也可能有问题。


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