Cough, there's one major thing all of these bugs have in common - they're all in C code.
This is mostly due to the volume and prominence of C. But a language with the same fundamental semantics of C but lacking the cleverbait syntax and weakened types would have prevented over half of these mistakes.
I would be more willing to blame C if these bugs were unsafe memory operations. Unused parameters, logic errors and assignment instead of comparison aren't unique to C and the language isn't without counter measures for them.
The X one is probably the only very C bug on the list and compiler warnings and/or a good static code checker would have found it.
I deliberately did not address unsafe memory operations, because the current widely-accepted state of the art for memory safety is garbage collection, which has significant overhead. I could have also tooted the horn for Rust (or Felix/BitC/Deca), but my goal was not to point out blank-slate solutions, but just how much of C itself could be trivially fixed.
Among others the Objective-C crowd might want to have a chat with you about it being the "widely-accepted state of the art." This is ignoring the fact that memory management does not really address C's ability to do unsafe memory operations as much as its just resource management.
I really should have said garbage collection + RAII. I'm not saying that GC is accepted by everyone, just among the people working in current memory-safe languages. (Or are you saying that ObjC does something even better that's yet to catch on?)
It's not so much about a language's ability to do unsafe memory operations, but the necessity of doing them to write useful code in the language.
The compiler could have prevented 'X' by not permitting "function == int" comparisons. That's 1/5.
The only thing you might be referring to with "cleverbait syntax" is the ++ fix in tarsnap, but note that the bug was not including ++. Being generous, we could say that if ++ wasn't allowed, it might have been more obvious that the code was broken, getting us 2/5. And being extra generous, maybe if `!i` was disallowed, they would have gone straight for `i <= 0` instead of `i != 0`. So 3/5, but yeah, dubious.
The only other one that's remotely like a C misfeature is that the compiler apparently didn't warn about 'unused parameter' in the Android bug.
Yes, those are the three I am referring to, but I don't agree that any are generous or dubious. Out of the C context, what does "not integer" possibly mean? `i` should either have been a boolean, or apparently an explicit multi-state enum, rather than the ever-favored weakly-typed ubiquitous `int` that C makes so attractive.
I'm not claiming the unused parameter bug, because there can be legitimate unused function parameters, and we can easily envision a very similar bug that still used all parameters.
But add in the current Apple bug that precipitated this post, and you have 4/6.
The general defense by C programmers is that everything works as long as you do the right thing. I have been there. However as these bugs illustrate, vigilance does not scale.
C has enums, and it's true that they can be implicitly used as ints and sometimes that can be bad, but here they just weren't used. I'm not sure what you think C could have done differently. It's not obvious to me that the current enums aren't good enough for this particular purpose, for example. This feels more like a culture thing than a language thing.
And note that 2/3 of the bugs you're claiming, apply to all weakly typed languages, of which there are many. Python would not have prevented them, for example. Showcasing them as problems with C seems somehow fishy. (I don't mean to imply dubious motivations on your part, I just get the feeling of "there's something not quite right with this argument".)
A lot of it is culture, but I feel that culture fuels itself with the tricks available in the language. It just feels so clever to use the return value of `i++` - number of lines matters one-level down in ASM, so why not here. And things like `if (!i)` are quite cute, while being hard to aggregate unions of existing types, so return-value definitions especially tend to stay informal.
You're right about my analysis applying to all weakly typed languages, or at least languages with weakly-typed core functions. Python pretty much only brings memory safety to the table (which as I said in a sibling comment has an actual overhead so I didn't touch upon it here). But it does show that the Tarsnap and the Apple bug are caused by syntax, which is a pretty heavy indictment.
> The compiler could have prevented 'X' by not permitting "function == int" comparisons. That's 1/5.
0 is also a special case litteral for the null pointer, and function names are valid in pointer contexts, so I'm not even sure that "f == 0" is badly typed.
Yes, many tools have been built to address the problems with C, and one is remiss if they ignore the greater development ecosystem.
But, that they're not integrated into the language itself means those tools can only ever make suggestions in a separate context, and so cannot function cohesively to permanently rule out classes of bugs in a way that can simply be taken for granted.
In fact, the Debian OpenSSL bug was actually caused [1] by a message from one of these tools being uncritically acted upon.
[1] the job of failure analysis is to find all contributing factors, not just pin everything on one.
Static code analysis tools exist in many languages even very high level, safe ones. A lot of them are even named after lint or as a tip of the hat to it.
Their presence isn't a sign of flaws of the language. They are signs of flaws in programmers. They give the designers the ability to extend the power of the compiler's warnings to help catch common mistakes and tune the automated feedback to fit the needs of the project.
Sure, but static analysis can only add so much, as the programmer is still working in the base language and can't convey higher level concepts to the static analysis tool, so it's forced to backfit them by guessing intent. And to the extent you can make annotations for this, you're effectively working in a new formal language without the benefit of a compiler.
This is mostly due to the volume and prominence of C. But a language with the same fundamental semantics of C but lacking the cleverbait syntax and weakened types would have prevented over half of these mistakes.