【问题标题】:Safely concatenate multibyte strings安全地连接多字节字符串
【发布时间】:2017-07-06 21:10:00
【问题描述】:

我越来越关注确保 PHP 应用程序是多字节安全的,这主要涉及用其等效的 mb_* 函数替换字符串操作函数。

但是字符串连接让我停下来思考。

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

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

【问题讨论】:

  • “PHP 够聪明吗” – 不。正如预期的那样,解决方案是在连接字符串之前从字符串中删除 BOM。
  • 两年零九个月没有具体答案,那么纯 UTF-8 多字节字符串呢?

标签: php string multibyte


【解决方案1】:

PHP 传统上只将字符串视为字节序列

仍然如此。 PHP 没有字符串 的概念,因为它存在于其他语言中。因此,所有字符串始终是字节字符串,您需要手动跟踪其中哪些是二进制字符串,哪些是字符串以及正在使用哪种编码。将 Unicode 字符串引入 PHP 的努力导致了 PHP 6,它被放弃并且从未发布。但是话又说回来,即使是具有本地字符串的语言也不会自动执行您所要求的操作。

看看Unicode FAQ about BOM,下面的一些信息直接来自那里。

如果字节顺序标记出现在字符串的中间,Unicode 规定它应该被解释为零宽度非中断空间。我的结论是,这通常不应该是一个问题,因此忽略 BOM 并没有那么糟糕。

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

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

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

【讨论】:

    猜你喜欢
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    相关资源
    最近更新 更多