C 编程/C 参考/非标准/strlcpy
在计算机编程中,strlcpy 函数旨在用一个安全的版本替换函数strcpy(将字符串复制到目标缓冲区),该安全版本不会溢出目标缓冲区。它几乎总是伴随着strlcat 函数,该函数为strcat(将源字符串追加到目标缓冲区)提供类似的替代方案。
标准 C 函数可以用来避免缓冲区溢出,strncpy和strncat,存在严重的設計缺陷,使得它們难以使用且不必要地慢。strlcpy和strlcat被设计成,尽可能使正确使用变得简单。
这些不是 C 标准库函数,但可以在几个 Unix 操作系统的库中使用,包括 BSD、Mac OS X、Solaris、Android 和 IRIX,显着例外是 Linux 上的 glibc,尽管它可以在libbsd 中使用。
size_t strlcpy(char *destination, const char *source, size_t size);
size_t strlcat(char *destination, const char *source, size_t size);
像strncpy, strlcpy一样,它将目标的大小作为参数,并且不会写入超过该数量的字节,以防止缓冲区溢出(假设size是正确的)。但是,与strncpy, strlcpy 不同,它总是向目标写入单个NUL字节(如果size不为零)。生成的字符串保证以NUL-结尾,即使被截断。另外,它不像NUL那样,浪费时间写入多个字节来填充缓冲区的剩余部分。strncpy.[1]
此外,strlcpy计算并返回整个源字符串的长度(strncpy不返回长度)。这个长度可以与目标缓冲区的大小进行比较,以检查它是否被截断,以及如何绕过截断,例如
char *copy; // this will point at our copy of the string
size_t length; // this will hold the length of the string
// Copy to a fast block of memory on the stack:
char stack_buffer[128];
length = strlcpy(stack_buffer, source, sizeof(stack_buffer));
if (length < sizeof(stack_buffer)) {
// it fit, use the stack buffer
copy = stack_buffer;
} else {
// it was truncated, use a slower buffer on the heap:
copy = malloc(length+1);
if (copy != NULL)
memcpy(copy, source, length+1);
}
// Now use the copy of the string. The length is often useful, too:
use(copy, length);
// free the buffer if we allocated it:
if (copy != stack_buffer) free(copy);
strlcat等效于将追加的字符串写入无限大的临时缓冲区,然后从该缓冲区进行strlcpy到目标。
strlcpy和strlcat由 Todd C. Miller 和 Theo de Raadt 开发,并首次在 OpenBSD 版本 2.4 中实现。后来被许多操作系统采用,包括 FreeBSD (从版本 3.3 开始)、Solaris、Mac OS X 和通过 libbsd 的 GNU 基于系统。许多应用程序包和库包含它们自己的这些函数副本,包括 glib、rsync、Samba、KDE 和 Linux 内核本身。
GNU C 库维护者 Ulrich Drepper 是strlcpy和strlcat函数的批评者之一;[2] 因此,这些函数没有被添加到 glibc 中。Drepper 认为strlcpy和strlcat使程序员更容易忽略截断错误,因此可能会引入比它们消除的错误更多。[2] 他对使用任何涉及静态分配的字符串函数时可能出现的截断的担忧,也为其他人所分享。[3]
Drepper 推荐的替代方案是
*((char *) mempcpy (dst, src, n)) = '\0';
其他批评是,这些函数是非标准的,并且 BSD 和 Solaris 实现之间存在实现差异(strlcat的返回值,当目标缓冲区中没有 NUL 时,会有所不同)。[4]
- ↑ Miller, Todd C.; de Raadt, Theo (1999). "strlcpy and strlcat - consistent, safe, string copy and concatenation". USENIX '99.
- ↑ a b libc-alpha 邮件列表,来自 2000 年 8 月 8 日主题的选定邮件:53,60,61
- ↑ Antill, James. 使用字符串 API 的安全性:在字符串库 API 中查找与安全性相关的事项
- ↑ Antill, James. 使用字符串 API 的安全性
- strlcpy 和 strlcat--一致、安全、字符串复制和串联 - Miller 和 de Raadt 撰写并在 Usenix 99 上发表的一篇论文
- : 大小受限的字符串复制和串联 – OpenBSD 库函数手册
- 开发者博客对strlcpy和mempcpy