Towards Shape Analysis for Device Drivers Hongseok Yang (Queen Mary, University of London) (Joint...

Preview:

Citation preview

Towards Shape Analysis for Device

DriversHongseok Yang

(Queen Mary, University of London)

(Joint work with Josh Berdine, Cristiano Calcagno, Byron Cook, Dino Distefano, Peter O’Hearn and Thomas Wies)

Dream

Do deep shape analysis for real programs (i.e., programs of ~ 100K LOC).

1. Memory safety2. Absence of leaks3. Race freedom4. Reponsiveness

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)ResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)

Pb 1: Extreme local analysis• Tied to OS kernel • Expensive shape analysis

KeReleaseSpinLock(&de->ResetSpinLock, Irql);

KeAcquireSpinLock(&de->ResetSpinLock, &Irql);

IoCompleteRequest(Irp, IO_NO_INCREMENT);

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)ResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)ResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

Pb1 : Extreme local analysis• A part of code in isolation.• No preconditions.• Only the memory footprint of the part.

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

Pb 2: Challenging Data Structurestypedef struct {

DEVICE_OBJECT* StackDeviceObject; DEVICE_OBJECT* PortDeviceObject; DEVICE_OBJECT* PhysicalDeviceObject; …ADDRESS_DATA* Flink1; RESET_IRP* Flink2; CROM_DATA* Flink3; DETACH_DATA* Flink4; RESOURCE_DATA* Flink5;} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef struct DEVICE_OBJECT {…DEVICE_EXTENSION* DeviceExtension; … } DEVICE_OBJECT, *PDEVICE_OBJECT;

Drawn by Dino Distefano

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

Pb 3: Concurrency

KeReleaseSpinLock(&de->ResetSpinLock, Irql);

KeAcquireSpinLock(&de->ResetSpinLock, &Irql);

typedef struct {…DRIVER_CANCEL (*CancelRoutine)(…); …} IRP, *PIRP;

Status of Separation-logic based Shape Analysis

(London/Cambridge)Problem 1: Extreme local analysisExtreme local shape analysis[Calcagno, Distefano, O’Hearn, Yang]

Problem 2: Challenging data structuresAdaptive shape analysis[Berdine, Calcagno, Disetafano, Cook, Wies, O’Hearn, Yang]

Problem 3: ConcurrencyThread-modular shape analysis [Gotsman, Berdine, Cook, Sagiv]

Extreme Local Shape Analysis

• Analyze a part of code in isolation.• No preconditions.• Only the memory footprint of the part.

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PRESET_IRP ResetIrp,temp,tempnext; PDEVICE_EXTENSION de; ……… KeAcquireSpinLock(&de->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&de->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PXXX_RESET_IRP XXXResetIrp,temp,tempnext; PDEVICE_EXTENSION deviceExtension; ……… KeAcquireSpinLock(&deviceExtension->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&deviceExtension->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)

typedef struct { RESET_IRP* Flink2; IRP* Irp;…} RESET_IRP, *PRESET_IRP;

typedef struct { RESET_IRP* Flink2; …} DEVICE_EXTENSION;

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,x1) * (x1aR Irp:Irp)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,0)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)(de aD Flink2: de)

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PXXX_RESET_IRP XXXResetIrp,temp,tempnext; PDEVICE_EXTENSION deviceExtension; ……… KeAcquireSpinLock(&deviceExtension->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&deviceExtension->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)

typedef struct { RESET_IRP* Flink2; IRP* Irp;…} RESET_IRP, *PRESET_IRP;

typedef struct { RESET_IRP* Flink2; …} DEVICE_EXTENSION;

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,x1) * (x1aR Irp:Irp)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,0)

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)(de aD Flink2: de)

de aD Flink2: de

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PXXX_RESET_IRP XXXResetIrp,temp,tempnext; PDEVICE_EXTENSION deviceExtension; ……… KeAcquireSpinLock(&deviceExtension->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&deviceExtension->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)

typedef struct { RESET_IRP* Flink2; IRP* Irp;…} RESET_IRP, *PRESET_IRP;

typedef struct { RESET_IRP* Flink2; …} DEVICE_EXTENSION;

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,x1) * (x1aR Irp:Irp)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,0)

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)(de aD Flink2: de)

de aD Flink2: deÆ de = ResetIrp

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PXXX_RESET_IRP XXXResetIrp,temp,tempnext; PDEVICE_EXTENSION deviceExtension; ……… KeAcquireSpinLock(&deviceExtension->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&deviceExtension->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)

typedef struct { RESET_IRP* Flink2; IRP* Irp;…} RESET_IRP, *PRESET_IRP;

typedef struct { RESET_IRP* Flink2; …} DEVICE_EXTENSION;

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,x1) * (x1aR Irp:Irp)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,0)

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)(de aD Flink2: de)

de aD Flink2: deÆ de = ResetIrp

void XXX_CancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp){ ……… PXXX_RESET_IRP XXXResetIrp,temp,tempnext; PDEVICE_EXTENSION deviceExtension; ……… KeAcquireSpinLock(&deviceExtension->ResetSpinLock, &Irql); ResetIrp = (PRESET_IRP)de->Flink2; while (ResetIrp !=NULL) { if (ResetIrp->Irp == Irp) { temp = (PRESET_IRP)de; tempnext = temp->Flink2; while (tempnext != ResetIrp) { temp = tempnext; tempnext = temp->Flink2; } temp->Flink2 = ResetIrp->Flink2; free(ResetIrp); break; } else if (ResetIrp->Flink2 == (PRESET_IRP)de) break; else ResetIrp = (PRESET_IRP)BusResetIrp->Flink2; } KeReleaseSpinLock(&deviceExtension->ResetSpinLock, Irql); …… IoCompleteRequest(Irp, IO_NO_INCREMENT);}

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)

typedef struct { RESET_IRP* Flink2; IRP* Irp;…} RESET_IRP, *PRESET_IRP;

typedef struct { RESET_IRP* Flink2; …} DEVICE_EXTENSION;

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,x1) * (x1aR Irp:Irp)

(de aD Flink2: x0) * ls (RESET_IRP,Flink2) (x0,0)

(de a Flink2: x0) * ls (RESET_IRP,Flink2) (x0,de)(de aD Flink2: de)

de aD Flink2: deÆ de = ResetIrp

ERROR: No IRP Field in DEVICE_EXTENSION

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

assert(x!=0);t=x;x=x->next;free(x);assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

assert(x!=0);t=x;x=x->next;free(x);assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

assert(x!=0);t=x;x=x->next;free(x);assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

P0 P1

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

assert(x!=0);t=x;x=x->next;free(x);assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

P0 P1

Abstract preconditions

P2P3

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

assert(x!=0);t=x;x=x->next;free(x);assert(x!=0);t=x;x=x->next;free(x);assert(x=0);

P0 P1

Abstract preconditions

P2P3

SpaceInvader

{P2,P3,…,Pn}

{Q1,Q2,…,Qk}

{I1,I2,…,Im}

Extreme Local Shape Analysis

TraceGeneration

FootprintComputation

Abstract preconditions

SpaceInvader

Sound precondition

Footprint only

Separation Logic

xay, ls (y,z)

xay * ls (y,z), emp

9y’. z!=0 Æ v=a Æ xay’ * ls (y’,z)

x y y z

y zx

Variable Convention

• Program variables: x,y,z,t,v,w• Ghost (or auxiliary) variables: a,b,c,d,….• Primed variables: x’,y’,z’,t’,v’,w’

9 w’,w’1.

x!=0 Æ z=a Æ w’!=w’1 Æ xaw’ * ls (w’,w’1) * yaw’1

Symbolic Heaps

Separation logic formulas of the form:

(x!=0 Æ z=a Æ w’!=w’1) Æ (xaw’ * ls (w’,w’1) * yaw’1)

