现在的位置: 首页 > 综合 > 正文

strcpy与strncpy的安全版本

2013年09月16日 ⁄ 综合 ⁄ 共 937字 ⁄ 字号 评论关闭

char* src = new char[10];

memset(src, 1, 10);

char* dest = new char[20];

strcpy(dest, src);

在这个例子中,我们不容易发现strcpy这个语句中有Bug。因为src没有休止符。

目前公司的做法是采用codescan工具找出strcpy,并使用strncpy代替。但实际上,这种方法也不是安全的做法。strcpy之所以不安全是由于接口本身的bug,strncpy可以再某种程度上避免strcpy所带来的缺陷。但strncpy任然不是安全的。因为有可能出现目标指针的字节数不足存放源指针所指向的内容。

如:

char* src = "hello world!";

char* dest = new char[10];

strncpy(dest, src, strlen(src)); // 这里有bug

目前对于strcpy,strncpy,从VS2005开始已经推出相应的安全版本:

接口的定义改变如下:

char* strcpy(char* dest, const char* src) --> errno_t strcpy_s(char* dest,
size_t numElems, const char* src)

char* strcpy(char* dest, const char* src, size_t count) --> errno_t
strcpy_s(char* dest, size_t numElems, const char* src, size_t count)

后者之所以比前者安全,是因为他们在接口增加了一个参数numElems来表明dest中的字节数,防止目标指针dest中的空间不够而导致出现Bug,同时返回值改成返回错误代码,而不是为了一些所谓的方便而返回char*。这样接口的定义就比原来安全很多。

所以我们应该把strcpy改成strncpy_s。这样会更为安全。

最后总结下:

接口的定义往往很重要。但同时也有一些相应的规范。如:

1)在接口中,如果出现需要修改的目标指针,需要增加相应的可存放字节数。

2)接口一般返回int(errno_t实际上就是int),这样可以标志返回错误类型。(注:在使用异常的环境下则不同,一般不返回。还有在一些比较特殊的情况下直接返回我们想要的类型。)

抱歉!评论已关闭.