Secure Coding mailing list archives

Compilers


From: leichter_jerrold at emc.com (Leichter, Jerry)
Date: Fri, 29 Dec 2006 09:46:16 -0500 (EST)

| I _strongly_ encourage development with "maximal" warnings turned on.
| However, this does have some side-effects because many compilers
| give excessive spurious warnings.  It's especially difficult to
| do with pre-existing code (the effort can be herculean).
Agreed.  Writing for maximum freedom from warnings is a learned skill,
and a discipline.  Mainly it involves avoiding certain kinds of
constructs that, when all is said and done, are usually as confusing
to human readers as they are to compilers.  There is a great deal of
overlap among "writing for no warnings", "writing for maximum
portability", "writing for clarity", and "writing for provability".
What they all come down to is:  The code sticks to the meaning of
the language definition and avoids all ambiguity; it has only one
possible interpretation, and coming to that interpretation requires
minimum work.

That said, there will always be cases where maximum speed, minimum
size, or some other external constraint drive you to do things that
don't meet these constraints.  Some of these are reasonable.  Bubble
sort is "obviously correct"; no O(N log N) sort is.  There are
places where you have to use comments to refer to a proof and the
kind of checking required becomes very different.  And there are
places where every nanosecond and every byte really matters.  The
conceit of all too many programmers is that *their* code is
*obviously* one of those cases.  It almost certainly isn't.
 
| An interesting discussion about warning problems in the Linux kernel
| can be found here:
| http://lwn.net/Articles/207030/
There's example given there of:

    bool flag = false;
    some_type* pointer;

    if (some_condition_is_true()) {
       flag = true;
       pointer = expensive_allocation_function();
    }
    do_something_else();
    if (flag) {
       use_the_fine(pointer);
    }

The compiler will warn that the call to use_the_fine() might be
called with an uninitialized pointer.  Noticing the tie between
flag being true and pointer being initialized is beyond gcc,
and probably beyond any compiler other than some research tools.

Then again, it's not so easy for a human either beyond a trivial
example like this!

There's an obvious way to change this code that is simultaneously
warning-free, clearer - it says exactly what it means - and smaller
and equally fast on all modern architectures:  Get rid of flag,
initialize pointer to NULL, then change the test of flag to test
whether pointer is non-NULL.  (Granted, this is reading into the
semantics of "expensive_allocation_function()".)  Someone mentions
this in one response, but none of the other respondents pick up
on the idea and the discussion instead goes off into very different
directions.

There's also no discussion of the actual cost in the generated code
of, say, initializing pointer to NULL.  After all, it's certainly
going to be in a register; clearing a register will be cheap.  And
the compiler might not even be smart enough to avoid a pointless
load from uninitialized memory of pointer is *not* given an
initial value.

(There is one nice idea in the discussion:  Having the compiler
tell you that some variable *could* have been declared const,
but wasn't.)

I find this kind of sideways discussion all too common when you
start talking about eliminating warnings.

| Ideally compiler writers should treat spurious warnings as serious bugs,
| or people will quickly learn to ignore all warnings.
| The challenge is that it can be difficult to determine what is
| "spurious" without also making the warning not report what it SHOULD
| report.  It's a classic false positive vs. false negative problem
| for all static tools, made especially hard in languages where
| there isn't a lot of information to work with.
Having assertions actually part of the language is a big help here.
This is all too rare.
                                                        -- Jerry
 
| --- David A. Wheeler


Current thread: