(The one exception may be, like, DJB. But djbdns/qmail are very unusual C programs in many ways.)
It's not so much that it requires smarts. It's that is requires you to be ever-vigilant and to never make any mistakes. (That's why UB and bounds overflows are so devastating to software security. Almost any slip-up by the developers can be exploited.)
Incidentally, the ever-vigilant bit is also why we really want compilers to be doing the bounds-checking (or proving that it isn't necessary). Compilers are really good at being ever-vigilant. Humans (no matter how smart)... not so much.
There goes the price of freedom. Drats.
Amen to that! If I could just add one feature to C - at least as an option - it would be array bounds checks.
I have no trouble with manual memory management - a garbage collector is nice to have, but I have not had many problems with memory leaks or dangling pointers. And the ones I had were relatively easy to locate and fix.
But array bounds violations are so easy to commit and so nasty to track down... When I still wrote C code for a living, I would have gladly sacrificed quite a bit of performance to get bounds checks on all array accesses, at least for testing and debugging...
Note that every single browser vulnerability in this year's Pwn2Own was a use after free (dangling pointer).
Plus, what a browser does is, by nature, a lot more complicated than what I worked on.
EDIT: What I am trying to say is: I do not mean to trivialize use-after-free bugs, but in my personal experience, I did not run into many, while I witnessed (and caused, I am afraid) a bunch of array bounds violations, and they sometimes made me want to cry.
You don't want to be writing your interpreters in C.
Well, technically, I think most browsers these days are written in C++, but your point remains valid.
OTOH, the "default" Python interpreter is written in C, and so is Perl (Ruby MRI, too, I think, but I am not 100% certain). I cannot recall any major security problem with those languages that originated inside the interpreter (which, of course, does not mean those did not/do not exist). Then again, a web browser is probably far messier in terms of what input is has to deal with.
That's the ticket, the browser does have a large attack surface but more importantly it's supposed to safely execute completely arbitrary and untrusted payloads. In the same category are pretty much all of the usual suspect of security issues: flash, java (applets), …
Most interpreters are only fed trusted payloads, lest the developer starts eval'ing stuff they got from god knows where, and in that case the fault is usually laid to the developer's feet rather than the interpreter's.
The promise of rust, which may or may not be realized is pushing some very common problems down to the compiler. All code has bugs, so the compiler probably does things wrong in some cases. As the tools mature, these will get scrubbed out, just like every other project.
That said, array bounds checking is responsible for so many problems, it seems worth it to raise the minimum for a language. Not every developer is elite. In fact, they're pretty rare. C requires you to be really smart all the time, or at least be aware of when you're not smart enough to get a chunk of code right. Looping over some bytes from a file shouldn't be that risky. rust lets me, a less than elite developer, save my few moments of brilliance for the hard part of a program, rather than having to worry about the evaluation order of foo(i++,i++);
Maybe, it'll turn out the only way to make good software in the future is to find the best 100 developers in the world, and get them to make stuff. I doubt it though, being able to leverage the other million of us to make stuff, and have some (a lot?) of confidence it'll be free from the most common C errors is valuable.
Nobody should be forced to use tools they don't like. rust is trendy, but it has some very good ideas. Trendyness isn't reason alone to dismiss its approach. blah blah rust cheerleading blah blah.