Most programming environments are meta-engineered to make typical software easier to write. They should instead be meta-engineered to make incorrect software harder to write. An operation that is not exactly what I normally want should take more work to express than an operation that is exactly what I normally want. There are occasions when I really do want arithmetic modulo 2**32 (or 2**64), but I am happy to do extra work on those occasions.He brings up a good point there. In this example, when two numbers are added, the compiler can figure out if the result turns out to be smaller than one (or both) of the operands. Is the behavior we currently get, silent overflows, what we would prefer? And if not, why aren't our compilers taking more activist choices in a deterministic case?
Bernstein doesn't talk about talent in the area of writing bug-free lines of code, he instead talks about making choices to limit factors such as the amount of code and the amount of trusted code. Extending this idea, he advocates programming languages that make it more difficult to write incorrect code, and compilers that perform extended checks. In the same sense that strict and warnings are not necessary pragmas in Perl if your code is perfect, culturally we support their use anyways, we could prefer the same helping hand from C compilers.
Nowadays I am much more insistent on programming-language support for smaller-scale partitioning, sane bounds checking, automatic updates of "summary" variables (e.g., "the number of nonzero elements of this array"), etc. By "sane bounds checking" I don't mean what people normally mean by "bounds checking," namely raising an exception if an index is out of range; what I mean is automatic array extension on writes, and automatic zero-fill on reads. (Out of memory? See Section 4.2.) Doing the same work by hand is silly.Languages providing strong support for those issues and others, and making them easy to use and well-integrated, can greatly limit security vulnerabilities in those areas.
We are fundamentally less likely to create software vulnerabilities due to the simple revolution of using an SvPV (a structure containing an integer for length and a character array) instead of a null-terminated character array, and only allowing userland (i.e. non-XS) access through a provided API. We can do something right and partake in enforced code reuse.
Additionally, our choice of programming language frames our focus in programming. The issues we need to focus on when programming in C are not entirely the same as the issues brought to our attention in Perl.
This may all seem obvious, but we still believe strongly in the responsibility of the individual to code well regardless of the environment he is in. This is ideal, but not realistic. People make mistakes. Limiting those mistakes through code reuse, and finding them through peer review, are benefits provided by using progressive languages that don't require you to resculpt your wheel continually. People should be responsible for the environment choices they make - what they do for their security karma regardless of how well they code an average statement.
Languages need to be held responsible for the types of code problems they encourage, the frame of the debate, because it is at underlying language and system levels that the security context is first defined.
UPDATE: Fixed quoting as blazar suggested