您的位置:首页 > 其它

string.h里面几个安全函数的比较snprintf strncpy strncat

2012-07-05 00:00 381 查看
在字符串处理过程中会常用到以下几个函数
strcpy() sprintf() strcat()
但它们都存在一定的安全隐患,相对应用的安全版本为:
strncpy() snprintf() strncat()

int sprintf( char *buffer, const char *format, [ argument] … ) ;
int snprintf(char *str, size_t size, const char *format, ...);

此两函数功能:把格式化的数据写入某个字符串.
返回值:字符串长度( strlen )

首先让我们来看下 sprintf()函数
Example
/* sprintf example */
#include <stdio.h>

int main (int argc, char *argv[])
{
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a %d char long string\n",buffer,n);
return 0;
}
Example Output:
[5 plus 3 is 8] is a 13 char long string

关于 sprintf() 不安全问题,主要由其参数决定,
(1) 缓冲区溢出,char *buffer多大多小难以预测.
(2) printf习惯造成的忘记第一个参数
(3) 参数对应问题,相对容易检查

snprintf();
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n的话,是不会溢出。
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
#include <stdio.h>

int main()
{
char str[10]={0,};
snprintf(str, sizeof(str), "0123456789012345678");	//如果使用sprintf()将会出错
printf("str=%s\n", str);
//snprintf(str, 18, "0123456789012345678");		//也能成功,但是不推荐使用
printf("str=%s\n", str);
return 0;
}
Example Output:
str=123456789
str=12345678901234567

提到sprintf()不得不说到在格式化时间的时候还有 sprintf 的孪生兄弟 strftime.
size_t strftime ( char * ptr, size_t maxsize, const char * format, const struct tm * timeptr );
Example:
/* strftime example */
#include <stdio.h>
#include <time.h>

int main (int argc, char *argv[])
{
time_t rawtime;
struct tm * timeinfo;
char buffer [80];

time (&rawtime);
timeinfo = localtime ( &rawtime );

strftime(buffer,80,"Now it's %Y%m%d%H%M%S",timeinfo);
puts(buffer);

return 0;
}
Example output:
Now it's 20120701170808

extern char *strcat(char *dest,char *src);
函数说明:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'.
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.
函数返回值:返回指向dest的指针。

extern char *strncat(char *dest,char *src,size_t n);
函数说明:把src所指字符串前n个字符添加添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'.
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串.
函数返回值:返回指向dest的指针。

char* strncat(char *dest,char *src,size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0; i < n && src[i] != '\0' ; i++ )
{
dest[dest_len + i] = src[i];
}
dest[dest_len + i] = '\0';

return dest;
}

char *strcat(char *strDest, const char *strSrc)
{
char *address = strDest;
assert((strDest != NULL) && (strSrc != NULL));
while(*strDest)
{
strDest++;
}
while(*strDest++ = *strSrc++)
{
NULL;
}
return address;
}

char *strcpy(char *dest, char *src);
char *strncpy(char *dest, char *src, size_t n);

strcpy只用来拷贝字符串,它遇到'\0'就结束拷贝。
strncpy将字符串src中最多n个字符复制到字符数组dest中,与strcpy不同只有遇到NULL才停止复制
而是多了一个条件停止,就是说如果复制到第n个字符还未遇到NULL,也停止,返回指向dest的指针
但是如n>strlen(dest)的长度,dest栈空间溢出产生崩溃异常
char *strcpy(char *dest, const char *src)
{
char *p = dest;

while (*src)
*dest++ = *src++;

*dest = '/0';
return p;
}
strncpy 标准用法
strncpy(path,src,sizeof(path)-1);
path[sizeof(path)-1] = '\0';
len = strlen(path);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: