字符串拷贝函数的安全问题

strcpy这个函数都知道不安全,有多不安全呢,它的底层实现简化一下大概长这样:

void strcpy(char *dst,const char* src )
{
    while(*dst++ = *src ++);
}

由于不知道dst的长度,一旦dst < src,就会导致缓冲区溢出。非常危险!

然后有个函数叫 memcpy(),它需要提供一个拷贝长度参数,那么memcpy安全吗?

int main()
{
    char src[]="hello,world!111111";
    char dst[12];
    memcpy(dst,src,12);
    cout<<dst<<endl;
    return 0;
}

猜猜会输出什么?
答案:

hello,world!111111

很遗憾,这个好像也不太安全。也许可以改成:

int main()
{
    char src[]="hello,world!111111";
    char dst[12];
    memcpy(dst,src,11);
    cout<<dst<<endl;
    return 0;
}

好像能够正常输出了,但是很遗憾,这样操作的安全性取决于dst[11] 是否是0;如果这样:

int main()
{
    char src[]="hello,world!1111";
    char dst[12];
    dst[11] = 'X';
    memcpy(dst,src,11);
    cout<<dst<<endl;
    return 0;
}

猜会输出什么?
答案:

hello,worldXhello,world!1111 //缓冲区溢出,未定义行为

这又是一个缓冲区溢出的未定义行为。
基于上面,我们可以得出,memcpy函数并不会自动给dst字符串末尾加0;

但是末尾加0真的是我们预期的行为吗,我们只是想copy一个字符串,在目的字符串末尾加0会不会超出使用者的预期,导致编码结果与程序员预期不一样?

int main()
{
    int src[]= {1,2,3,4,5,6,7,8,};
    int dst[100];

    memcpy(dst + 20,src,20);
    for(int i  =20;i < 25;i++)
    {
        cout<<dst[i]<<endl;
    }
    return 0;
}

我用memcpy对数组赋值,如果末尾加0;在以后我要操作时,或许就会出现一些意想不到的情况。

事实上一些所谓安全函数就是在dst字符串末尾加0,来达到所谓得安全。举个例子:
memcpy_s(void *restrict dest, rsize_t dmax, const void *restrict src, rsize_t slen)这个安全函数,会对两个缓冲区的大小,以及各自指针指向的位置是否合法、是否会产生重叠等进行检查。

显然,这些检查会带来更多开销,而且最重要的,即使有这些检查也不能完全保证这个赋值就是安全的。如果传递的参数 max大于了dest缓冲区的长度,照样会出现缓冲区的溢出。

我们会犯这种低级错误吗? 呵呵。程序的世界越低级的错误越难以debug。如果我们能保证传入的dst和src是有效合理的,即使用strcpy也未尝不可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值