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).