sprintf 使用不当越界修改内存

sprintf “%02X” 导致越界修改内存

使用sprintf 中二进制转换16进制(“%02X”)时,传入参数要在char型的范围内;同理,在做其他的转换时,对应的参数要在合理的范围内,否则可能发生内存的改写,影响附近内存块的数据安全。


前言

二进制转换为16进制字符串表示时,1 Byte 的二进制需要2 Byte的char型存储空间。C语言中,二进制转换为16进制,一般采用类似下面这样的语句:

 ...
unsigned char chbuf[4] ={0};
int a =23534;
memcpy(chbuf,&a,4);
char hexStr[9]={0};

/*转换*/
for(int i=0; i<4; i++)
{
    sprintf(hexStr+i*2,"%02X",chbuf[i]);
}

//输出
 ...

这时,在sprintf中, “%02X” 对应的参数应为1Byte的数据类型变量(如:unsigned char)。

发现问题

如果将上面的sprintf中, “%02X” 对应的参数应为1Byte的数据类型变量,传入一个存储空间大于1Byte类型的变量(如:int),会怎么样呢?

事实是,传入int类型也是可以的,如传入一个叫 iValue的变量,只有当0< iValue <255 时,转换后存储空间存入数据正常;

下图是一个错误的内存信息(其中一次转换的结果):
这里写图片描述

从调试信息可以看出,在temp等于 -28 时,一次转换后buf里的内存有8Byte都被改写了(图中内存 红色 数字为本次内存被修改的数据)。正常时一次buf里写入2Byte数据,也就是说有6Byte内存空间被意外改写。

测试确认

下面为用VS2010环境里写的测试该问题的小程序(用随机数生成UUID):

#include<iostream>
#include <ctime>
using namespace std;

int main(){

    unsigned char buf1[4] ={0};
    int a =23534;
    memcpy(buf1,&a,4);

    char buf[33]={0};
    char bufStr[10]={0};

    srand(time(0));
    int temp;
    //越界测试
    for (int num = 0; ;num++)
    {
        for (int i =0;i<16;i++)
        {
            /*正确用法*/
            //sprintf(bufStr+i*2,"%02X",buf1[i]);

            /*传参值大于“%02X”的合理值 会导致越界写数据*/
            //范围控制不当
            //temp = (1+(int)(300.0*rand()/(RAND_MAX+2.0)));
            //temp = (1+(int)(300.0*rand()/(RAND_MAX+2.0)))-150;
            temp = 1+(int)(300.0*rand());
            sprintf((buf + i*2),"%02X",temp );

            //范围控制正确
            //sprintf((buf + i*2),"%02X", (1+(int)(255.0*rand()/(RAND_MAX+2.0))));

        }
        int len =strlen(buf);
        if (len>32)
        {
            std::cout<<"NO"<< num <<": 越界(" << len << ") -> \t"<<buf<<std::endl;
            buf[32]='\0';
            std::cout<<"NO"<< num <<": 字符串修正) -> \t"<<buf<<std::endl;
            system("pause");
            std::cout<<std::endl;
        }
    }   
}

部分结果截图:

1)数值有概率性的超出范围:
概率性的超出范围
2)数值直接超出范围:
每次都超出范围

结论

使用sprintf 中二进制转换16进制(“%02X”)时,传入参数要在char型的范围内;同理,在做其他的转换时,对应的参数要在合理的范围内,否则可能发生内存的改写,影响附近内存块的数据安全。


快速导航 >>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值