推理 arm-linux-gcc/g++ v3.4.1 版本的一个漏洞
来源:互联网 发布:可以学数学的软件 编辑:程序博客网 时间:2024/05/17 04:48
如下是自己在开发项目的时候遇到的一个问题,并简单地记录下来。讲解的思路不是很连贯,但是,其中有给出一个例子,该例子推理出了问题的所在。
问题的引出
在开发项目的时候,下位机把一包事件发送给上位机,那么,自己调试,在发送数据包的时候,把事件给显示出来,有如下的逻辑:
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);
}
}
- 推理 arm-linux-gcc/g++ v3.4.1 版本的一个漏洞
- linux更换gcc g++版本
- Linux的gcc和g++的版本切换问题
- arm-linux-gnueabi-gcc/g++ 编译opencv
- arm-linux-gcc不同版本交叉编译器的切换使用
- 稳定版本的arm-linux-gcc 3.3.2下载
- linux不同gcc/G++版本之间的切换
- Linux下修改gcc和g++的版本
- arm-none-linux-gnueabi-gcc 版本下载
- linux 中切换gcc 和 g++版本
- arm-linux-gcc 和gcc的问题
- arm-linux-gcc的用法
- arm-linux-gcc的安装
- arm-linux-gcc的安装
- arm-linux-gcc的安装
- arm-linux-gcc的安装
- arm-linux-gcc的安装
- arm-linux-gcc的安装
- medical项目说明
- QvtkWidget 和 vtkImageViewer2 改变default mouse interactorStyle
- C++里父类的析构函数为什么声明为virtual
- Android基础之ListView
- linux的国外著名论坛网站
- 推理 arm-linux-gcc/g++ v3.4.1 版本的一个漏洞
- 类型初始值设定项引发异常
- 第19章、动态数组
- 基于ARM+LINUX的无线视频采集系统设计----------搭建嵌入式web服务器
- 第20章、控制语句foreach用法
- POJ3014 Cake Pieces and Plates DP
- Web建模工具
- day2 test10
- Java基础了解