Memory Allocation III CSE 351 Autumn 2016
Memory-Related Perils and Pitfalls in C
1
Slide Program stop
possible? Fixes:
A) Dereferencing a non-pointer
B) Freed block – access again
C) Freed block – free again
D) Memory leak – failing to free memory
E) No bounds checking
F) Reading uninitialized memory
G) Referencing nonexistent variable
H) Wrong allocation size
CMPT 295
L23: Memory Allocation III
Find That Bug! (Slide 2)
2
char s[8];
int i;
gets(s); /* reads “123456789” from stdin */
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
No bounds checking
Segfault, security flaw (buffer overflow!)
Fix: use fgets()
Find That Bug! (Slide 3)
3
int* foo() {
int val = 0;
return &val;
}
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Referencing nonexistent variable
No segfault (unless casting to pointer & deref), no security flaw (except in very strange case)
Fix: allocate val dynamically, rather than as a local variable.
Find That Bug! (Slide 4)
N and M defined elsewhere (#define)
4
int **p;
p = (int **)malloc( N * sizeof(int) );
for (int i = 0; i < N; i++) {
p[i] = (int *)malloc( M * sizeof(int) );
}
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Wrong allocation size
Segfault, no security flaw
Fix: p = malloc(N * sizeof(int *))
Find That Bug! (Slide 5)
A is NxN matrix, x is N-sized vector (so product is vector of size N)
N defined elsewhere (#define)
5
/* return y = Ax */
int *matvec(int **A, int *x) {
int *y = (int *)malloc( N*sizeof(int) );
int i, j;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
y[i] += A[i][j] * x[j];
return y;
}
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Reading uninitialized memory
No segfault, no security flaw
Fix: explicitly zero y[i], or use calloc()
Find That Bug! (Slide 6)
The classic scanf bug
int scanf(const char *format)
6
int val;
...
scanf("%d", val);
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Dereference a non-pointer
Segfault, security flaw
Fix: &val, not val
Find That Bug! (Slide 7)
7
x = (int*)malloc( N * sizeof(int) );
// manipulate x
free(x);
...
y = (int*)malloc( M * sizeof(int) );
// manipulate y
free(x);
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Freed block – free again
Program aborts (but not a segfault), no security flaw
Fix: free(x) just once, fix typo to free(y)
Difficult to diagnose / resolve because free() itself doesn’t (can’t) return any errors – errors are only encountered later on!
Find That Bug! (Slide 8)
8
x = (int*)malloc( N * sizeof(int) );
// manipulate x
free(x);
...
y = (int*)malloc( M * sizeof(int) );
for (i=0; i
head->next = NULL;
// create and manipulate the rest of the list
…
free(head);
return;
}
Error Prog stop Fix:
Type: Possible?
CMPT 295
L23: Memory Allocation III
Memory leak
No program stop, no security flaw
Fix: save next = head->next before free(head), then free next (and all other nodes following it) too…
Dealing With Memory Bugs
Conventional debugger (gdb)
Good for finding bad pointer dereferences
Hard to detect the other memory bugs
Debugging malloc (UToronto CSRI malloc)
Wrapper around conventional malloc
Detects memory bugs at malloc and free boundaries
Memory overwrites that corrupt heap structures
Some instances of freeing blocks multiple times
Memory leaks
Cannot detect all memory bugs
Overwrites into the middle of allocated blocks
Freeing block twice that has been reallocated in the interim
Referencing freed blocks
10
Non-testable Material
CMPT 295
L23: Memory Allocation III
Dealing With Memory Bugs (cont.)
Some malloc implementations contain checking code
Linux glibc malloc: setenv MALLOC_CHECK_ 2
FreeBSD: setenv MALLOC_OPTIONS AJR
Binary translator: valgrind (Linux), Purify
Powerful debugging and analysis technique
Rewrites text section of executable object file
Can detect all errors as debugging malloc
Can also check each individual reference at runtime
Bad pointers
Overwriting
Referencing outside of allocated block
11
Non-testable Material
CMPT 295
L23: Memory Allocation III