strncpy的问题与GCC编译期检查的解决方案

用strcpy( )有问题,用strncpy( )还是有问题。

#define PATH_MAX 128

比如:strncpy(file_path, src, PATH_MAX);

strncpy( )容易出现2种问题:1)源串太长,造成没有结束符,引用时有越界乱码现象。 2)字符串长度容易与标称不一致。比如file_path说是最大支持128字符,然而如果把结束符算上,经常只有127。

strncpy源码:当src达到count时,就没有结束符了:

char* strncpy(char* dest, const char* source, size_t count)
{
	char* start=dest;
	while (count && (*dest++=*source++))
		count--;
	if(count)
		while (--count)
			*dest++='\0';
	return(start);
}

一个好的解决方案是:

1.保证字符串长度是标称的长度,不虚标

2.其次不能越界,必须有正确的'\0'结束符

3.能够检查出dst长度必须至少比src长度一个字符

可能的实现如下:使用safe_strncpy(),并且获取dst长度进行安全检查

#define PATH_MAX 128
char file_path[PATH_MAX+1];

比如:safe_strncpy(file_path, src,PATH_MAX+1, PATH_MAX);
int safe_strncpy(char *dst, const char *src, size_t dst_size,size_t str_size)
{
    if(dst_size <= str_size)
        return -1;
    dst[dst_size-1] = '\0';
    return strncpy(dst,src,str_size);
}

这其中的关键这是要保证dst字符串长度要足够。

在运行时检查其实并不是太好,原因的必须测试到这才能发现问题。

更好的方案应该是在编译期间来对dst长度进行安全检查。

GCC编译期检查方案

GCC好像在4.3开始支持编译期断言

 _Static_assert( expr,"msg")

如果代码写错了,dst空间与size相等时,存在无结束符bug应该报错。

如下字体串file_path支持128个字符,但是file_path定义空间也是128,应该定义为129

#define PATH_MAX 128
char file_path[PATH_MAX];

比如:safe_strncpy(file_path, src, PATH_MAX);

使用效果如下:

../include/comm.h:202:5: error: static assertion failed: "strncp small buf size error"
     _Static_assert( sizeof(dst) > size,"strncp small buf size error");\
     ^
cmd_mark.c:137:13: note: in expansion of macro ‘safe_strncpy’
             safe_strncpy(file_path, optarg, OS_PATH_MAX);

代码如下:

#define safe_strncpy(dst,src,size)  \
do { \
    _Static_assert( sizeof(dst) > size,"strncp small buf size error");\
   _safe_strncpy(dst,src,sizeof(dst),size); \
        }while(0)

这样,只要经过编译,就能保证所有调用safe_strncpy()的地方,有足够多的空间。

编译期断言的威力在于能更早发现问题,而不是等到运行时发现。如果有人误用了safe_strncpy(char * ptr, src,SIZE)也会提前发现代码的问题,而不是在运行时,甚至在发布后才发现问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值