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