Joe Pfeiffer
8/25/2011 3:34:00 PM
Kenneth Brody <kenbrody@spamcop.net> writes:
> On 8/24/2011 1:29 PM, William Ahern wrote:
>> Because the issue gets discussed here on a semi-monthly basis, I thought the
>> following real-world example might be worth posting. The code belongs to the
>> c-ares project, which is used in much FLOSS and commercial software.
>>
>> Backdrop of the code in question:
>>
>> struct nameinfo_query {
>> union {
>> struct sockaddr_in addr4;
>> struct sockaddr_in6 addr6;
>> } addr;
>> };
>>
>> struct nameinfo_query niquery;
>> struct sockaddr_in *addr;
>>
>> Original code, circa 2005:
>>
>> memcpy(&niquery->addr.addr4, addr, sizeof(addr));
>>
>> First fix in June 2011:
>>
>> memcpy(&niquery->addr.addr4, addr, sizeof(struct in_addr));
>>
>> Final fix:
>>
>> memcpy(&niquery->addr.addr4, addr, sizeof(niquery->addr.addr4));
> [...]
>
> Well, in this case, the bug was using the sizeof() the wrong thing.
> In this case, you're dealing with a destination that may be larger
> than the source, due to the fact that it can hold multiple types of
> structs. Therefore, as the "final fix" uses, you need the sizeof()
> the source, not the destination.
>
> Consider a simpler version of the same thing:
>
> unsigned char GenericBuffer[65535];
> struct foo MyFoo;
> ...
> memcpy(&MyFoo,GenericBuffer,sizeof(???));
>
> (This assumes, of course, that the implementor knows that
> GenericBuffer will never need to hold anything larger than 65535
> bytes.)
No, the final fix used the sizeof the actual destination. Which
suggests the following might be a "final final fix":
sizeof(GenericBuffer) < sizeof(MyFoo) ? sizeof(GenericBuffer) : sizeof(MyFoo)