1
Shape Analysisvia 3-Valued Logic
TVLA + ApplicationsMooly Sagiv
Tel Aviv University
http://www.cs.tau.ac.il/~rumster/TVLA/
Shape Analysis with Applications
2
Outline
Basic ideas behind TVLA TVLA for Singly Linked Lists Reachability Applications (next week)
3
The TVLA System
Input:– SOS using Predicate Logic
– Control Flow Graph
– A set of 3-valued structures at the start node
– Implementation hints
Output– The set of 3-valued structures at every control flow
node (labeled directed graphs)
– Textual error messages
TVP
TVS
4
tvla create include\empty -d
/* create.c */
Elements create() {
Elements *f, *x;
int i, size;
for(i=0; i<size; i++) {
f = malloc(sizeof(Elements));
f->n = x;
x = f;
}
return x;
}
c2tvp create
/* list.h */typedef struct node { struct node *n; int data} *Elements;
tvla create include\empty
5
tvla reverse include\list
c2tvp reverse
typedef struct node { struct node *n; int data;} *Elements;
Elements * reverse(Elements *x) { Elements *y, *t; y = NULL; while (x != NULL) { t = y; y = x; x = x n; y n = t; }return y;}
6
/* reverse.tvp */
%s PVar {x, y, t}
#include "include\pred.tvp"
%%
#include "include\cond.tvp"
#include "include\stat.tvp"
%%
// y = NULL
n_1 Set_Null_L(y) n_2
// while (x != NULL) {
n_2 Is_Null_Var(x) exit
n_2 Is_Not_Null_Var(x) n_3
// t = y
n_3 Copy_Var_L(t, y) n_4
// y = x
n_4 Copy_Var_L(y, x) n_5
// x = x->n
n_5 Get_Next_L(x, x) n_6
// y->n = NULL
n_6 Set_Next_Null_L(y) n_7
// y->n = t
n_7 Set_Next_L(y, t) n_2
// }
7
/* create.tvp */
%s PVar {x, f}
#include "include\pred.tvp"
%%
#include "include\cond.tvp"
#include "include\stat.tvp"
%%
// for(i=0; i<size; i++) {
n_1 uninterpreted() n_2
// f = malloc(sizeof(Elements));
n_2 Malloc_L(f) n_3
// f->n = x;
n_3 Set_Next_Null_L(f) n_4
n_4 Set_Next_L(f,x) n_5
// x = f;
n_5 Copy_Var_L(x, f) n_1
n_2 uninterpreted() exit
// }
8
/* pred.tvp */
/*************** Core Predicates *************/
foreach (z in PVar) {
%p z(v_1) unique box
}
%p n(v_1, v_2) function
/**********************************************/
/*********** Instrumentation Predicates *************/
%i is[n](v) = E(v_1, v_2) ( v_1 != v_2 & n(v_1, v) & n(v_2, v))
9
/* cond.tvp */
%action uninterpreted() {
%t "uninterpreted"
}
%action Is_Not_Null_Var(x1) {
%t x1 + " != NULL"
%f { x1(v) }
%p E(v) x1(v)
}
%action Is_Null_Var(x1) {
%t x1 + " == NULL"
%f { x1(v) }
%p !(E(v) x1(v))
}
%action Is_Eq_Var(x1, x2) {
%t x1 + " == " + x2
%f { x1(v), x2(v) }
%p A(v) x1(v) <-> x2(v)
}
%action Is_Not_Eq_Var(x1, x2) {
%t x1 + " != " + x2
%f { x1(v), x2(v) }
%p !A(v) x1(v) <-> x2(v)
}
10
stat.tvp%action Set_Null_L(x1) {
%t x1 + " = NULL"
{
x1(v) = 0
}
}
%action Copy_Var_L(x1, x2) {
%t x1 + " = " + x2
%f { x2(v) }
{
x1(v) = x2(v)
}
}
%action Malloc_L(x1) {
%t x1 + " = (L) malloc(sizeof(struct node)) "
%new
{
x1(v) = isNew(v)
}
}
11
stat.tvp (2)%action Get_Next_L(x1, x2) {
%t x1 + " = " + x2 + "->" + n
%f { E(v_1) x2(v_1) & n(v_1, v) }
%message (!E(v) x2(v)) -> "an illegal dereference to\n" +
n + " component of " + x2 + "\n"
{
x1(v) = E(v_1) x2(v_1) & n(v_1, v)
}
}
12
stat.tvp (3)
%action Set_Next_Null_L(x1) {
%t x1 + "->" + n + " = null"
%f { x1(v) }
%message (!E(v) x1(v)) -> "an illegal dereference to\n" +
n + " component of " + x1 + "\n"
{
n(v_1, v_2) = n(v_1, v_2) & !x1(v_1)
is[n](v) = is[n](v) & (!(E(v_1) x1(v_1) & n(v_1, v)) |
E(v_1, v_2) v_1 != v_2 &
(n(v_1, v) & !x1(v_1)) & (n(v_2, v) & !x1(v_2)))
}
}
13
stat.tvp (4)
%action Set_Next_L(x1, x2) {
%t x1 + "->" + n + " = " + x2
%f { x1(v), x2(v) }
%message (E(v, v1) x1(v) & n(v, v1)) ->
"Internal Error! assume that " + x1 + "->" + n + "==NULL"
%message (!E(v) x1(v)) -> "an illegal dereference to\n" +
n + " component of " + x1 + "\n"
{
n(v_1, v_2) = n(v_1, v_2) | x1(v_1) & x2(v_2)
is[n](v) = is[n](v) | E(v_1) x2(v) & n(v_1, v)
}
}
14
Typical Garbage Collector
Program
Variables
a
b
c
d
e
f
Reachability-based
15
Program
Variables
a
b
c
d
e
f
Typical Garbage Collector Reachability-based
16
Typical Garbage Collector
Program
Variables
a
b
c
d
e
f
Reachability-based
17
Reachability
Concrete semantics which records reachability from stack (global) variables
Useful for:– Compile-time Garbage Collection
– Saving calls to Dynamic Garbage Collection» No memory leaks
– Speeding-up static analysis
Instrumentation predicater[n, x](v) = E(v1) x(v1) & n*(v1, v)
18
/* create.c */
Elements create() {
Elements *f, *x;
int i, size;
for(i=0; i<size; i++) {
f = malloc(sizeof(Elements));
f->n = x;
x = f;
}
return x;
}
c2tvp create
/* list.h */typedef struct node { struct node *n; int data} *Elements;
tvla rcreate include\empty
19
tvla rreverse include\rlist
c2tvp reverse
typedef struct node { struct node *n; int data;} *Elements;
Elements * reverse(Elements *x) { Elements *y, *t; y = NULL; while (x != NULL) { t = y; y = x; x = x n; y n = t; }return y;}
20
tvla rfumble include\rlist
c2tvp fumble
typedef struct node { struct node *n; int data;} *Elements;
Elements* reverse(Elements *x){
Elements *y,*t; y = NULL;while (x!= NULL) {
t = xn;
y = x;xn = y;
x = t;}
return y;
21
/* rpred.tvp */
/*************** Core Predicates *************/
foreach (z in PVar) {
%p z(v_1) unique box
}
%p n(v_1, v_2) function
/**********************************************/
/*********** Instrumentation Predicates *************/
%i is[n](v) = E(v_1, v_2) ( v_1 != v_2 & n(v_1, v) & n(v_2, v))
foreach (z in PVar) {
%i r[n,z](v) = E(v_1) (z(v_1) & n*(v_1, v))
}
%i c[n](v) = n+(v, v)
22
rstat.tvp%action Set_Null_L(x1) {
%t x1 + " = NULL“
%message … ->
{
x1(v) = 0
r[n, x](v) = 0
}
}
%action Copy_Var_L(x1, x2) {
%t x1 + " = " + x2
%f { x2(v) }
{
x1(v) = x2(v)
r[n, x](v) = 0
}
}
%action Malloc_L(x1) {
%t x1 + " = (L) malloc(sizeof(struct node)) "
%new
{
x1(v) = isNew(v)
r[n, x](v) = isNew(v)
}
}
23
(1) Focus on v1: x(v1) cdr(v1,v)
y u1 ux
u1 ux cdr
cdr
r[cdr]
y ux
u1 ux
cdr
y u1 ux
u1 ux cdr
cdr
yu1 u.1
x
u.0
cdr
cdr
cdr
cdr
24
Benefit of Reachability
Predict memory leaks Separate disjoint data structures More precise semantic reduction
– x = x->n
25
Optimizations in TVLA
Order of constrains– Eliminate cycles
Lazy evaluation Functional properties Exploit sparseness OBDD representation Java representation
26
TVLA Design Mistakes
The operational semantics is written in too low level language– No types
– No local updates to specific predicate values
– No constants and functions
– No means for modularity
– No local variables and sequencing
– Combines UI with functionality
TVP can be a high level language TVLA3VLA
27
TVLA Experience
Quite fast on small programs– But runs on medium programs too
Not a panacea More instrumentation may lead to faster (and
more precise) analysis