Suspicious pointer-to-pointer conversion (area too small) in C

2k views Asked by At
uint8_t *buf;
uint16_t *ptr = (uint16_t *)buf;

I feel the above code is correct but I get "Suspicious pointer-to-pointer conversion (area too small)" Lint warning. Anyone knows how to solve this warning?

3

There are 3 answers

0
Sourav Ghosh On

IMHO, don't cast the pointer at all. It changes the way (representation) a variable (and corresponding memory) is accessed, which is very problematic.

If you have to, cast the value instead.

0
Pradheep On

Its a problem in your code

In line uint8_t buf you must have assigned it with an memory area which is 8 bits long

and then in line uint16_t *ptr = (uint16_t *)buf; you try to assign it to a pointer that will access it as 16 bits.

When you try to access with ptr variable you are acessing memory beyond what is assigned to you and its a undefined behaviour.

0
Lundin On

The problem here is strict aliasing. Imagine that when you have a case like this:

uint8_t  raw_data [N]; // chunk of raw data

uint16_t val = 1;
memcpy(raw_data, &val, sizeof(val)); // copy an uint16_t into this array

uint16_t* lets_go_crazy = (uint16_t*)raw_data;
*lets_go_crazy = 5;

print(raw_data);

Assume the print function prints all the values of the bytes. You might then think that the two first bytes have changed to contain your machine's representation of an uint16_t containing the value 5. Not necessarily so.

Because the compiler on the other hand is free to assume that you have never modified the raw_data array since the memcpy, because an uint16_t is not allowed to alias an uint8_t. So it might optimize the whole code into something like:

uint8_t  raw_data [N]; // chunk of raw data

uint16_t val = 1;
memcpy(raw_data, &val, sizeof(val)); // copy an uint16_t into this array

print(raw_data);

What will happen is undefined, because the strict aliasing was broken.

Though note that your code might be perfectly fine if, and only if, you can guarantee that your particular compiler does not apply strict aliasing to whatever scenario you have. There are compiler options to disable it on some compilers.

Alternatively, you could use a pointer to a struct or union containing an uint16_t, in which case the aliasing does not apply.