Presentation is loading. Please wait.

Presentation is loading. Please wait.

Roman Manevich Ben-Gurion University Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 16: Shape Analysis.

Similar presentations


Presentation on theme: "Roman Manevich Ben-Gurion University Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 16: Shape Analysis."— Presentation transcript:

1 Roman Manevich Ben-Gurion University Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 16: Shape Analysis

2 Syllabus Semantics Natural Semantics Structural semantics Axiomatic Verification Static Analysis Automating Hoare Logic Control Flow Graphs Equation Systems Collecting Semantics Abstract Interpretation fundamentals LatticesFixed-Points Chaotic Iteration Galois Connections Domain constructors Widening/ Narrowing Analysis Techniques Numerical Domains Alias analysis Shape Analysis Interprocedural Analysis CEGAR Crafting your own Soot From proofs to abstractions Systematically developing transformers 2

3 Previously Points-to analysis and alias analysis 3

4 Agenda Going beyond pointer analysis Shape analysis – Property-based summarization – Materialization – Specialized analysis for singly-linked lists – (3-valued Shape Analysis Framework / TVLA) 4

5 Limitations of pointer analysis 5 // Singly-linked list // data type. class SLL { int data; public SLL n; // next cell SLL(Object data) { this.data = data; this.n = null; } } // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; }

6 Flow&Field-sensitive Analysis 6 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; }

7 Flow&Field-sensitive Analysis 7 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t

8 Flow&Field-sensitive Analysis 8 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t L1 n

9 Flow&Field-sensitive Analysis 9 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n

10 Flow&Field-sensitive Analysis 10 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n

11 Flow&Field-sensitive Analysis 11 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n n

12 Flow&Field-sensitive Analysis 12 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n n

13 Flow&Field-sensitive Analysis 13 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n tmp null h t L1 n  tmp != null tmp == null n

14 Flow&Field-sensitive Analysis 14 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n tmp null h t L1 n  n

15 Flow&Field-sensitive Analysis 15 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n tmp == null ? n

16 Flow&Field-sensitive Analysis 16 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n n

17 Flow&Field-sensitive Analysis 17 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n Possible null dereference! n

18 Flow&Field-sensitive Analysis 18 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n Fixed-point for first loop n

19 Flow&Field-sensitive Analysis 19 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n n

20 Flow&Field-sensitive Analysis 20 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } tmp null h t L1 n L2 n Possible null dereference! n

21 What was the problem? Pointer analysis abstract all objects allocated at same program location into one summary object. However, objects allocated at same memory location may behave very differently – E.g., object is first/last one in the list – Assign extra predicates to distinguish between objects with different roles Number of objects represented by summary object  1 – does not allow strong updates – Distinguish between concrete objects (#=1) and abstract objects (#  1) Join operator very coarse – abstracts away important distinctions (tmp=null/tmp!=null) – Apply disjunctive completion 21

22 Improved solution Pointer analysis abstract all objects allocated at same program location into one summary object. However, objects allocated at same memory location may behave very differently – E.g., object is first/last one in the list – Add extra instrumentation predicates to distinguish between objects with different roles Number of objects represented by summary object  1 – does not allow strong updates – Distinguish between concrete objects (#=1) and abstract objects (#  1) Join operator very coarse – abstracts away important distinctions (tmp=null/tmp!=null) – Apply disjunctive completion 22

23 Adding properties to objects Let’s first drop allocation site information and instead… Define a unary predicate x(v) for each pointer variable x meaning x points to x Predicate holds for at most one node Merge together nodes with same sets of predicates 23

24 Flow&Field-sensitive Analysis 24 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t

25 Flow&Field-sensitive Analysis 25 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {h, t} n

26 Flow&Field-sensitive Analysis 26 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {h, t} tmp n

27 Flow&Field-sensitive Analysis 27 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {h, t} tmp n {tmp} n No null dereference

28 Flow&Field-sensitive Analysis 28 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {h, t} tmp n {tmp} n

29 Flow&Field-sensitive Analysis 29 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n {h, tmp} n

30 Flow&Field-sensitive Analysis 30 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n {h, tmp} n  null h t {h, t} tmp n

31 Flow&Field-sensitive Analysis 31 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n {h, tmp} n  null h t {h, t} tmp n Do we need to analyze this shape graph again?

32 Flow&Field-sensitive Analysis 32 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n {h, tmp} n  null h t {h, t} tmp n

33 Flow&Field-sensitive Analysis 33 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { h} n { tmp} n No null dereference

34 Flow&Field-sensitive Analysis 34 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { h} n { tmp} n

35 Flow&Field-sensitive Analysis 35 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n { h, tmp} n

36 Flow&Field-sensitive Analysis 36 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n { h, tmp} n

37 Flow&Field-sensitive Analysis 37 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n { h} n { tmp} n No null dereference

38 Flow&Field-sensitive Analysis 38 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n { h} n { tmp} n

39 Flow&Field-sensitive Analysis 39 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n n {h, tmp} n

40 Flow&Field-sensitive Analysis 40 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h, tmp} n n Summarization How many objects does it represent?

41 Flow&Field-sensitive Analysis 41 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h} n n { tmp} No null dereference n

42 Flow&Field-sensitive Analysis 42 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h} n n { tmp} n

43 Flow&Field-sensitive Analysis 43 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h, tmp} n n Fixed-point for first loop

44 Flow&Field-sensitive Analysis 44 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h, tmp} n n

45 Flow&Field-sensitive Analysis 45 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { } n {h, tmp} n n

46 Flow&Field-sensitive Analysis 46 // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; } null h t {t} tmp n { tmp?} n { tmp} n n

47 Improving precision via partial concretization 47

48 Best (induced) transformer 48 CA 2 3 f f # (a)=  (f(  (a))) 1 f#f# 4 Problem:  incomputable directly

49 Best transformer for tmp=tmp.n 49 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n { } n {h, tmp} n null h t {t} tmp n { } n {h, tmp} n { } 

50 Best transformer for tmp=tmp.n:  50 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n { } n {h, tmp} n null h t {t} tmp n { } n {h, tmp} n { }  null h t {t} tmp n { } n {h, tmp} n { } …

51 Best transformer for  tmp=tmp.n  51 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n {tmp } n {h} n null h t {t} tmp n { } n {h} n { } {tmp } null h t {t} tmp n { } n {h} n { } {tmp } …

52 Best transformer for tmp=tmp.n:  52 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n {tmp } n {h} n null h t {t} tmp n { } n {h} n {tmp } null h t {t} tmp n { } n {h} n {tmp } …

53 Handling updates on summary nodes Transformers accessing only concrete nodes are easy Transformers accessing summary nodes are complicated Can’t concretize summary nodes – represents potentially unbounded number of concrete nodes We need to split into cases by “materializing” concrete nodes from summary node – Introduce a new temporary predicate tmp.n – Partial concretization 53

54 Transformer for tmp=tmp.n:  ’ 54 null h t {t} tmp n { } n {h, tmp} n n ’’ Case 1: Exactly 1 object. Case 2: >1 objects.

55 Transformer for tmp=tmp.n:  ’ 55 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n {tmp.n } n {h, tmp} n null h t {t} tmp n { } n {h, tmp} n {tmp.n } ’’ tmp.n is a concrete node Summary node spaghetti

56 Transformer  tmp=tmp.n  56 null h t {t} tmp n { } n {h, tmp} n n null h t {t} tmp n {t, tmp.n } n {h} n null h t {t} tmp n { } n {h} n {t, tmp.n }

57 Transformer for tmp=tmp.n:  57 null h t {t} tmp n {t} n {h} n null h t {t} tmp n { } n {h} n {t} // Build a list SLL h=null, t = null; L1: h=t= new SLL(-1); SLL tmp = null; while (…) { int data = getData(…); L2: tmp = new SLL(data); tmp.n = h; h = tmp; } // Process elements tmp = h; while (tmp != t) { assert tmp != null; tmp.data += 1; tmp = tmp.n; }

58 Transformer via partial-concretization 58 CA 2 3 f f # (a)=  ’(f # ’(  ’(a))) 1 f#f# 4 A’ 5 f #’ 6 ’’ ’’

59 Recap Adding more properties to nodes refines abstraction Can add temporary properties for partial concretization – Materialize concrete nodes from summary nodes – Allows turning weak updates into strong ones – Focus operation in shape-analysis lingo – Not trivial in general and requires more semantic reduction to clean up impossible edges – General algorithms available via 3-valued logic and implemented in TVLA system 59

60 Analyzing singly-linked lists 60

61 Specialized analysis for SLL Very simple shape analysis Assumes – SLL only data structure – Data fields cannot point to SLL nodes – No recursive procedures Simple algorithms, quick implementation – Implemented in Abstract Interpretation package 61

62 What is it good for? Supports assertions – assertReach(x,y) – assertDisjointLists(x,y) Enables parallelization – assertAcyclicList(x) – assertCyclicList(x) – assert(x==y)assert(x!=y) Check cleanness properties – Absence of NullPointerException ’s – Absence of memory leaks (in C) – No misuse of dangling pointers (in C) 62

63 Concrete store x y class SLL { int data; SLL n; } n nnnnnnnn nnn n 63

64 Interrupting nodes x y Interruption: node pointed-to by a variable or shared by n fields #interruptions ≤ 2 · #variables (bounded number of sharing patterns) n nnnnnnnn nnn n 64

65 List segments x y Maximal sub-list between two interruptions not containing interruptions in-between n nnnnnnn nnn n n 65

66 List segments x y segment 2segment 1 segment 3 segment 4 n nnnnnnn nnn n n 66

67 Abstraction idea Add following instrumentation predicates to each node – x(v) – node v is pointed-to by variable x – seg(v) – node v is properly contained in a list segment Merge nodes within the same end points of a segment 67

68 Instrumented store x y seg n nnnnnnn nnn n n 68

69 Abstract store x y n n nn n nn n n n seg 69

70 Store it represents x y seg n nnnnnnn nnn n n 70

71 Store it does not represent x y seg n nnnnnnn nnn n n 71

72 Simplified representation x y 1 >1 Make summary node implicit. Abstract length: how many links in segment {1, >1} 72

73 Intuitive meaning of abstraction Retains overall “shape” of the heap – Which important points exist – How they are connected via paths – Precisely captures disjointness/sharing/cycles Abstracts away – Lengths of simple paths – Many times not relevant for proving correctness of list-manipulating programs – But sometimes is Refinements with numerical abstractions of lengths is needed 73

74 Abstract transformers for singly-linked lists 74

75 Abstract transformers Need transformers for program statements – x = new List() – x = null – x = y – x = y.n – x.n = y – assume x!=y – assume x==y 75

76 Simplifying code transformations Code transformations that preserve semantics and simplify implementing transformers by eliminating annoying corner cases Precede all assignment to x by x=null E.g., replace x=new List() with x=null; x=new List() Replace x=x.n with t=x.n; x=t Replace x.n=x with t=x; x.n=t Replace x.n=t with x.n=null; x.n=t 76

77  x = new List()  # Recall assumption that x==null before statement (simplifying transformation) Allocate new node and have x point to it – Just like concrete semantics 77 t y n >1 x null  x = new List()  # t y 1 >1 x null 1

78  x = t  # Recall assumption that x==null before statement (simplifying transformation) t points to a concrete node Have x point to that node – Just like concrete semantics 78 t y 1 >1 x null  x = t  # t y 1 >1 x null

79  x = null  # Case 1: x points to an interruption that remains an interruption even without x pointing to it Just have x point to null 79 t y 1 >1 x  x = null  # t y 1 >1 x null

80  x = null  # Case 2: x points to an interruption that ceases to be an interruption Have x point to null 80 t 1 >1 x  x = null  # t 1 >1 x null

81  x = null  # Case 2: x points to an interruption that ceases to be an interruption Step 1: Have x point to null Step 2: Abstract non-maximal list segments 81 t 1 >1 x  x = null  # t 1 >1 x null

82  x = null  # Case 2: x points to an interruption that ceases to be an interruption Step 1: Have x point to null Step 2: Abstract non-maximal list segments 82 t 1 >1 x  x = null  # t >1 x null >1

83  x = y.n  # Recall assumption that x==null before statement (simplifying transformation) Case 1: y.n is an interruption (edge with abstract length 1) Just have x point to the successor of y 83 t y 1 >1 1  x = y.n  # t y 1 >1 1 x x null

