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.