detecting memory errors using compile time techniques nurit dor mooly sagiv tel-aviv university
Post on 21-Dec-2015
223 views
TRANSCRIPT
Detecting Memory Errors usingCompile Time Techniques
Nurit Dor
Mooly Sagiv
Tel-Aviv University
Memory errors
Hard to detect– point of failure is not point of error
– difficult to reproduce
– Depends on the system’s architecture
Many result from pointer misuse Other types: out of bound reference
Usage of dead storagemain()
{ int *x,*z;
x = (int *)malloc(sizeof(int));
free(x);
z = (int *)malloc(sizeof(int));
if (x==z)
printf(“ unexpected equality”);
}
usage of deallocated storage
Dereference of NULL pointerstypedef struct element {
int value;
struct element *next;
} Elements
bool search(int value, Elements *c) {Elements *elem;for ( elem = c; c != NULL;elem = elem->next;)
if (elem->val == value)
return TRUE;
return FALSE
NULL dereference
Dereference of NULL pointerstypedef struct element {
int value;
struct element *next;
} Elements
bool search(int value, Elements *c) {Elements *elem;for ( elem = c; elem != NULL;elem = elem->next;)
if (elem->val == value)
return TRUE;
return FALSE
Memory leakage
Elements* reverse(Elements *c){
Elements *h,*g;h = NULL;while (c!= NULL) {
g = c->next;h = c;c->next = h;c = g;}
return h;
leakage of address pointed-by h
Memory leakage
Elements* reverse(Elements *c){
Elements *h,*g;h = NULL;while (c!= NULL) {
g = c->next;
c->next = h;
h = c;c = g;}
return h;
Cleanness Rules that a program must obey Does not depend on a program’s specification Precondition rules for each statement type Some cleanness rules are integrated into the
programming language:– Type checking
– Array bound accesses
– Java dereference
Other cleanness rules are programmer responsibility
Run-Time vs. Static
Property Run-Time Conservative
Static
Manual runs
Depends on test cases
Assures against bugs
Interferes production
False alarms
Scales for large programs ? ?
Shape graph
Example
Characteristics– finite representation– “sharing” of run-time locations by:
“pointed-to by” and “reachable from” variables
1 2 3 5 7 11 13c
elem
c
elem
NULL
NULL
Shape analysis
Initialization - empty shape graph Iteratively apply every program statement and
condition Stop when no more shape graphs can be derived
Cleanness checking via shape analysis
Compute a set of possible shape graphs before every program statement
Check cleanness condition of every statement against any possible shape graph
Cleanness conditions are generated in a syntax directed fashion
Report violations with the “witness” shape graph
Abstract interpretation
state ’
Operational semantics
statement s
abstract representation
state
concretization
Abstractsemantics
statement s abstract representation’
abstraction
Dereference of NULL pointerstypedef struct element {
int value;
struct element *next;
} Elements
bool search(int value, Elements *c) {Elements *elem;for ( elem = c; c != NULL;elem = elem->next;)
if (elem->val == value)
return TRUE;
return FALSE
NULL dereference
c
elem NULL
c NULL
c NULL
elem
elem
elem= elem next
elem= elem next
c NULL
c NULL
elem
elem
c NULL
c NULL
elem
elem
c NULL elem
X
Implementation PAG (Program Analysis Generator)
– C front-end
– Supply transfer functions and abstract representation
Input– C program under restrictions
» no recursion» no pointer arithmetic or casting
Output– graphical presentation of shape graphs
– list of potential cleanness violations
Points-To analysis
Program analysis that computes information regarding the pointers in the program
Point-to pairs (p,a) p = &a; “ p points-to a”
Heap treatment (p,heapl):l: p= malloc(...) “ p points-to heapl - heap address
allocate at this statement”
Empirical resultssec / leakage false alarms
Program Shape Analysis Points-to
search.c 0.02/0 0.01/5
null_deref.c 0.03/0 0.02/5
delete.c 0.05/0 0.01/7
del_all.c 0.02/0 0.01/6
insert.c 0.02/0 0.03/7
merge.c 2.08/0 0.01/8
reverse.c 0.03/0 0.01/7
fumble.c 0.04/0 0.02/6
rotate.c 0.01/0 0.01/5
swap.c 0.01/0 0.01/5
Empirical resultssec / reference+dereference false alarms
Program Shape Analysis Points-to
search.c 0.02/0 0.01/0
null_deref.c 0.03/0 0.02/0
delete.c 0.05/0 0.01/0
del_all.c 0.02/0 0.01/4
insert.c 0.02/0
merge.c 2.08/0 0.01/5
reverse.c 0.03/0 0.01/0
fumble.c 0.04/0 0.02/0
rotate.c 0.01/0 0.01/1
swap.c 0.01/0 0.01/0
0.03/1
False alarms
Abstraction not precise enough – acyclic lists
– trees
Infeasible paths
Advantage
Detection of non trivial bugs Easy to use:
– Minimal false alarms (No false alarms on many linked list programs)
– Minimal user interactions(No annotations)
– Graphical output of control-flow graph and shape graphs
Significantly faster than verification tools
Challenges
Scaling for large programs– Annotations
– Cheaper preprocessing
– Better interprocedural analysis
– Other programming languages
– Ignore unlikely cases - losing conservative
Other data structures (trees, cyclic lists) Applications that can benefit from this