CVSROOT:        /cvs
Module name:    src
Changes by:     t...@cvs.openbsd.org    2025/07/16 23:30:41

Modified files:
        bin/md5        : md5.c 

Log message:
md5(1): avoid incompatible function pointer casts

This is a bit of a stupid change with lots of boilerplate. The problem
is undefined behavior due to the second sentence of C99 6.3.2.3, 8:

A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare equal
to the original pointer. If a converted pointer is used to call a
function whose type is not compatible with the pointed-to type, the
behavior is undefined.

The notion of compatibility for the functions here boils down to
compatible return type and compatible argument list, which in particular
means the same number of arguments. See 6.7.5.3, 15 for the gory details.
There's also a version understandable to a human being lacking the brain
damage necessary for successfully deciphering the C99 standard's language:
https://en.cppreference.com/w/c/language/type.html

So calling 'void CKSUM_Final(CKSUM_CTX *);' through the final member of
struct hash_function is clearly UB since the numbers of parameters don't
match. If that was all, the fix would be trivial. But the same goes for
void MD5Final(MD5_CTX *, char *); because MD5_CTX * and void * aren't
compatible in this sense: by definition, two pointer types are compatible
if they point to compatible types. Or, if you prefer: void * has looser
alignment requirements than MD5_CTX *, so they aren't compatible.

The below avoids this by adding wrapper functions that have the correct
types that then propagate their parameters by using the appropriate
union member.

with/ok millert

Reply via email to