Strcpy
Strcpy 是C语言的函数之一,来自 C语言标准函数库,定义于 string.h,它可以复制以 null 为结束字符的存储器区块到另一个存储器区块内。由于字符串在 C 语言不是首要的资料类型,而是以实现的方式来替代,在存储器内以连续的字节区块组成,strcpy 可以有效复制两个配置在存储器以指针回传的字符串(字符指针或是字符串指针)。
函数原型如下:[1]
#include<string.h>
char *strcpy(char *destination, const char *source);
传回值是 destination
字符数组或是配置在存储器的字符指针(或是字符串指针)。
使用方式与实现
[编辑]例如
char *str1 = malloc(LARGE_NUMBER);
char *str2 = malloc(LARGE_NUMBER);
fgets(str1, LARGE_NUMBER, stdin);
strcpy(str2, str1); /* 這行程式碼類似 str2 "=" str1 */
前两行代码是先配置存储器,经由 malloc 函数把配置完成的存储器地址,传回给 str1 和 str2。到了下一行代码,指向 str1 的存储器,会被用户输入的字符串填满。之后,复制 str1 字符串到 str2 的存储器区块内。虽然 str2 = str1 这个程序叙述可以出现类似的现象,但是它只能复制地址从 str1 到 str2,让 str2 指向 str1 的存储器,实际上也无法真正做到复制字符串的动作。这就是 str1 和 str2 两个指针都指向相同的存储器区块地址。这相当于所谓的 shallow copy(浅复制),因为 str2 实际上没有真正从 str1 复制到字符串,所以这两个指针所指的其实都是同一个的字符串。
strcpy 函数利用循环动作逐次完成复制字符串中每一个字符。在GCC-4.8.0的testsuite中的实现如下:
extern void abort (void);
extern int inside_main;
__attribute__ ((__noinline__))
char *
strcpy (char *d, const char *s)
{
char *r = d;
#if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__
if (inside_main)
abort ();
#endif
while ((*d++ = *s++));
return r;
}
缓存溢出
[编辑]必须注意使用 strcpy 函数,因为如果来源字符串的长度太长,当复制到目的缓冲器时,它会改写到连接目的缓冲器后方的存储器,导致无法预期的结果。而且程序通常容易会出现区段错误(也就是常见的例外现象),但是熟练的骇客会利用缓存溢出来破解进入操作系统(详见电脑安全)。
Bounds checking variants
[编辑]strncpy 这个常见的 bounded variant 它的实现方式与 strcpy 相类似,它只要复制指定的字节个数,而且只要它接近指定的最大长度时,就会在目的缓冲器加上结束字符来结束复制动作。只要指定的字节个数大于目的字符串的长度,它就会因为缓存溢出而受到影响;然而,程序会自动假定来源字符串是以 null 作为结束字符的字符串,当来源字符串的长度大于指定的长度时,它无法保证产生出来的结果是以 null 来作为结束字符的字符串,它也可能出现读取例外的现象。
strlcpy
[编辑]由 OpenBSD 的研发人员 Todd C. Miller 和 Theo de Raadt 两人设计 strlcpy 函数,通常视为是 strncpy 安全版本。对于一些操作系统而言,这个函数会出现被掌控的问题,但是它已经被 glibc 维修人员给特别地删除,所以在此建议使用 memcpy 函数来替代。[2]
strcpy_s
[编辑]strcpy_s
函数是 strcpy
的安全版本,属于 ISO/IEC TR 24731 的标准, [3][4]某些 C 函数库支持这个函数,包含 Microsoft C Runtime Library(微软 C 语言执行时期函数库)。[5] 它与 strcpy
的不同在于,在它获取额外参数来决定目的缓冲器大小时,会因为发生溢出而出现错误,如此一来,就可以预防缓存溢出。由于 strcpy_s
对于 C 语言来说是新的函数,所以没有特别受到广泛支持。
反对Microsoft人士宣称,这个函数连同其他Microsoft在其Runtime Library号称对安全性所做的强化[6]皆为Microsoft试图把开发人员锁死在视窗平台上的手段之一。[7][8];虽然strcpy_s是属于ISO/IEC TR 24731的标准而非Windows独有的标准,且在本质上跟OpenBSD的strlcpy没有差别。
参考资料
[编辑]- ^ 存档副本. [2007-06-11]. (原始内容存档于2007-06-10).
- ^ libc-alpha mailing list (页面存档备份,存于互联网档案馆), selected messages from 8 Aug 2000 thread: 53 (页面存档备份,存于互联网档案馆), 60 (页面存档备份,存于互联网档案馆), 61 (页面存档备份,存于互联网档案馆)
- ^ ISO/IEC. ISO/IEC WDTR 24731 Specification for Secure C Library Functions. 国际标准化组织. 2004.
- ^ Plakosh, Daniel. strcpy_s() and strcat_s(). Pearson Education, Inc. [2006-08-12]. (原始内容存档于2006-09-23).
- ^ Microsoft. Security Enhancements in the CRT. MSDN. [2006-08-12].
- ^ Microsoft. Security Enhancements in the CRT. MSDN. [2008-09-16]. (原始内容存档于2008-09-13).
- ^ Danny Kalev. They're at it again. InformIT. [2008-09-15]. (原始内容存档于2012-01-15).
- ^ Security Enhanced CRT, Safer Than Standard Library?. [2008-09-15]. (原始内容存档于2008-09-19).