SH = Set of all symbolic heapsGhostSH = Set of sym. heaps with ghost vars

only

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Q0

P

P0

C

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.Foot(t=x->next, x=aÆemp) = (aab, x=aÆt=bÆaab) {x=a Æ emp*aab} t=x->next {x=a Æ t=b Æ aab}

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(free(x),P*EaF) = (emp,P) if (P*EaF) ` E=xFoot(free(x), x=a Æ aa0) = (emp, x=a Æ emp)

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(free(x),P*EaF) = (emp,P) if (P*EaF) ` E=xFoot(free(x),P) = (aab,P) if P ` x=a, fresh b

Rewrite x to some ghost variable.

Foot(free(x), x=a Æ emp) = (aab, x=a Æ emp)

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(free(x),P*EaF) = (emp,P) if (P*EaF) ` E=xFoot(free(x),P) = (aab,P) if P ` x=a, fresh b

Foot(free(x),P) = (false,P) otherwise

Foot(free(x), emp) = (false, emp) != (xa b, emp)

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(A;C,P) = let (P0,Q0)=Foot(A,P) and (P1,Q1)=Foot(C,Q0)

in (P0*P1, Q1)

P

Q1P0 Q0

P1

A C

P1

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(A;C,P) = let (P0,Q0)=Foot(A,P) and (P1,Q1)=Foot(C,Q0)

in (P0*P1, Q1) Foot(free(x);free(y), x=a Æ y=b Æ emp) = (aac * bad, x=a Æ y=b Æ emp)

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Algorithm : Given a trace C. Supp FPV(C) = {x}.

P := (x=a Æ emp); (P0,Q0) := Foot(C, P);

return (P * P0);

List Disposal

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

x

0

List Disposal

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

x

0

List Disposal

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

x

0

t

List Disposal

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

x

0

t

List Disposal

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

x

0

t

Footprint Computation

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ emp

x=a Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ emp * aab

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ emp * aab

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ emp

x=b Æ a!=0 Æ t=a Æ emp

x=b Æ a!=0 Æ t=a Æ emp * aab

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ emp * aab

x=b Æ a!=0 Æ t=a Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

x=b Æ a!=0 Æ t=a Æ b!=0 Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);}

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ emp * aab

x=b Æ a!=0 Æ t=a Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

x=b Æ a!=0 Æ t=a Æ b!=0 Æ empx=b Æ a!=0 Æ t=b Æ b!=0 Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ emp * aab * bac

x=b Æ a!=0 Æ t=a Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

x=b Æ a!=0 Æ t=a Æ b!=0 Æ empx=b Æ a!=0 Æ t=b Æ b!=0 Æ empx=c Æ a!=0 Æ t=b Æ b!=0 Æ emp * bac

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ emp * aab * bac

x=b Æ a!=0 Æ t=a Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

x=b Æ a!=0 Æ t=a Æ b!=0 Æ empx=b Æ a!=0 Æ t=b Æ b!=0 Æ empx=c Æ a!=0 Æ t=b Æ b!=0 Æ emp * bacx=c Æ a!=0 Æ t=b Æ b!=0 Æ emp

Footprint Computation

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

x=c Æ a!= 0 Æ t=b Æ b!=0 Æ c=0 Æ emp

x=b Æ a!=0 Æ t=a Æ emp

x=a Æ empx=a Æ a!=0 Æ emp

x=a Æ a!=0 Æ t=a Æ empx=b Æ a!=0 Æ t=a Æ emp * aab

x=b Æ a!=0 Æ t=a Æ b!=0 Æ empx=b Æ a!=0 Æ t=b Æ b!=0 Æ empx=c Æ a!=0 Æ t=b Æ b!=0 Æ emp * bacx=c Æ a!=0 Æ t=b Æ b!=0 Æ emp

Abstraction

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

Abs : SH ! CanonicalSH

1. Existentially quantify ghost vars.2. Substitute away equalities d’=E.3. Drop disequalities.4. Apply list abstraction.

Abstraction

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

Abs : SH ! CanonicalSH

1. Existentially quantify ghost vars.2. Substitute away equalities d’=E.3. Drop disequalities.4. Apply list abstraction.

Discovered Precondition: x=a’ Æ a’!=0 Æ b’!=0 Æ c’=0 Æ emp * a’ab’ * b’ac’

Abstraction

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

Abs : SH ! CanonicalSH

1. Existentially quantify ghost vars.2. Substitute away equalities d’=E.3. Drop disequalities.4. Apply list abstraction.

Discovered Precondition: x=a’ Æ a’!=0 Æ b’!=0 Æ c’=0 Æ emp * a’ab’ * b’ac’

Discovered Precondition: x!=0 Æ b’!=0 Æ emp * xab’ * b’a0

Abstraction

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

Abs : SH ! CanonicalSH

1. Existentially quantify ghost vars.2. Substitute away equalities d’=E.3. Drop disequalities.4. Apply list abstraction.

Discovered Precondition: x=a’ Æ a’!=0 Æ b’!=0 Æ c’=0 Æ emp * a’ab’ * b’ac’

Discovered Precondition: x!=0 Æ b’!=0 Æ emp * xab’ * b’a0

Discovered Precondition:

emp * xab’ * b’a0

Abstraction

Discovered Precondition: x=a Æ a!=0 Æ b!=0 Æ c=0 Æ emp * aab * bac

Abs : SH ! CanonicalSH

1. Existentially quantify ghost vars.2. Substitute away equalities d’=E.3. Drop disequalities.4. Apply list abstraction.

Discovered Precondition: x=a’ Æ a’!=0 Æ b’!=0 Æ c’=0 Æ emp * a’ab’ * b’ac’

Discovered Precondition: x!=0 Æ b’!=0 Æ emp * xab’ * b’a0

Discovered Precondition:

emp * xab’ * b’a0

Discovered Precondition:

ls (x,0)

SpaceInvader

list t*;while (x!=0) {

t = x;

x = x->next;

free(t);

}

Precondition: ls (x, 0)

Postcondition: x=0 Æ emp

Fixpoint Computation

Backward Footprint Computation

list t*;while (x!

=0) { t = x; x = x-

>next; free(t);}

Backward:

assert(x!=0);t = x;x = x->next;free(t);assert(x=0);

Forward:

assert(x!=0);t = x;x = x->next;free(t);assert(x=0);

Frame Rule and Correctness of Footprint

Computation Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(A;C,P) = let (P0,Q0)=Foot(A,P) and (P1,Q1)=Foot(C,Q0)

in (P0*P1, Q1)

P

Q1P0 Q0

P1

A C

P1

Sound because of Frame Rule in Sep. Log.

{P*P0}A{Q0}

{P*P0*P1}A{Q0*P1} {Q0*P1}C{Q}

{P*P0*P1}A;C{Q}

Experiments with Firewire Device Driver

MacBook, 2GH Intel Core Duo. 2GB Mem. All fn calls are inlined.

Function LOC Time Result

F1 32 0.07 Alarm Real Err

F2 87 0.04 Yes

F3 130 0.43 Yes

F4 198 0.31 Yes

F5 (loop 1) 325 40.75 Yes

F5 (loop 2) 46 2.83 Yes

F5 (loop 3) 221 0.45 Yes

F5 (loop 4) 170 > 10 min

???

F5 (loop 5) 59 0.036 Yes

Future Direction

1. Weaving analysis results.2. Good abstraction for footprints.3. Better shape abstraction.

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(assert(x!=0),P) = (a!=0 Æ emp, a!=0 Æ P) if P ` x=a

Footprint Computation

Foot : Trace x SH ! GhostSH x SH

Correctness: If Foot(C,P)=(P0,Q0), then {P*P0}C{Q0} holds in Sep.

Log.

Foot(assert(x!=0),P) = (a!=0 Æ emp, a!=0ÆP) if P ` x=a

Foot(assert(x!=0),P) = (false, P) otherwise

Recommended