...
C99 and C90 allow a pointer to be cast into and out of void *
. As a result, it is possible to silently convert from one pointer type to another without the compiler diagnosing the problem by storing or casting a pointer to void *
and then storing or casting it to the final type. In this noncompliant code example, the type checking system is circumvented due to the caveats of void
pointers.
Code Block | ||||
---|---|---|---|---|
| ||||
char *loop_ptr; int *int_ptr; int *loop_function(void *v_pointer) { /* ... */ return v_pointer; } int_ptr = loop_function(loop_ptr); |
...
Because the input parameter directly influences the return value, and loop_function()
returns an int *
, the formal parameter v_pointer
is redeclared to only accept int *
.
Code Block | ||||
---|---|---|---|---|
| ||||
int *loop_ptr; int *int_ptr; int *loop_function(int *v_pointer) { /* ... */ return v_pointer; } int_ptr = loop_function(loop_ptr); |
...
Many architectures require that pointers are correctly aligned when accessing objects bigger than a byte. There are, however, many places in system code where you receive unaligned data (for example, the network stacks) that needs to be copied to a properly aligned memory location, such as in this noncompliant code example.
Code Block | ||||
---|---|---|---|---|
| ||||
char *data; struct foo_header *tmp; struct foo_header *header; tmp = data + offset; memcpy(&header, tmp, sizeof(header)); if (header.len < FOO) /* ... */ |
...
This compliant solution does not use the foo_header
pointer.
Code Block | ||||
---|---|---|---|---|
| ||||
char *data; struct foo_header header; memcpy(&header, data + offset, sizeof(header)); if (header.len < FOO) /* ... */ |
...