您的位置:首页 > 运维架构 > Linux

推理 arm-linux-gcc/g++ v3.4.1 版本的一个漏洞

2013-05-23 17:54 267 查看
     如下是自己在开发项目的时候遇到的一个问题,并简单地记录下来。讲解的思路不是很连贯,但是,其中有给出一个例子,该例子推理出了问题的所在。

 

问题的引出

       在开发项目的时候,下位机把一包事件发送给上位机,那么,自己调试,在发送数据包的时候,把事件给显示出来,有如下的逻辑:

typedef
unsigned char INT8U;
typedef
unsigned long long INT64U;
 
struct _EVENT
{
    INT64U cardid;    //结构体中有这个数据
    .....
};
 
INT8U buf[1204];  //存放事件包的缓存
 
memcpy(buf, .....);  //把事件包存放到 buf[]
缓存中
 
void show_card_info(INT8U *buf, INT16U count)
//显示缓存信息
{
    Event *e = (Event*)buf;  //把 buf
缓存强制转换为 Event* 类型
 
    printf("e->cardid = %llu \n", e->cardid);
    .....
}

最终,运行程序发现:

1 cardid 变量中 8
个字节存放的数据是正确的,但是,使用 printf();
输出的时候,却是错误的。

2 假如 cardid
中 8 个字节的数据是 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88,而在 cardid
前面的 2 个字节是 0x1A, 0x1B
的话,那么,printf(); 输出的 carid
值是:0x1A, 0x1B , 0x11, 0x22, 0x33, 0x44, 0x55, 0x66
这样的数据组织成的值。

就是说,cardid
的数值是 buf[ ] 中给 Event*e
引用的时候,会引用其前面的2 个字节。

注意:这种情况是在如下的 arm-linux-gcc/g++
编译器中出现:

[weikaifeng@weikaifeng test]$ arm-linux-gcc -v

……

gcc version 3.4.1

在Fedora14
系统自带的 GCC 编译器中,没有出现这种情况。

如下是一个测试的例子:

typedef
unsigned char INT8U;
typedef
unsigned long long INT64U;
 
struct _TEST
{
    INT64U id;
};
 
typedef
struct _TEST test;
 
void func(INT8U* buf)
{
    int i = 0;
    INT8U *p = NULL;
    INT64U id = 0;
    INT64U p_id = 0;
 
    test *t = (test*)buf;
 
    printf("t->id = %llu \n", t->id);
 
    printf("buf = ");
//显示传递进来的 buf[] 值
    for(i = 0; i < 8; i++)
    {
       printf("%2x ", buf[i]);
    }
    printf("\n");
    //计算 buf[]
存放的 id 数据
    for(i = 7; i >= 0; i--)
    {
       id = id*256 + buf[i];
    }
    printf("id = %llu \n", id);
 
    //显示 t->id
的内存数据
    p = (INT8U*)&(t->id);
    printf("p = ");
    for(i = 0; i < 8; i++)
    {
       printf("%2x ", *p);
       p++;
    }
    printf("\n");
    printf("t->id = %llu \n", t->id);
 
    //把 t->id
赋给一个变量,再次显示这个变量中 内存数据,发现与 t->id 的实际内存不一样
    //而是 main();
函数中定义的整个 buf[] 是一样的。
    //所以,可以推论 使用 printf();
输出 t->id 的时候,引导到了 buf[2] 的前 2 个数据
    p_id = t->id;
    printf("p_id = %llu \n", p_id);
 
    p = (INT8U*)&p_id;
    printf("p = ");
    for(i = 0; i < 8; i++)
    {
       printf("%2x ", *p);
       p++;
    }
    printf("\n");
}
 
int main(void)
{
    int i = 0;
    INT64U id = 8868;
    INT8U buf[10];
 
    buf[0] = 0x01;
    buf[1] = 0x02;
 
    for(i = 0; i < 8; i++)
    {
       buf[i + 2] = id % 256;
       id = id / 256;
    }
 
    printf("buf = ");
    for(i = 0; i < 10; i++)
    {
       printf("%2x ", buf[i]);
    }
    printf("\n");
 
 
    func(&buf[2]);    //注意,传的只是从 buf[2]
开始,为了测试在 func(); 函数中是否引用到 buf[2] 前面的 2 个字节
 
    printf("\nhehe.....\n");
    return 0;
}
在 Fedora14
系统自带的 GCC 编译环境中编译运行的结果如下:

[weikaifeng@weikaifeng test]$ ./test

buf =  1  2 a4 22  0  0  0  0  0  0

t->id = 8868

buf = a4 22  0  0  0  0  0  0

id = 8868

p = a4 22  0  0  0  0  0  0

t->id = 8868

p_id = 8868

p = a4 22  0  0  0  0  0  0

hehe.....

结果是完全正确的,如果使用 arm-linux-gcc v3.4.1
版本的编译器编译,然后,下载到ARM板上运行,得到的结果如下:

dig ~# ./arm_test

buf =  1  2 a4 22  0  0  0  0  0  0

t->id = 581173761

buf = a4 22  0  0  0  0  0  0

id = 8868

p = a4 22  0  0  0  0  0  0

t->id = 581173761

p_id = 581173761

p =  1  2 a4 22  0  0  0  0

hehe.....

可以看到,相同的一份代码,使用不同的编译器编译,得到不同的结果。同时,也可以推理出 arm-linux-gcc v3.4.1
版本的编译应该有这样的一个漏洞。对于 ARM 板上的芯片和当前PC上的CPU芯片,处理内存都是小端法,不会有影响。就应该是
arm-linux-gcc v3.4.1 版本编译器的问题。

最后,为了解决在ARM板上的应用程序能够显示正确的数据,可以利用:把 buf[ ]
缓存中的数据复制到一个相应的结构体中,然后,再显示结构体中的数据。

void show_card_info(INT8U *buf, INT16U count)
{
    TGDR_Event event;
    bzero(&event,
sizeof(TGDR_Event));
 
    for(int i = 0; i < count; i++)
    {
       buf = buf + i*sizeof(TGDR_Event);
       memcpy(&event, buf,
sizeof(TGDR_Event));      //把 buf[]
缓存中的数据复制到一个结构体中再操作
       printf("*********** i = %d **********\n", i);
       printf("CardNo = %llu \n",
event.CardNo);
       printf("EvtCode = %u \n",
event.EvtCode);
       printf("eDate = %u \n",
event.eDate);
       printf("eTime = %u \n",
event.eTime);
       printf("EvtType = %u \n",
event.EvtType);
       printf("EvtActType = %u \n",
event.EvtActType);
       printf("DotAddr = %u \n",
event.DotAddr);
    }
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: