Module: Memory Errors
Causes of Corruption
Yan Shoshitaishvili
Arizona State University
Cause: Classic Buffer Overflow
Because C does not implicitly track buffer sizes, simple overwrites are common.
Smallest possible example:
int main(int argc, char **argv, char **envp)
{
char small_buffer[16];
read(0, small_buffer, 128);
}
Let's look at a demo!
Cause: Signedness Mixups
The standard C library uses unsigned integers for sizes (i.e., the last argument to read, memcmp, strncpy, and others). The default integer types (short, int, long) are signed.
int main() {
int size;
char buf[16];
scanf("%i", &size);
if (size > 16) exit(1);
read(0, buf, size);
}
Why is this a problem? Recall twos compliment:
Guess which one is used in this code?
Cause: Integer Overflows
When developers try to calculate sizes, mistakes can occur...
Consider:
int main() {
unsigned int size;
scanf("%i", &size);
char *buf = alloca(size+1);
int n = read(0, buf, size);
buf[n] = '\0';
}
Cause: Off-by-one Errors
Consider:
int a[3] = { 1, 2, 3 };
for (int i = 0; i <= 3; i++) a[i] = 0;
Off-by-one errors can cause small amounts of memory corruption.
Depending on what you corrupt in memory, this can be disastrous.
stack
return address
saved rbp
local variable
local variable
return address
saved rbp
local variable
local variable
return address
saved rbp
local variable
local buffer
stack
return address
saved rbp
local variable
local variable
return address
saved rbp
local variable
local variable
return address
saved rbp
local variable
local buffer