Many of the most pernicious security exploits in modern software arise from buffer overflows, especially those buffers or variables that are automatically allocated on stacks.
The problem in C (et al) is the concept of an “data-bounded” string, ie, the NULL termination of strings. This runs counter to how strings are allocated in most higher-order languages, where there is a string descriptor or array that the compiler knows is “X so big” and attempts to cram too many characters into the string are caught both at compile time and at run time. In C, there’s no actual bound to the size of a string that the compiler really can enforce. If you allocate an array type for the string, you can use a pointer reference to access the string and write off the end of the string without any warning or exception.
This gives you an idea of how widespread the problem is:
http://web.nvd.nist.gov/view/vuln/search?execution=e2s1
Enter “buffer” in the “Keyword search” box and hit “Search All” - and wait a little while, because it is searching a pretty big DB. You’ll see two things:
1. There are buffer overflows all over the product/platform space. MS, Apple, Google... everyone has buffer overflows.
2. The severity level is usually “high” - meaning that the error can usually be exploited to gain access.
When a buffer overflow is coupled with a system like Windows where the typical user is running as an Administrator.... it’s game over. The exploit can then do pretty much anything it wants.
So how did we get here?
In the 80’s, software vendors were looking for a language that would allow rapid development of software that could touch hardware on microprocessor based systems. Enter C, which was really nothing more than a high level assembler on Unix’s initial implementation on PDP-11’s. For those of us who started on PDP-11’s, you can show us a line of C and we can write out what the assembly code will look like as a result of that line - and 99% of the time, I’ll have it nailed down to the instruction and order of instructions. With modern chipsets, I can’t do that, but C started on PDP-11’s and the PDP-11’s addressing modes influenced the design of C quite a bit.
Being that C is little more than a high-level assembler, there is little to no checking of constraints at run time, because there are few constraints encoded in the source. The whole of C/Unix was sort of a “up yours” response to the Multics OS, which was much larger, much more complicated and written in PL/I. Multics was, however, quite secure.
There is no run-time array bounds checking in C and C-derived languages unless you add in the facility yourself. You can add this with some programming in C++, but it is clunky and not a part of the base language. If we’re going to have run-time bounds checking, it has to be mandatory - not a compile-time switch that has to be enabled (or that can be disabled), and it has to be uniform. We can’t have one shop define their C++ bounds-checked strings one way, and another shop do their “smart strings” differently.
Ada provides run-time constraint checking; when you try to overwrite the end of strings, the run time system throws an exception. There is a good exception handling facility in the language for the programmer to handle other exceptions within the software - in C, there’s only setjmp()/longjmp() and in C++, there’s try... both very mediocre (at best) exception handling.
Here’s a great little example of how mediocre:
http://stackoverflow.com/questions/167199/what-c-c-tools-can-check-for-buffer-overflows
A half-dozen different approaches for something the compiler just does in many other languages.
What Ada brings to the table is strong type checking, strong run time checking and strong exception handling. For a C programmer converting to Ada, getting his first program to compile and link is like getting a root canal. Ada wants things specified down to a gnat’s ass, and C programmers are used to playing fast and loose with type conversions/promotions, interfaces, etc, getting their programs to compile quickly and easily.... and then they start discovering their errors at run time.
When you develop with Ada, the compiler barks at you again and again, requiring that the interfaces, data visibility, types, etc are consistent throughout the program. Very tight compile-time checking is the rule of the day. It can take quite a long time to get the source to compile... but then when it finally does, the program often “just works” without the usual experience C programmers are used to, where it starts running and then there’s a run-time blowup that has to be found and debugged.
As I said, I view security exploits as software reliability failures. There was a bug, someone found it and exploited it to their end. In Windows, for example, there are buffer overruns a-plenty, and again, coupled with the number of people running as Admin... it makes for a very easily exploited system. Unix certainly has the same buffer overflow issues, but unless the exploited program is running with suid, or the user is running as root, the escalation of the exploit is limited.
I’ve developed s/w for more than 25 years, in over a dozen languages and on a dozen+ operating systems. I’ve been around this block a few times. Software errors become security problems very quickly now, and on better systems with better programming languages, the types of exploits we commonly see today were rare by today’s standards.
Wow, a long an interesting comment I must say... You are right on some of your points, but really, all language compilers are the problem for overflow checking, not the language. Yes, Ada had some benefits, and some problems, after all, it was NOT really decided that it would be the language of the future but a government decision - good luck there...
Actually, I think the major problem is that the military suddenly realized that almost all of their proprietary code was written in Fortran and they panicked, as they should - after all, the government is about 40 years behind in advanced programming languages - so Ada became the choice of the future.
Of course, today, Ada is obsolete and has little to do with government...so, what will they proclaim next as the language of the future? You don’t really think that the backward government has any clue as to what will suffice for programming now do you really?
Keep your Ada skills though, they may be valuable for the next 40 years or so if the government has any say...
“The problem in C (et al) is the concept of an data-bounded string, ie, the NULL termination of strings.”
Yes, this is a common problem - a programming problem that later programmers expect compilers to correct. It is too bad that bad programmers have given this problem its name.
And no, most programmers today have no idea how to code the segment in assembly language - after all, that is what high level languages are about. Don’t expect that schools teach assembly equivalent to these high level language students.
“Being that C is little more than a high-level assembler, there is little to no checking of constraints at run time, because there are few constraints encoded in the source.”
Very TRUE! That is exactly “C” or “C++” is still in vogue. It retains the ability to go low level where most high level languages do not.
“There is no run-time array bounds checking in C and C-derived languages unless you add in the facility yourself.”
Sorry, that is a Compiler problem and has been much improved in recent years - not like my younger days.
“Ada provides run-time constraint checking; when you try to overwrite the end of strings, the run time system throws an exception.”
Yes, but it does add overhead and sometimes poor compilation but what the heck, it’s a government issue... Of course, it does not allow the lower level handling that is built into C either...
“What Ada brings to the table is strong type checking, strong run time checking and strong exception handling. For a C programmer converting to Ada, getting his first program to compile and link is like getting a root canal.”
Sorry, that is a programmer problem that your are describing, not a language issue...
“When you develop with Ada, the compiler barks at you again and again,”
Of course, what you are saying is that as a programmer, you need Compiler help in creating the correct code because you are not up to speed...
“Ive developed s/w for more than 25 years, in over a dozen languages and on a dozen+ operating systems.”
Well, then I would expect that you could program in any language with problems - no need to the compiler to catch your laziness...
By the way... I have programmed in Ada and thought it much like Pascal. High level and limited but easy to program.