Hi,After reading more about transparent_unit, here's my idea of a fix for the API. old_api() is an example for the libc functions that accept a `struct sockaddr *`, and user_code() is an example for user code functions that handle sockaddr structures. The interface would be the same as it is currently, but the implementation inside libc would change to use a union. In user code, uses of sockaddr_storage would be made safe with these changes, I believe, and new code would be simpler, since it wouldn't need casts.
void old_api(union my_sockaddr_ptr *sa);
struct sockaddr_storage {
union {
struct {
sa_family_t ss_family;
};
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct sockaddr_un sun;
// ...
};
};
union [[gnu::transparent_union]] sockaddr_ptr {
struct sockaddr_storage *ss;
struct sockaddr *sa;
};
void old_api(struct sockaddr_storage *ss)
{
// Here libc uses the union, so it doesn't invoke UB.
ss->sun.sa_family = AF_UNIX;
//...
}
void user_code(void)
{
struct my_sockaddr_storage ss; // object definition
// ...
old_api(&ss); // The transparent_union allows no casts.
switch (ss.ss_family) {
// This is safe too.
// thanks to common initial sequence within a union.
}
}
This would in fact deprecate plain `struct sockaddr`, as Bastien suggested.
Cheers,
Alex
--
<http://www.alejandro-colomar.es/>
OpenPGP_signature
Description: OpenPGP digital signature
