One thing that hasn’t been mentioned is that interchanging signed/unsigned numbers can lead to security bugs. This is a big issue, since many of the functions in the standard C-library take/return unsigned numbers (fread, memcpy, malloc etc. all take size_t
parameters)
For instance, take the following innocuous example (from real code):
//Copy a user-defined structure into a buffer and process it
char* processNext(char* data, short length)
{
char buffer[512];
if (length <= 512) {
memcpy(buffer, data, length);
process(buffer);
return data + length;
} else {
return -1;
}
}
Looks harmless, right? The problem is that length
is signed, but is converted to unsigned when passed to memcpy
. Thus setting length to SHRT_MIN
will validate the <= 512
test, but cause memcpy
to copy more than 512 bytes to the buffer – this allows an attacker to overwrite the function return address on the stack and (after a bit of work) take over your computer!
You may naively be saying, “It’s so obvious that length needs to be size_t
or checked to be >= 0
, I could never make that mistake”. Except, I guarantee that if you’ve ever written anything non-trivial, you have. So have the authors of Windows, Linux, BSD, Solaris, Firefox, OpenSSL, Safari, MS Paint, Internet Explorer, Google Picasa, Opera, Flash, Open Office, Subversion, Apache, Python, PHP, Pidgin, Gimp, … on and on and on … – and these are all bright people whose job is knowing security.
In short, always use size_t
for sizes.
Man, programming is hard.