?

Log in

teacher-mode

Heartbleed

Thanks to jducoeur, this link to XKCD's explanation of the Heartbleed bug.

OMG: I didn't realize it was this simple and stupid. Reason #738 why no production code should be written in C or C++.

Comments

Reason 1 why it should - because few languages provide as much quality of access to real hardware as C or C++.

Reason 2 why it can be - reasonable code review can find and avoid defects of this sort.

Reason 3 why it is sometimes necessary: because while other languages provide some automation in the avoidance of certain classes of defects, they do not absolutely prevent this one, but their features often reduce performance - and sometimes that matters.

I say these things, despite preferring other languages, because that is how real systems are made currently. And because, as a software quality engineer, how bugs like this are prevented.

When I heard ABOUT the HeartBleed bug being related to Keep-Alive pings and returning bad memory, I knew what the bug was and how to fix it. That's one of the basic things we check for when checking protocols.

The bug was in the protocol: because the protocol permits the client to ask for more data than it sends. Implementing that protocol properly in ANY language, would have implemented a bug as well.

Language snobbery is not the correct response. One can screw this up in ANY language.
Code review didn't find it here.

Some languages ARE more inherently fragile than others. Plenty of languages prevent entire categories of errors, most specifically the ones easiest to use for exploits (buffer overflows, bad pointer dereferencing).

Juggling flaming radioactive knives can be done safely by professionals, but if all you need to do is juggle, why not use batons instead?
Code Review did not find it here.

If there was Code Review, if the code review was professionally done...

Quality Engineering is a fraught existence: when we find and fix bugs, we get no plaudits, but miss one damned thing: and we get hung by the neck until dead, while the developer that put the bug in there only gets spanked. :-)

The right tool for the job is the right tool: and sometimes that right tool is a language that permits buffer overruns and illegal pointer dereferencing, but which provides other language features that are advantageous.

It's all about balancing risks properly.

I would proffer that, given the incredible importance of this software, as it relates to critical infrastructure, it sure would have been nice if it had gotten more and better attention.
The code reviewer has come forward, along with the bug author.
I know.

I thought that was a very good thing, frankly.

Although if they had not, GIT would have done it for them. :-)

Fair cop

True: it would have been possible to produce this bug in other languages. But it would have been harder: you would have had to actively choose to dump from a specified memory position forward for a specified length rather than doing the easy thing, sending out a copy of the received string. C makes it easy to get at the raw machine when you need to -- but it also makes it easy to get at the raw machine when you DON'T need to.

And yes, the right answer in ANY language is good code review, careful documentation of assumptions, and testing what happens when those assumptions are violated.

There are languages (e.g. Haskell) that get nearly the performance of C without losing soundness, because the compiler does a lot of theorem-proving about what can and can't be true at various points in the code. Of course, that technology didn't exist forty years ago....

Re: Fair cop

Let me clarify that my objections were not to the language chosen to implement OpenSSL, but your assertion that nothing should ever be done in languages like C and C++.

Frankly, if the memory used in the Heartbleed bug was created with calloc() and not malloc() the issue would have also gone away. I always use calloc(): I consider malloc() to be "mentally deprecated". I've not found a situation yet where the performance penalty of calloc() was a problem. (Arguendo that I ever do: I would certainly argue that code whose performance was THAT critical probably has been reviewed near-unto-death.)

I keep meaning to learn Haskell and Scala, precisely because they are so frigging cool. :-)

But, I say absent certain knowledge, I bet that they don't get so cozy with the hardware, that you can use them to specifically access UARTS or specific memory locations in order to interface with custom hardware. Which is something that realtime systems (like many of the commercial products I work on lately) often do. And they also have to install interrupt handlers, and catch hardware exception signals, and other fun stuff.

When the language permits scary behaviors (and all that stuff is scary), the investment in careful construction and review is warranted. The problem with free software is that it is a Tragedy of the Commons.

Re: Fair cop

But, I say absent certain knowledge, I bet that they don't get so cozy with the hardware

Don't actually know the answer in this particular case, but the general answer for Scala is: if Java can do it, Scala can do it. (And if not, not.) For better and worse, Scala tied its fate to the JVM. (Which gives it easier access to many more toys than Haskell, at the cost of some elegance.)

And while, yes, there are definitely some major areas where C is still the right answer, they're receding pretty steadily. Performance is rarely a convincing argument any more -- the compilers for the high-level languages can generally do better than most people rolling hand-coded C -- although I agree that hardware access often still is.

In this particular case, the argument is a little subtler. I doubt that performance or hardware access are actually worth writing it in C -- but depending on a VM would rule it out for many of the places where it is being used. I'm actually not sure what the best answer is nowadays for coding a native-compiled library...