Mac OS X和Linux中的安全字符串函数

24

在Mac OSX和Linux中是否有与Windows中的安全字符串函数(如strcpy_s,strncpy_s等)等效的函数?

那么用于多字节和宽字符之间转换的函数呢?


如果使用C ++,请使用syd :: String和字符串缓冲区,而不是这些 - 这些仅适用于C而不是C ++。 - mmmmmm
我也需要操作C字符串。 - Orca
std::string有一个处理C接口的接口:str.c_str()将返回一个char const*,您可以将其传递给C API。 - C. K. Young
我知道,但我需要更多的功能,不仅仅是将const char*发送到函数中。 - Orca
我会使用C++类来更改您代码中的数据,然后将C字符串传递给您调用的代码。 - mmmmmm
OS X自BSD继承了更安全的字符串函数。在Linux上,您可以安装libbsd软件包。Debian软件包是libbsd-dev,而Fedora软件包是libbsd-devel - jww
5个回答

11

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

另一方面,Mac OSX 包含自 BSD 起源的 strlcpystrlcat。在这两个平台上,可以使用 snprintfasprintf 来达到同样的效果:

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实现,在这里找到。如果你的代码将在多个平台上编译,你可以使用预定义库宏来测试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接口最方便地处理字符编码之间的转换。


1
我需要一个简单的 strlcpystrlcat 实现,用于我正在移植到 Linux 的工具,但是这些实现并没有按预期工作;当我使用这个实现时,会出现大量缺失输出。将它们替换为 BSD 实现(http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/)可以产生预期的结果。 - Rob
似乎 OpenBSD 的源代码已经移动了 - 新链接是 http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/ - Neil Smithline
你的替换方式不安全,简直是垃圾。什么鬼???此外,在Linux上有更安全的字符串函数可用。你只需要安装libbsd包即可。Debian包名为libbsd-dev,Fedora包名为libbsd-devel - jww

4

OSX有strlcpystrlcat函数。据我所知,Linux目前没有这些函数,但是可以很容易地从OpenBSD等操作系统中引入这些函数。


1
宽字符转多字节转换怎么样? - Orca
6
在 Unix 环境中使用宽字符并不常见(大多数程序都使用 UTF-8),因此这在很大程度上不是问题。 - C. K. Young

3

1
只有当GCC能够推断出目标缓冲区的大小时,FORTIFY_SOURCE=2才能按照您的期望工作。在许多情况下,它无法推断缓冲区的大小。如果GCC无法推断缓冲区的大小,则原始的不安全函数仍然存在。最好明确地使用“更安全”的字符串函数。 - jww

2
如果您必须使用字符缓冲区(NTBS=以空字符结尾的字节串),那么就没有本质上安全的字符串函数。即使是strlen()也不安全。
相反,存在本质上不安全的字符串函数,例如gets()和大多数sprintf()的用法。这些函数是不安全的,因为您无法可靠地预测所需的缓冲区大小。
另一类字符串函数可以在正确跟踪所使用和所需的最大缓冲区大小的情况下安全使用。
在C++中帮助做到这一点的一种方法是使用Google的RE2包中的StringPiece这样的好类,它是指针和长度,其中指针指向NTBS。通过一次将正确的长度存储到StringPiece中,该类可以跟踪各种操作的长度。您也可以编写这样的类。这样做不会使您的代码正确,但它将隔离关键点(即,正确获取构造函数参数)。
在这种情况下,封装是您的朋友。

2

有标准的C函数可以在多字节字符和宽字符之间进行转换:mbtowc()mbstowcs()wctomb()wcstombs()等。


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