[英]Is insecure to cast a void * pointer?
例如下面的代码:
#include <stdio.h>
int main()
{
char i = 0;
char j = 0;
char *p = &i;
void *q = p;
int *pp = q;
printf("%d %d\n", i, j);
*pp = -1;
printf("%d %d\n", i, j);
return 0;
}
如果我使用gcc版本8.1.0 x64(Ubuntu 8.1.0-5ubuntu1〜16.04)进行编译,则输出为:
0 0
-1 -1
现在,我使用强制转换为整数*
#include <stdio.h>
int main()
{
char i = 0;
char j = 0;
char *p = &i;
void *q = p;
int *pp = (int *)q;
printf("%d %d\n", i, j);
*pp = -1;
printf("%d %d\n", i, j);
return 0;
}
结果与之前的结果相同。
使用clang-6.0 x64时,输出为:
0 0
-1 0
该代码显然是缓冲区溢出吗?
我希望我已经清楚地解释了。
强制转换或不强制转换,您实际上是在尝试使用不兼容的类型,从而导致违反严格的别名规则。
根据C11
第6.5节,
一个对象只能通过具有以下类型之一的左值表达式访问其存储值:88)
—与对象的有效类型兼容的类型,
—与对象的有效类型兼容的类型的限定版本,
—一个类型,它是与对象的有效类型相对应的有符号或无符号类型,
—一种类型,是与对象的有效类型的限定版本相对应的有符号或无符号类型,
—集合或联合类型,其成员中包括上述类型之一(递归地包括子集合或包含的联合的成员),或
—字符类型。
但是,您尝试通过int
类型访问为char
分配的内存。 这违反了严格的别名。
也就是说,该标准保证char
大小为1个字节, int
大小为>=
char
。 因此,访问将超出范围,并导致未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.