- Vectors
- Atomic Operations
- Bit Operations
- Branch on Condition
- Sensible Scoping
- Thread-Local Variables
- A Real Preprocessor
- Summary
Branch on Condition
A couple of years ago, the OpenSSH team discovered a new kind of vulnerability resulting from integer overflows. Code would look something like this:
foo = malloc(a * b);
An attacker with some control over a or b could cause the value of the multiplication to overflow, so malloc would be passed a much smaller number than the programmer expected. Data would then be written past the end of the allocated space early on, giving a nice way for an attacker to inject arbitrary code.
This was a problem because it’s not easy to check the condition flags that are set as the result of an operation. It ought to be possible to write the following:
if(!overflow(a*b)) { foo = malloc(a*b); } else { //Handle error; }
This kind of thing can be done fairly trivially in assembly. Every arithmetic operation results in the flag being set if it overflows. You could try implementing this in a library, but it’s prone to error. The compiler is likely to translate this into an add, then a store, then a call. The call or the store could reset the condition register (depending on the architecture). As such, this needs to be something defined at the language level, because only the compiler can know not to insert anything that clobbers the condition register in the correct place.
Of course, you could write inline assembly for every architecture you support, which provides a "multiply and check for overflow" routine, but this would be a lot of effort and removes a large part of the point of C—being a cross-platform assembler.