84  x = y.n  # Recall assumption that x==null before statement (simplifying transformation) Case 2: y.n is not an interruption (edge with abstract length >1) Apply partial concretization and then do case 1 84 t y 1 >1  x = y.n  # x null What lengths does it represent?

85  x = y.n  # Recall assumption that x==null before statement (simplifying transformation) Case 2: y.n is not an interruption (edge with abstract length >1) Apply partial concretization and then do case 1 85 t y 1 >1  x = y.n  # x null >1 = 2 or >2

86  x = y.n  # Recall assumption that x==null before statement (simplifying transformation) Case 2: y.n is not an interruption (edge with abstract length >1) Apply partial concretization and then do case 1 86 t y null 1 >1 ’’ x t y null 1 >1 x 1 1 t y null 1 >1 x 1

87  x = y.n  # Recall assumption that x==null before statement (simplifying transformation) Case 2: y.n is not an interruption (edge with abstract length >1) Apply partial concretization and then do case 1 87 t y null 1 >1  x = y.n   ’ x t y null 1 >1 x 1 1 t y null 1 >1 x 1

88  x.n = null  # Can be used to detect memory leaks – (Also x=null) Again two cases: x.n is a concrete node / x.n is a summary node 88

89  x.n = null  # Can be used to detect memory leaks Again two cases: x.n is a concrete node / x.n is a summary node Case 1: x.n is a concrete node Follow concrete semantics 89 t x null 1 >1 1  x.n = null  # t x null 1 >1 1 Need to merge non- maximal segment

90  x.n = null  # Can be used to detect memory leaks Again two cases: x.n is a concrete node / x.n is a summary node Case 1: x.n is a concrete node Follow concrete semantics 90 t x null 1 >1 1  x.n = null  # t x null 1 >1

91  x.n = null  # Can be used to detect memory leaks Again two cases: x.n is a concrete node / x.n is a summary node Case 2: x.n is a summary node Apply partial concretization and do case 1 91 t x null 1 >1  x.n = null  # … What can go wrong here in C?

92  x.n = y  # Trivial after x.n=null 92 t x null 1 >1 1 y  x.n = y  # t x null 1 >1 1 y

93  assume x==y  #  assume x!=y  # How do we check these? 93

94 Checking assertions How do we check these? – assertReach(x,y) – assertDisjointLists(x,y) – assertAcyclicList(x) – assertCyclicList(x) 94

95 Proving termination of heap-manipulating programs 95

96 The Goal Input: a program in a language with objects (Java, C++, C#...) Output: proof that program terminates or some information to suggest otherwise Why is it important? – When a device driver goes into an infinite loop your operating system hangs

97 The Challenge Proving termination is undecidable – Turing’s halting problem But the problem is really important What can we do? – Give up – Provide approximate algorithms with one-sided error (sound): if answer is yes program terminates but if answer is no we don’t really know – Focus on a subset of programs

98 [ x=y & list(x, null) ] L1: while (y != null) y := y.n; L2: skip; exit: [ y=null & list(x, null)] A Simple Example

99 [ x=y & list(x, null) ] t := 0; L1: while (y != null) ++t; assert t < |list(x,null)|; y := y.n; L2: skip; exit: [ y=null & list(x, null)] Idea: add counters and prove bound But how do we prove this?

100 Idea: Use Shape Abstraction Approximate memory layout by abstracting into a finite number of equivalence classes L1: xy nul l S4S4 xy 11 L1: 

101 xy a nul l b S1S1 xy m n S5S5 xy c d S2S2 xy o p S6S6 xy k l S4S4 i j xy g h S3S3 e f L1: L2: L3: Abstract Transition Relation Finite approximation of all program executions Where did the counter go?

102 xy d nul l 11 abc xy h 22 efg L1: L2: Idea: Encode Counter In Objects QFPA constraint for single transition Problem: infinite system of constraints for ALL transitions

103 Final Solution Generate constraints for abstract transition relation Finite system of constraints = quantifier-free formula in Presburger arithmetic Formula is satisfiable  program is Loop Polynomial – Polynomial in the maximum nesting depth – Each loop performs linear number iterations Satisfiability is decidable Works well in practice

104 Next lecture: Interprocedural analysis


Download ppt "Roman Manevich Ben-Gurion University Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 16: Shape Analysis."

Similar presentations


Ads by Google