Path-based Inductive Synthesis for Program Inversion Saurabh Srivastava (a) Sumit Gulwani (b) Swarat Chaudhuri (c) Jeffrey S. Foster (d) (a) University of California, Berkeley (b) Microsoft Research, Redmond (c) Rice University (d) University of Maryland, College Park
Program Inversion as Synthesis • Task Given a program P , synthesis P -1 such that P -1 ( P (x)) = x • Motivation : Many common program/inverse pairs • Compress/decompress, insert/delete, lossless encode/decode, encrypt/decrypt, rollback, many more • Only having to write one increases productivity, reduces bugs • Problem • Existing synthesis techniques not well-suited for inversion • Dedicated inversion techniques limited in scope
PINS: Path-based Inductive Synthesis • Specification • Program to be inverted • Template hints: Control flow, and expressions, predicates • Functional requirement: Program + Inverse = Identity • Engine : SMT solver (Z3) • Algorithm : Inspired by testing • Explore path through program + template • Ask engine for instantiations on path to match spec • Iterate, refining space
Small path-bound hypothesis “Program behavior can be summarized by examining a carefully chosen , small, finite set of paths” • Same hypothesis underlies program testing • As in testing, two questions: 1) Which paths? • Especially since the template describes “set of programs” 2) How can we ensure the generated inverse is correct? • We check using: manual inspection, testing, bounded verification
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] A = [1,0,2] N = [3,2,4] A’ = [1,1,1,0,0,2,2,2,2]
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] assume(n>=0); i, m := 0, 0; // parallel assignment while (i < n) Original r := 1; encoder while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; A = [1,0,2] N = [3,2,4] A’ = [1,1,1,0,0,2,2,2,2]
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] assume(n>=0); i, m := 0, 0; // parallel assignment while (i < n) Original r := 1; encoder while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; A = [1,0,2] N = [3,2,4] i ʼ , m ʼ := e 1 , e 2 ; // e i ∈ E while (p 1 ) // p i ∈ P r ʼ := e 3 ; Template while (p 2 ) decoder r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ; A’ = [1,1,1,0,0,2,2,2,2]
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] assume(n>=0); i, m := 0, 0; // parallel assignment while (i < n) Original r := 1; encoder while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; A = [1,0,2] E = { N = [3,2,4] i ʼ , m ʼ := e 1 , e 2 ; // e i ∈ E 0, 1, m ʼ +1, m ʼ -1, r ʼ +1, r ʼ -1, while (p 1 ) // p i ∈ P i ʼ +1, i ʼ -1, A ʼ [m ʼ ]:=A[i ʼ ], r ʼ := e 3 ; A ʼ [i ʼ ] := A[m ʼ ], N[m ʼ ] Template } while (p 2 ) decoder r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ; A’ = [1,1,1,0,0,2,2,2,2]
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] assume(n>=0); i, m := 0, 0; // parallel assignment while (i < n) Original r := 1; encoder while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; A = [1,0,2] E = { N = [3,2,4] i ʼ , m ʼ := e 1 , e 2 ; // e i ∈ E 0, 1, m ʼ +1, m ʼ -1, r ʼ +1, r ʼ -1, while (p 1 ) // p i ∈ P i ʼ +1, i ʼ -1, A ʼ [m ʼ ]:=A[i ʼ ], r ʼ := e 3 ; A ʼ [i ʼ ] := A[m ʼ ], N[m ʼ ] Template } while (p 2 ) decoder r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; P = { m ʼ := e 7 ; m ʼ <m, r ʼ >0, A ʼ [i ʼ ]=A ʼ [i ʼ +1] A’ = [1,1,1,0,0,2,2,2,2] }
Example of templates In-place run-length encoding: A = [1,1,1,0,0,2,2,2,2] assume(n>=0); i, m := 0, 0; // parallel assignment Template control flow, while (i < n) expressions E, and predicates P, Original r := 1; semi-automatically mined from encoder while (i+1 < n && A[i] = A[i+1]) original r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; A = [1,0,2] E = { N = [3,2,4] i ʼ , m ʼ := e 1 , e 2 ; // e i ∈ E 0, 1, m ʼ +1, m ʼ -1, r ʼ +1, r ʼ -1, while (p 1 ) // p i ∈ P i ʼ +1, i ʼ -1, A ʼ [m ʼ ]:=A[i ʼ ], r ʼ := e 3 ; A ʼ [i ʼ ] := A[m ʼ ], N[m ʼ ] Template } while (p 2 ) decoder r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; P = { m ʼ := e 7 ; m ʼ <m, r ʼ >0, A ʼ [i ʼ ]=A ʼ [i ʼ +1] A’ = [1,1,1,0,0,2,2,2,2] }
Symbolic execution of program paths assume(n>=0); i, m := 0, 0; while (i < n) r := 1; while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths assume(n>=0); i, m := 0, 0; while (i < n) r := 1; while (i+1 < n && A[i] = A[i+1]) r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) ¬ (p 1V ) r := 1; while (i+1 < n && A[i] = A[i+1]) ⇒ identity r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) (n>=0) r ʼ := e 3 ; i, m := 0, 0 while (p 2 ) ¬ (i < n) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ; i ʼ , m ʼ := e 1 , e 2 ¬ (p 1 )
Symbolic execution of program paths (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) ¬ (p 1V ) r := 1; while (i+1 < n && A[i] = A[i+1]) ⇒ identity r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) ¬ (p 1V ) r := 1; while (i+1 < n && A[i] = A[i+1]) ⇒ identity r, i := r + 1, i+1; A[m], N[m], m, i := A[i], r, m+1, i+1; i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths (n 0 >=0) ∧ (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ i 1 = 0 ∧ m 1 = 0 ∧ (i 1 < n 0 ) ∧ ¬ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) (p 1V ʼ ) ∧ ¬ (p 1V ) r := 1; r ʼ 1 =e 3V ʼ ∧ while (i+1 < n && A[i] = A[i+1]) ⇒ identity ¬ (p 2V ʼʼ ) ∧ r, i := r + 1, i+1; m ʼ 2 =e 7V ʼʼ ∧ A[m], N[m], m, i := A[i], r, m+1, i+1; ⇒ identity ¬ (p 1V ʼʼʼ ) (n>=0) i ʼ , m ʼ := e 1 , e 2 ; i, m := 0, 0 while (p 1 ) ¬ (i < n) r ʼ := e 3 ; while (p 2 ) i ʼ , m ʼ := e 1 , e 2 r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; (p 1 ) m ʼ := e 7 ; r ʼ := e 3 ¬ (p 2 ) m ʼ := e 7 ¬ (p 1 )
Symbolic execution of program paths (n 0 >=0) ∧ (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ i 1 = 0 ∧ m 1 = 0 ∧ (i 1 < n 0 ) ∧ ¬ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) (p 1V ʼ ) ∧ ¬ (p 1V ) r := 1; r ʼ 1 =e 3V ʼ ∧ while (i+1 < n && A[i] = A[i+1]) ⇒ identity ¬ (p 2V ʼʼ ) ∧ r, i := r + 1, i+1; m ʼ 2 =e 7V ʼʼ ∧ A[m], N[m], m, i := A[i], r, m+1, i+1; ⇒ identity ¬ (p 1V ʼʼʼ ) i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths (n 0 >=0) ∧ (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ i 1 = 0 ∧ m 1 = 0 ∧ (i 1 < n 0 ) ∧ ¬ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) (p 1V ʼ ) ∧ ¬ (p 1V ) r := 1; r ʼ 1 =e 3V ʼ ∧ while (i+1 < n && A[i] = A[i+1]) ⇒ identity ¬ (p 2V ʼʼ ) ∧ r, i := r + 1, i+1; m ʼ 2 =e 7V ʼʼ ∧ A[m], N[m], m, i := A[i], r, m+1, i+1; ⇒ identity ¬ (p 1V ʼʼʼ ) i ʼ , m ʼ := e 1 , e 2 ; while (p 1 ) r ʼ := e 3 ; while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; m ʼ := e 7 ;
Symbolic execution of program paths (n 0 >=0) ∧ (n 0 >=0) ∧ i 1 = 0 ∧ m 1 = 0 ∧ i 1 = 0 ∧ m 1 = 0 ∧ (i 1 < n 0 ) ∧ ¬ ¬ assume(n>=0); (i 1 < n 0 ) ∧ i, m := 0, 0; i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ i ʼ 1 =e 1V ∧ m ʼ 1 =e 2V ∧ while (i < n) (p 1V ʼ ) ∧ ¬ (p 1V ) r := 1; r ʼ 1 =e 3V ʼ ∧ while (i+1 < n && A[i] = A[i+1]) ⇒ identity ¬ (p 2V ʼʼ ) ∧ r, i := r + 1, i+1; m ʼ 2 =e 7V ʼʼ ∧ A[m], N[m], m, i := A[i], r, m+1, i+1; ⇒ identity ¬ (p 1V ʼʼʼ ) (n>=0) i ʼ , m ʼ := e 1 , e 2 ; i, m := 0, 0 while (p 1 ) (i < n) r ʼ := e 3 ; r := 1 while (p 2 ) r ʼ , i ʼ , A ʼ := e 4 , e 5 , e 6 ; (i+1 < n && A[i] = A[i+1]) ¬ m ʼ := e 7 ; A[m], N[m], m, i := A[i], r, m+1, i+1 ¬ (i < n) i ʼ , m ʼ := e 1 , e 2 ¬ (p 1 )
Recommend
More recommend