This repository has been archived by the owner on Sep 30, 2024. It is now read-only.
Problems caused by __SOCKADDR_ARG
transparent union in sys/socket.h
when _GNU_SOURCE
is on
#440
Labels
This issue was copied from checkedc/checkedc#441
We started seeing an error in the 3C benchmark tests when we turned on implicit checked header inclusion (#440 and checkedc/checkedc-clang#998). Our icecast benchmark contains the equivalent of the following:
With implicit checked header inclusion, the second line effectively becomes
#include <sys/socket_checked.h>
, and compiling the above gives:And so forth for the rest of the declarations in
sys/socket_checked.h
that use__SOCKADDR_ARG
or__CONST_SOCKADDR_ARG
. (Without implicit checked header inclusion, we didn't see the problem because our#include
updating script had a bug and didn't process checked headers in subdirectories such assys/socket_checked.h
: oops.)When
_GNU_SOURCE
is off,__CONST_SOCKADDR_ARG
is a typedef forconst struct sockaddr *
(and similarly for__SOCKADDR_ARG
), which exactly corresponds to the itype, and everything works as expected. But when_GNU_SOURCE
is on,__CONST_SOCKADDR_ARG
is a typedef for a magical "transparent union" of several pointer types, includingconst struct sockaddr *
. This is a compiler extension (implemented by at least GCC and Clang) that allows the function to be redeclared later in the translation unit with the parameter type being any one of the members of the transparent union and the compiler will accept it, as an exception to the normal restrictions on redeclaring a function with different parameter types. In this case, I think the goal was to be compatible with user source code that redeclared socket-related functions using certain types similar but not identical toconst struct sockaddr *
. However, this seems to break the Checked C compiler because the transparent union is not itself a pointer type, so it cannot have a pointer type as its itype.One way to fix the immediate problem is for
sys/socket_checked.h
to useconst struct sockaddr *
, etc. directly instead of__CONST_SOCKADDR_ARG
. This theoretically would break existing plain C code that turned on_GNU_SOURCE
and relied on the ability to use the other types, though such code would eventually need changes to be ported to Checked C anyway. I tried that approach, but then 3C raised a fatal error, the root cause of which was the two declarations ofbind
with different unchecked parameter types (the transparent union in the system header andconst struct sockaddr *
in the Checked C header). 3C's error message in this situation currently isn't great; obviously I knew the error was caused by thesys/socket_checked.h
change that I was testing, but that probably wouldn't be clear to an average 3C user who hit the error in a different but analogous situation. So apart from any fix tosys/socket_checked.h
, it might be worth considering having the Checked C compiler place additional restrictions on transparent unions or at least provide an API for program analysis tools such as 3C that cannot handle them to disable support for them in the compiler so they will be rejected up front.For now, our workaround will probably be to patch icecast to turn off
_GNU_SOURCE
.The text was updated successfully, but these errors were encountered: