As promised yesterday today’s post is about implicit declarations. Let’s first give a bit of background of those, even though I have partially described them with GLIBC 2.12 since they seem to have increased with that release.
As the name already explains, implicit function declarations are caused when you call a function without declaring it beforehand. This behaviour has been classically allowed by the C language, but is usually not allowed by most other compiled languages, starting from C’s younger cousins such as C++. Since a declaration provides the specification of the type of return values and parameters, how does that work? Simple: any function used without declaration is declared as int func(...)
.
Is this a bad situation? You bet; as Mike pointed out the main issue there is with the size of parameters and, more importantly, of the return value. For instance, if the function is supposed to return a pointer, it will not work, and rather truncate it, on any 64-bit system; and today’s systems are mostly 64-bit! There is also the problem of the compiler being unable to validate the needed number and order of parameters. More importantly in my opinion is that an implicit declaration can point out for an undefined symbol when a function (or macro) has been mistyped, or removed from the used libraries.
So implicit declarations are bad, why are they not always disallowed then? Well, they are, on C++, as I said; they are not in C for various reasons; and while you can make the compiler refuse them with -Werror-implicit-declarations
(and on more modern compilers -Werror=implicit-declarations
) you cannot do that on a distribution level because things like autoconf actually rely on them to be allowed, ouch.
So In this situation, should Gentoo developers care about fixing these warnings themselves? Yes and no; from one side, fixing them adds a tighter safety to the code, and that is something that we could always use; on the other side, they tend not to be much of a problem if the package works at the end of the day; while we love to make things better, we should try to stick with upstream as much as possible; diverging even just for this kind of stuff is never good.
But there is something more to consider here; as I wrote twice we should be caring more about fortified functions. Fortified functions are there to make our programs more secure, by making sure that we don’t have buffer overflows that could lead to security issues further down the road. I have also noted that since version 4.3.3-r1 of GCC in Gentoo, all you have to do to enable use of fortified source is using -O2
(fortified functions are enabled only if function inlining is enabled, otherwise they will be ignored). Actually it’s a bit more complex.
The fortified functions have a chk
specification, and are separate symbols from the “standard” common functions; this means that, for instance, you shouldn’t have a reference to strncpy
to have the fortified function but rather __strncpy_chk
. The translation between these two names is done by the header files, when optimisations and inline functions are supported. This, though, only works if the header files where the function is declared are actually included. This means that leaving the declarations implicit also leave you uncovered from both the build-time and run-time control of fortified sources, which let me tell you, is bad news.
But this should also act as a warning: fixing implicit declarations is not just a build-time fix! It might even change the behaviour of the program, adding possible aborts at runtime when the code actually has overflows that generally are not fatal. Is that a bad thing? Not really, in my opinion, but others might disagree. In any case, it’s enough of a change to warrant a revision bump, to me. Of course to avoid that the easiest thing to do is … not having implicit declarations the first time you add a package to the tree, or version bump it.
I guess I’ll have to doublecheck my own packages, and possibly ask again Zac to allow for per-package features so that I can make sure that this kind of stuff never makes it on my final commits.
What if someone fixes the tools failing with -Werror-implicit-declarations?Could we then use this in gentoo to track those errors down?
Highly unlikely to work out properly; autoconf will provide false information, rather than simply fail, so it’s not a good idea to use it in Gentoo as it is.
Per-package environment variables work, and it should be all you need from the portage side. They don’t work with all FEATURES, but do work with what I think is enough for your needs, unless I’m overlooking something.
I believe tuXXX was inquiring as to the viability of changing autoconf so that it would return proper results even in the presence of -Werror=implicit-declarations.For packages that properly isolate src_configure and src_compile, it might be possible to have a Portage bashrc rule that inserts -Werror=implicit-declarations into $CFLAGS when $EBUILD_PHASE = “compile”. This should avoid confusing autoconf, but still provide most of the desired protection. Of course, it will fail horribly if used in a package that calls configure from inside src_compile, and I see no obvious way of detecting that from inside the bashrc code. Perhaps someone else can build on this idea. For example, it might work if the change was restricted to use in EAPIs that declare it bad form to use configure from inside src_compile.
Most of the implicit declarations I’ve hit are trivial to fix ( one line diff ), so if the ebuild maintainers find the time shouldn’t those diffs be somewhat easy to merge upstream?I can understand that it’s unwanted to have gentoo-specific patches for just implicit declarations though.
For what concerns autotools, there is enough of trouble that the best way to handle this is probably what I’ve been doing on feng and other projects I follow: after the configure checks are done, it tests how to tell the compiler to abort on implicit declarations (@-Werror=implicit-declarations@ or for older ones @-Werror-implicit-declarations@) and includes it to CFLAGS. Rewriting the CFLAGS variable on @make@ call is not going to be that helpful, I’m afraid.Patching is usually trivial and most upstream will accept the patches gladly so it shouldn’t be much of a showstopper.Thanks for the note Harald, I thought that the new per-package env still only worked for the bash phases, not for Python as well! Looks perfect now, I have a couple of things to fix it seems…