[Cryptography] GnuTLS -- time to look at the diff.

Patrick Chkoreff patrick at rayservers.net
Fri Mar 7 19:26:04 EST 2014


Nico Williams wrote, On 03/07/2014 04:19 PM:

> Well, no, it's not easy: you _have_ to initialize them because they
> don't auto-initialize.

But that *is* easy.  To wit:

    long count = 0;
    double ratio = 0;
    struct int_pair pair = {1,2};

That initialization is extraordinarily easy.


> One can do something about this: put all local variables in a local
> struct and memclear it at function entry. ...

Now why would I complicate my simple initializers with an artificial
struct, and a memclear with sizeof?  I'm going with the flow.


Now let's wrap it in some code with one of those short-circuiting
one-shot do loops and see what that looks like:

$ cat foo.c
#include <stdio.h>

struct int_pair
    {
    int i;
    int j;
    };

void do_stuff(void)
    {
    printf("== begin\n");

    long count = 0;
    double ratio = 0;
    struct int_pair pair = {1,2};
    /* maybe some malloc stuff too */

    do
    {
    printf("Here's where I'd do an elaborate computation.\n");
    int sum = pair.i + pair.j;
        /* (TODO what about integer overflow? heh :) */
    if (sum < 4)
        {
        printf("  Oops, the sum is less than four, I'm outta here!\n");
        break;
        }
    printf("Whew, thank goodness sum is at least four!\n");

    /* ... a dozen other cases that can short-circuit go here ... */

    } while (0);

    printf("count = %ld\n", count);
    printf("ratio = %.15f\n", ratio);
    printf("pair = (%d,%d)\n", pair.i, pair.j);

    /* maybe some free stuff too */
    printf("== end\n");
    }

int main(int argc, char *argv[])
    {
    do_stuff();
    return 0;
    }


$ gcc -Wall foo.c -o foo && ./foo
== begin
Here's where I'd do an elaborate computation.
  Oops, the sum is less than four, I'm outta here!
count = 0
ratio = 0.000000000000000
pair = (1,2)
== end


The -Wall will even warn you if you forget to initialize count or ratio.
 I always use -Werror as well, so I absolutely cannot ignore warnings.
I demand serene compilation.

The one problem I noticed:  gcc will *not* warn you if you forget to
initialize pair.  Not cool.  I need to find out what's up with that.


> Downsides:
>  - unnecessary and distracting additional indentation...

There's no need to indent the do loop in my example, because it looks
better without it.


> Seriously: the goto was not the problem.  Building a lot of machinery
> to avoid a non-problem is only going to cause problems.

I build code by evolving simple control structures (if, while, function
call) in a methodical way, where each individual mutation preserves the
semantics of the code, with the exception of one well-understood new
feature.  I keep adding those mutations up until I'm done.  It's proof
and programming all in one process.  But ya gotta write some tests cuz
you probably screwed up the proof somewhere.

During that process, it never even *crosses my mind* to use a goto.


> If you're not paying for discipline then you'll need a scapegoat; I
> suppose goto is as good as any other scapegoat.

I have explicitly said that "goto" is not the scapegoat in the bug in
question.

Lack of a test case was a big deal.

Regarding merges, I distrust automated merges so badly that I'd rather
look at a diff in a terminal and manually do the merges in a
split-screen vim terminal.  It's an elaborate sequence of Ctrl-w, y, p,
%, d, etc., and I can sit there and contemplate the actual *semantics*
of the code I'm merging, as I go.

Every once in a while I'll do an automated git merge, with butterflies
in my stomach, and then frantically look through the resulting code to
see if any semantic flaws might have been introduced as a result of
purely textual merging.  When I do it manually, it feels more "haptic",
like I'm clicking engine parts together in a satisfying way.


-- Patrick

P.S. OK I'm going to resist talking about code techniques for a while.
It's tangentially related to crypto, because what's the point of crypto
if your code is unsound?  But there's not a damn thing I or anyone else
can do about Gnu TLS or Open SSL or any of that.

I think a crypto library should be built from the ground up using
unassailable parts -- and immediately after building a new part everyone
should go about assailing mercilessly.  Bounties paid for making it
overrun a buffer or segfault.  Then just keep plugging those suckers
together until you have one big unassailable part.

Oh but I forgot about ASN.1.  Gag.  All my air castles just went *poof*.



More information about the cryptography mailing list