The following is a collection of C code, which may have side effects or behavior that is not immediately apparent or obvious. It is intended to serve as a collection of interesting behaviors that may inspire folks to dig deeper into the how and why of the C standard and compilers, as well as also providing a warning of the complexities of having your code do what you intended.
What will the answer be?
(1/2) are both
int literals which evaluate to zero.
The answer is zero.
Will it overrun?
Will the following code memset beyond the allocated buffer? Assume the compiler will not optimize anything out, and 2’s compliment.
It depends on the data model in use.
We’re taking a
signed int, casting it to
unsigned int and then
size_t for the malloc, and casting it to
size_t for the memcpy.
On ILP32 (32-bit Windows, Linux, OSX) where the width of size_t is equal to the width of unsigned int, no error occurs.
On LP64 (64 bit OSX and Linux) where unsigned int is 32 bit but size_t is 64 bit, the following can occur:
- The value -1 is passed in by a user, represented as a negative value in the
intwith 2’s complement as 0xFFFFFFFF
- In the malloc, the value is cast to an
unsigned int, keeping it’s value of 0xFFFFFFFF but becoming
unsigned, followed by being cast from
size_t, which is an
unsigned int, so the value becomes 0x00000000FFFFFFFF.
- In the memcpy, the value needs to go from 32 bit int to 64 bit (unsigned)
size_t. The first thing that occurs is the value is cast from signed 32 bit to signed 64 bit. To represent -1 in 64-bit, a sign extension occurs, resulting in the value 0xFFFFFFFFFFFFFFFF. This value is then cast to unsigned, which does not affect the underlying bit pattern
- The memcpy size far exceeds the allocated memory, resulting in an attempted out of bounds write
What is the result of running
./prog? what about
./prog a b c? why?
#define line is essentially a match/replace. This can be observed by running
gcc -E code.c.
./prog results in
h() running, due to the lack of curly braces around
the if body.
./prog a b c results in