Q: why didn't GCC warn about this uninitialized variable? (was: Re: [PATCH] perf tests: initialize sa.sa_flags)

From: Ingo Molnar
Date: Thu Mar 03 2016 - 07:19:54 EST



* Arnaldo Carvalho de Melo <acme@xxxxxxxxxx> wrote:

> Em Wed, Mar 02, 2016 at 02:21:27PM +0100, Peter Zijlstra escreveu:
> > On Wed, Mar 02, 2016 at 10:03:50AM -0300, Arnaldo Carvalho de Melo wrote:
> > > > Would not something like:
> > > >
> > > > sa = (struct sigaction){
> > > > .sa_sigaction = segfault_handler,
> > > > };
> > > > sigfillset(&sa.sa_mask);
> > > >
> > > > Be better?
> > >
> > > I thought about that, but isn't that set in stone? This would be a 4
> > > liner, while his is a one' :-)
> >
> > Dunno, you're right that its rather unlikely struct sigaction is going
> > to grow another member, but I like the above pattern better in general,
> > makes it harder to end up with uninitalized bits.
> >
> > When performance matters the above pattern isn't ideal, but that should
> > not be a concern here.
>
> Right, I also always use :
>
>
> struct foo bar = {
> .baz = 1,
> .name = "whatever",
> };
>
> Even more compact than using that cast. But didn't bother changing in
> this case.

So the source of the bug was:

struct sigaction sa;

...

sigfillset(&sa.sa_mask);
sa.sa_sigaction = segfault_handler;
sigaction(SIGSEGV, &sa, NULL);

... which uninitialized sa.sa_flags field GCC merrily accepted as proper C code,
despite us turning on essentially _all_ GCC warnings for the perf build that exist
under the sun:

gcc -Wbad-function-cast -Wdeclaration-after-statement -Wformat-security -Wformat-y2k \
-Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
-Wno-system-headers -Wold-style-definition -Wpacked -Wredundant-decls \
-Wshadow -Wstrict-aliasing=3 -Wstrict-prototypes -Wswitch-default -Wswitch-enum \
-Wundef -Wwrite-strings -Wformat \
-Werror -O6 -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 -fstack-protector-all -D_FORTIFY_SOURCE=2

This is a _trivial_ uninitialized variable bug, yet GCC never warned about it.
Why?

People build perf with a wide range of GCC versions, from old ones to trunk. I
cannot believe it that none of those GCC versions warned about this trivial
looking bug!

And yes, I know that unitialized structures on the stack are valid C code, yet
it's one of the most fragile aspects of C and it was the source of countless
security holes in the past...

Thanks,

Ingo