Sloppy coding can be done in any language, but C and C++ have 3 features that aggravate the problem:
1. The "array=pointer" idiom. Given a parameter which is an array, you can't ask at run-time how big the array is - you have to do extra work and pass the size in an additional parameter (whereas most languages pass the size of an array automatically as part of the array). So doing buffer overflow checks requires more than just inserting the check - you have to make sure that an extra "array size" parameter is passed all the way down the call stack. [C and C++ cannot be considered strongly typed, in part because of the lack of distinction between pointers and arrays]. 2. By permitting pointer arithmetic, C and C++ encourage you to pass a pointer into the middle of a buffer, rather than passing the [start of the] buffer and an index into it, which makes bounds checking even more tedious to do (you have to pass a pointer to one-past-the-end-of-the-array as well, and even then this is less useful than having an index and a limit). 3. The lack of automatic bounds checking. Of course, run-time bounds checking is by no means a complete solution, but it does at least prevent a buffer overflow being used as a security attack, turning it into a denial-of-service attack instead. Apart from the obvious solution of choosing another language, there are at least two ways to avoid these problems in C++: 1. Ban arrays (to quote Marshall Cline's "C++ FAQ Lite", arrays are evil!). Use classes from the STL, or another template library instead. Arrays should be used only in the template library, where their use can be controlled. 2. If you really must have naked arrays, ban the use of indexing and arithmetic on naked pointers to arrays (i.e. if p is a pointer, then p[x], p+x, p-x, ++p and --p are all banned). Instead, refer to arrays using instances of a template class "Array<X>" that encapsulates both the pointer (an X*) and the limit (an unsigned int). Such an object needs only 2 words of storage (compared to 1 word for a naked pointer), so it can assigned and passed by value. You can provide an operator to return the value of the limit, and an indexing operator (with optional bounds checking). If you really must, you can even implement "pointer arithmetic" operators for the class which update the limit at the same time as updating the pointer. David Crocker Consultancy & contracting for dependable software development www.eschertech.com