简体   繁体   English

不安全地使用void *指针吗?

[英]Is insecure to cast a void * pointer?

For example in this code: 例如下面的代码:

#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;
}

if I compile with gcc version 8.1.0 x64 (Ubuntu 8.1.0-5ubuntu1~16.04) the output is: 如果我使用gcc版本8.1.0 x64(Ubuntu 8.1.0-5ubuntu1〜16.04)进行编译,则输出为:
0 0 0 0
-1 -1 -1 -1
now, I use a cast to int * 现在,我使用强制转换为整数*

#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;
}

the result is the same as the previous. 结果与之前的结果相同。
With clang-6.0 x64 the output is: 使用clang-6.0 x64时,输出为:
0 0 0 0
-1 0 -1 0
Is the code apparently a buffer overflow? 该代码显然是缓冲区溢出吗?
I hope I've explained that clearly. 我希望我已经清楚地解释了。

You actually have two problems: 您实际上有两个问题:

The first is that you break strict aliasing and have undefined behavior . 首先是您破坏严格的别名并具有未定义的行为

The second problem is that on most modern platforms the size of an int is four bytes, and the pointer pp is pointing only to a single byte. 第二个问题是,在大多数现代平台上,一个int的大小为4个字节,而指针pp仅指向单个字节。 The assignment you make to *pp will therefore write out of bounds and also lead to undefined behavior. 因此,您对*pp进行的分配将超出范围, 导致未定义的行为。

Cast or no cast, you are essentially try to use incompatible types, leading to violating strict aliasing rules. 强制转换或不强制转换,您实际上是在尝试使用不兼容的类型,从而导致违反严格的别名规则。

According to C11 , chapter §6.5, 根据C11第6.5节,

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88) 一个对象只能通过具有以下类型之一的左值表达式访问其存储值:88)

— a type compatible with the effective type of the object, —与对象的有效类型兼容的类型,

— a qualified version of a type compatible with the effective type of the object, —与对象的有效类型兼容的类型的限定版本,

— a type that is the signed or unsigned type corresponding to the effective type of the object, —一个类型,它是与对象的有效类型相对应的有符号或无符号类型,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, —一种类型,是与对象的有效类型的限定版本相对应的有符号或无符号类型,

— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or —集合或联合类型,其成员中包括上述类型之一(递归地包括子集合或包含的联合的成员),或

— a character type. —字符类型。

But, you try to access the memory allocated for a char via an int type. 但是,您尝试通过int类型访问为char分配的内存。 This violates strict aliasing. 这违反了严格的别名。

That said, the standard guarantees that size of a char is 1 byte, size of an int is >= char . 也就是说,该标准保证char大小为1个字节, int大小为>= char So, the access would be out of bound and lead to undefined behavior. 因此,访问将超出范围,并导致未定义的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM