Download raw body.
md5(1): avoid undefined function pointer casts
This is a bit of a stupid diff with lots of ugly boilerplate, but I
don't see a better way. The problem is 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 wrappers that have the correct types
and that then propagate their parameters in a defined way. As I said,
it's stupid and ugly and the one upside apart from appeasing the
language lawyers I can see is that we no longer have function pointer
casts.
PS: there is similar code in isakmpd/hash.c.
Index: md5.c
===================================================================
RCS file: /cvs/src/bin/md5/md5.c,v
diff -u -p -r1.98 md5.c
--- md5.c 31 Oct 2023 19:37:17 -0000 1.98
+++ md5.c 12 Jul 2025 09:10:17 -0000
@@ -63,6 +63,222 @@ union ANY_CTX {
SHA2_CTX sha2;
};
+static void
+cksum_init(void *ctx)
+{
+ CKSUM_Init(ctx);
+}
+
+static void
+cksum_update(void *ctx, const unsigned char *data, size_t len)
+{
+ CKSUM_Update(ctx, data, len);
+}
+
+static void
+cksum_final(unsigned char *digest, void *ctx)
+{
+ CKSUM_Final(ctx);
+}
+
+static char *
+cksum_end(void *ctx, char *digest)
+{
+ return CKSUM_End(ctx, digest);
+}
+
+static void
+md5_init(void *ctx)
+{
+ MD5Init(ctx);
+}
+
+static void
+md5_update(void *ctx, const unsigned char *data, size_t len)
+{
+ MD5Update(ctx, data, len);
+}
+
+static void
+md5_final(unsigned char *digest, void *ctx)
+{
+ MD5Final(digest, ctx);
+}
+
+static char *
+md5_end(void *ctx, char *digest)
+{
+ return MD5End(ctx, digest);
+}
+
+static void
+rmd160_init(void *ctx)
+{
+ RMD160Init(ctx);
+}
+
+static void
+rmd160_update(void *ctx, const unsigned char *data, size_t len)
+{
+ RMD160Update(ctx, data, len);
+}
+
+static void
+rmd160_final(unsigned char *digest, void *ctx)
+{
+ RMD160Final(digest, ctx);
+}
+
+static char *
+rmd160_end(void *ctx, char *digest)
+{
+ return RMD160End(ctx, digest);
+}
+
+static void
+sha1_init(void *ctx)
+{
+ SHA1Init(ctx);
+}
+
+static void
+sha1_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA1Update(ctx, data, len);
+}
+
+static void
+sha1_final(unsigned char *digest, void *ctx)
+{
+ SHA1Final(digest, ctx);
+}
+
+static char *
+sha1_end(void *ctx, char *digest)
+{
+ return SHA1End(ctx, digest);
+}
+
+static void
+sha224_init(void *ctx)
+{
+ SHA224Init(ctx);
+}
+
+static void
+sha224_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA224Update(ctx, data, len);
+}
+
+static void
+sha224_final(unsigned char *digest, void *ctx)
+{
+ SHA224Final(digest, ctx);
+}
+
+static char *
+sha224_end(void *ctx, char *digest)
+{
+ return SHA224End(ctx, digest);
+}
+
+static void
+sha256_init(void *ctx)
+{
+ SHA256Init(ctx);
+}
+
+static void
+sha256_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA256Update(ctx, data, len);
+}
+
+static void
+sha256_final(unsigned char *digest, void *ctx)
+{
+ SHA256Final(digest, ctx);
+}
+
+static char *
+sha256_end(void *ctx, char *digest)
+{
+ return SHA256End(ctx, digest);
+}
+
+static void
+sha384_init(void *ctx)
+{
+ SHA384Init(ctx);
+}
+
+static void
+sha384_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA384Update(ctx, data, len);
+}
+
+static void
+sha384_final(unsigned char *digest, void *ctx)
+{
+ SHA384Final(digest, ctx);
+}
+
+static char *
+sha384_end(void *ctx, char *digest)
+{
+ return SHA384End(ctx, digest);
+}
+
+static void
+sha512_256_init(void *ctx)
+{
+ SHA512_256Init(ctx);
+}
+
+static void
+sha512_256_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA512_256Update(ctx, data, len);
+}
+
+static void
+sha512_256_final(unsigned char *digest, void *ctx)
+{
+ SHA512_256Final(digest, ctx);
+}
+
+static char *
+sha512_256_end(void *ctx, char *digest)
+{
+ return SHA512_256End(ctx, digest);
+}
+
+static void
+sha512_init(void *ctx)
+{
+ SHA512Init(ctx);
+}
+
+static void
+sha512_update(void *ctx, const unsigned char *data, size_t len)
+{
+ SHA512Update(ctx, data, len);
+}
+
+static void
+sha512_final(unsigned char *digest, void *ctx)
+{
+ SHA512Final(digest, ctx);
+}
+
+static char *
+sha512_end(void *ctx, char *digest)
+{
+ return SHA512End(ctx, digest);
+}
+
struct hash_function {
const char *name;
size_t digestlen;
@@ -82,10 +298,10 @@ struct hash_function {
STYLE_CKSUM,
-1,
NULL,
- (void (*)(void *))CKSUM_Init,
- (void (*)(void *, const unsigned char *, size_t))CKSUM_Update,
- (void (*)(unsigned char *, void *))CKSUM_Final,
- (char *(*)(void *, char *))CKSUM_End
+ cksum_init,
+ cksum_update,
+ cksum_final,
+ cksum_end,
},
{
"MD5",
@@ -93,10 +309,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))MD5Init,
- (void (*)(void *, const unsigned char *, size_t))MD5Update,
- (void (*)(unsigned char *, void *))MD5Final,
- (char *(*)(void *, char *))MD5End
+ md5_init,
+ md5_update,
+ md5_final,
+ md5_end,
},
{
"RMD160",
@@ -104,10 +320,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))RMD160Init,
- (void (*)(void *, const unsigned char *, size_t))RMD160Update,
- (void (*)(unsigned char *, void *))RMD160Final,
- (char *(*)(void *, char *))RMD160End
+ rmd160_init,
+ rmd160_update,
+ rmd160_final,
+ rmd160_end,
},
{
"SHA1",
@@ -115,10 +331,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA1Init,
- (void (*)(void *, const unsigned char *, size_t))SHA1Update,
- (void (*)(unsigned char *, void *))SHA1Final,
- (char *(*)(void *, char *))SHA1End
+ sha1_init,
+ sha1_update,
+ sha1_final,
+ sha1_end,
},
{
"SHA224",
@@ -126,10 +342,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA224Init,
- (void (*)(void *, const unsigned char *, size_t))SHA224Update,
- (void (*)(unsigned char *, void *))SHA224Final,
- (char *(*)(void *, char *))SHA224End
+ sha224_init,
+ sha224_update,
+ sha224_final,
+ sha224_end,
},
#endif /* !defined(SHA2_ONLY) */
{
@@ -138,10 +354,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA256Init,
- (void (*)(void *, const unsigned char *, size_t))SHA256Update,
- (void (*)(unsigned char *, void *))SHA256Final,
- (char *(*)(void *, char *))SHA256End
+ sha256_init,
+ sha256_update,
+ sha256_final,
+ sha256_end,
},
#if !defined(SHA2_ONLY)
{
@@ -150,10 +366,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA384Init,
- (void (*)(void *, const unsigned char *, size_t))SHA384Update,
- (void (*)(unsigned char *, void *))SHA384Final,
- (char *(*)(void *, char *))SHA384End
+ sha384_init,
+ sha384_update,
+ sha384_final,
+ sha384_end,
},
{
"SHA512/256",
@@ -161,10 +377,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA512_256Init,
- (void (*)(void *, const unsigned char *, size_t))SHA512_256Update,
- (void (*)(unsigned char *, void *))SHA512_256Final,
- (char *(*)(void *, char *))SHA512_256End
+ sha512_256_init,
+ sha512_256_update,
+ sha512_256_final,
+ sha512_256_end,
},
#endif /* !defined(SHA2_ONLY) */
{
@@ -173,10 +389,10 @@ struct hash_function {
STYLE_MD5,
0,
NULL,
- (void (*)(void *))SHA512Init,
- (void (*)(void *, const unsigned char *, size_t))SHA512Update,
- (void (*)(unsigned char *, void *))SHA512Final,
- (char *(*)(void *, char *))SHA512End
+ sha512_init,
+ sha512_update,
+ sha512_final,
+ sha512_end,
},
{
NULL,
md5(1): avoid undefined function pointer casts