简体   繁体   中英

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:
0 0
-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:
0 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. The assignment you make to *pp will therefore write out of bounds and also lead to undefined behavior.

Cast or no cast, you are essentially try to use incompatible types, leading to violating strict aliasing rules.

According to C11 , chapter §6.5,

An object shall have its stored value accessed only by an lvalue expression that has one of the following types: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. This violates strict aliasing.

That said, the standard guarantees that size of a char is 1 byte, size of an int is >= char . So, the access would be out of bound and lead to undefined behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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