I'm a senior studying computer science and I've never seen behavior this strange before. I'm sure there is just some C complexity that I'm not understanding but I'm completely lost right now.
I’ve made the following function:
Declaration
void parse_resp(unsigned char *resp, unsigned char *chunk, unsigned int *opcode, unsigned char *opparams, unsigned int *nonce, unsigned char *treasure, int *offset);
Basically just a function where I pass a punch of pointers to get populated
Definition
void parse_resp(unsigned char *resp, unsigned char *chunk, unsigned int *opcode, unsigned char *opparams, unsigned int *nonce, unsigned char *treasure, int *offset)
{
int chunklen = resp[0];
memcpy(&chunk[0], &resp[1], chunklen);
memcpy(opcode, &resp[chunklen 1], 1);
memcpy(&opparams[0], &resp[chunklen 2], 2);
memcpy(nonce, &resp[chunklen 4], 4);
*nonce = htonl(*nonce);
}
Variable Initialization
unsigned char treasure[1024];
int offset = 0;
unsigned char chunk[127];
unsigned int opcode;
unsigned char opparams[2];
unsigned int nonce;
But here’s where it gets weird.
If I call the function like this parse_resp(buf, chunk, &opcode, opparams, &nonce, NULL, &offset);
Then everything works fine.
But if I pass in treasure as an argument (even though parse_resp doesn’t use treasure) then memcpy(opcode, &resp[chunklen 1], 1);
doesn’t work. Printing the value of opcode after this shows some random int . This makes no sense to me. I don’t understand how passing treasure as an argument could make memcpy behave incorrectly. If I print the value of resp[chunklen 1]
, I see a 0 (as expected), but when I try to memcpy()
that same location, I get a random number? Any idea what is going on here?
Note: I realize there are fairly easy work arounds for this error, but I would like to understand what is going on first.
CodePudding user response:
opcode
has type int
which is most likely 4 bytes, however you're only copying a single byte into it:
memcpy(opcode, &resp[chunklen 1], 1);
So the other 3 bytes are left uninitialized and therefore have indeterminate values. So at best there is no guarantee that these bytes have any particular value, and changing how parse_resp
is called is enough to vary the values of those uninitialized bytes.
In some cases reading an uninitialized variable can trigger undefined behavior, however since opcode
had its address taken it's not an issue (unless you're on an exotic architecture that has trap representations for int
).
Change the type of this variable and the associated parameter to unsigned char
.