【问题标题】:Safe String Functions In Mac OS X and LinuxMac OS X 和 Linux 中的安全字符串函数
【发布时间】:2011-06-01 23:49:18
【问题描述】:

Mac OSX 和 Linux 中是否有与 Windows 中相同的安全字符串函数(strcpy_s、strncpy_s..etc)?

在多字节字符和宽字符之间转换的函数呢?

【问题讨论】:

  • 如果使用 C++ 使用 syd::String 和字符串缓冲区而不是这些 - thesw 应该只用于 C 而不是 C++
  • 我也需要对C字符串进行操作。
  • std::string 有一个用于处理 C 接口的接口:str.c_str() 将返回一个 char const*,您可以将其传递给 C API。
  • 我知道,但我需要的功能不仅仅是向函数发送 const char*。
  • 我会使用 C++ 类更改代码中的数据,然后将 C 字符串传递给您调用的代码。

标签: c++ windows linux security macos


【解决方案1】:

安全字符串操作有两种策略。 Linux / glibc 的维护者拒绝添加安全函数,认为您应该保留字符串的长度并使用 memcpy

另一方面,Mac OSX 包含来自 BSD 的 strlcpystrlcatsnprintfasprintf 可以在两个平台上使用,效果大致相同:

size_t strlcpy(char *d, char const *s, size_t n)
{
    return snprintf(d, n, "%s", s);
}

size_t strlcat(char *d, char const *s, size_t n)
{
    return snprintf(d, n, "%s%s", d, s);
}

您也可以考虑使用 BSD 实现 found here。如果您的代码将在多个平台上编译,您可以使用pre-defined library macros 测试是否存在 glibc:

#if defined __GNU_LIBRARY__ || defined __GLIBC__

    size_t strlcpy(char *, char const *, size_t);
    size_t strlcat(char *, char const *, size_t);

#endif 

使用iconv 接口最容易处理字符编码之间的转换。

【讨论】:

  • 我需要一个简单的 strlcpystrlcat 实现,用于我要移植到 Linux 的工具,但是 这些不能按预期工作;当我切换到这个实现时,我得到了大量的缺失输出。用 BSD 实现 (openbsd.org/cgi-bin/cvsweb/src/lib/libc/string) 替换它们会产生预期的结果。
  • OpenBSD 源代码似乎已经移动 - 新链接是 cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string
  • 你的替代品是不安全的垃圾。怎么回事???此外,Linux 上还提供了更安全的字符串函数。你只需要安装libbsd 包。 Debian 包是libbsd-dev,Fedora 包是libbsd-devel
【解决方案2】:

OSX 有strlcpystrlcat。据我所知,Linux 目前还没有这些功能,但很容易从 OpenBSD 等平台引入这些功能。

【讨论】:

  • 宽字符到多字节的转换呢?
  • @Voulnet:在 Unix 世界中使用宽字符并不常见(大多数程序使用 UTF-8 代替),因此在大多数情况下这不是问题。
【解决方案3】:

您可以使用 gcc 的 -D_FORTIFY_SOURCE=2 选项,对于 Linux,您可以更高级,为此您应该阅读 Secure Programming with gcc & glibc

【讨论】:

  • FORTIFY_SOURCE=2 只会在 GCC 可以推断出目标缓冲区大小的情况下按您希望的方式工作。在许多情况下它不能。如果 GCC 无法推断出缓冲区大小,则保留原来的不安全函数。最好明确使用“更安全”的字符串函数。
【解决方案4】:

如果您必须使用字符缓冲区(NTBS=Nul 终止的字节字符串),则有 no 本质上安全的字符串函数。甚至 strlen() 都不安全。

相反,存在本质上的不安全字符串函数,例如gets() 和sprintf() 的大多数用法。这些是不安全的,因为您无法可靠地预测所需的缓冲区大小。

如果您跟踪正确使用和要求的最大缓冲区大小,则可以安全地使用其他类别的字符串函数

在 C++ 中帮助做到这一点的一种方法是使用一个不错的类,例如 Google 的 RE2 包中的 StringPiece,它是一个指针和长度,其中指针指向 NTBS。通过一次将正确的长度存储到 StringPiece 中,该类可以跟踪各种操作的长度。你可以自己写这样一个类。这样做不会使您的代码正确,但会隔离关键点(即正确获取构造函数的参数)。

在这种情况下,封装是你的朋友。

【讨论】:

    【解决方案5】:

    提供在多字节和宽字符之间转换的标准 C 函数:mbtowc()mbstowcs()wctomb()wcstombs() 等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 2011-11-29
      • 2013-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多