A Simple and Extensible Approach to Program Analysis David Darais University of Maryland University of Vermont
Does my program cause a runtime error? Does my program allocate too much? Does my program sanitize all untrusted inputs? Does my program have any data races?
βΉ My PL Doesnβt Have a Program Analyzer
π€ Should I Write My Own Program Analyzer?
π Writing Your Own Program Analyzer is Easy If you know how to write an interpreter
Abstracting Definitional Interpreters Interpreter => Analyzer Sound Terminating Precise Extensible
β¨ β¨ Hypothesis: β¨ Itβs easier to write a precise semantics than an abstract semantics. Approach: β¨ Write, maintain and debug one precise semantics. Systematically derive multiple static analyzers.
Concrete Interpreter Static Analyzer
Concrete β¨ Interpreter
if (N β 0){ x β 100/N }
if (N β 0){ x β 100/N } N=1
if (N β 0){ x β 100/N } N=1 if (true){ x β 100/N } N=1
if (N β 0){ x β 100/N } N=1 if (true){ x β 100/N } N=1 x β 100/N N=1
if (N β 0){ x β 100/N } N=1 if (true){ x β 100/N } N=1 x β 100/N N=1 100 N=1 x=100
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
eval : exp Γ env β val Γ env eval(Var(x), Ο ) β ( Ο (x), Ο ) eval(Assign(x,e), Ο ) β (v, Οβ² ) β eval(e, Ο ) (v, Οβ² [x β¦ v]) env β var β val eval(Op(o,e β ,e β ), Ο ) β val β πΊ β β€ (v β , Οβ² ) β eval(e β , Ο ) (v β , Οβ³ ) β eval(e β , Οβ² ) Ξ΄ : op Γ val Γ val β val ( Ξ΄ (o,v β ,v β ), Οβ³ ) eval(If(e β ,e β ,e β ), Ο ) β (v β , Οβ² ) β eval(e β , Ο ) cases v β = true β eval(e β , Οβ² ) v β = false β eval(e β , Οβ² )
Concrete β¨ Interpreter
Monadic Concrete β¨ Interpreter
eval : exp Γ env β val Γ env
eval : exp Γ env β val Γ env β eval : exp β M(val) M(val) β env β val Γ env
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env env β var β val put-env Ο [x β¦ v] val β πΊ β β€ return v eval(Op(o,e β ,e β )) β do Ξ΄ : op Γ val Γ val β val β¨ v β β eval(e β ) v β β eval(e β ) M(A) β env β A Γ env return Ξ΄ (o,v β ,v β ) eval(If(e β ,e β ,e β )) β do v β β eval(e β ) cases v β = true β eval(e β ) v β = false β eval(e β )
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env env β var β val put-env Ο [x β¦ v] val β πΊ β β€ return v eval(Op(o,e β ,e β )) β do Ξ΄ : op Γ val Γ val β val β¨ v β β eval(e β ) v β β eval(e β ) M(A) β env β A Γ env return Ξ΄ (o,v β ,v β ) eval(If(e β ,e β ,e β )) β do v β β eval(e β ) cases v β = true β eval(e β ) v β = false β eval(e β )
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env env β var β val put-env Ο [x β¦ v] val β πΊ β β€ return v eval(Op(o,e β ,e β )) β do Ξ΄ : op Γ val Γ val β val β¨ v β β eval(e β ) v β β eval(e β ) M(A) β env β A Γ env return Ξ΄ (o,v β ,v β ) eval(If(e β ,e β ,e β )) β do v β β eval(e β ) cases v β = true β eval(e β ) v β = false β eval(e β )
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env env β var β val put-env Ο [x β¦ v] val β πΊ β β€ return v eval(Op(o,e β ,e β )) β do Ξ΄ : op Γ val Γ val β val β¨ v β β eval(e β ) v β β eval(e β ) M(A) β env β A Γ env return Ξ΄ (o,v β ,v β ) eval(If(e β ,e β ,e β )) β do v β β eval(e β ) cases v β = true β eval(e β ) v β = false β eval(e β )
if (N=0){ x β 100/N }
if (N=0){ x β 100/N } N=0 β
if (N=0){ x β 100/N } N=1 β
if (N=0){ x β 100/N } N=ANY ?
Monadic Concrete β¨ Interpreter
Monadic Abstract β¨ Interpreter
Abstract Values Join Results Variable Refinement
β€ β² {-,0,+} 2 / ( 3 - 1 ) {+} / ({+} - {+}) {+} / {-,0,+} . β {+,-} OR β
β€ β² {-,0,+} 2 / ( 3 - 1 ) {+} / ({+} - {+}) {+} / {-,0,+} . β {+,-} OR β
β€ β² {-,0,+} 2 / ( 3 - 1 ) {+} / ({+} - {+}) {+} / {-,0,+} . β {+,-} OR β
β€ β² {-,0,+} 2 / ( 3 - 1 ) {+} / ({+} - {+}) {+} / {-,0,+} . β {+,-} OR β
β€ β² {-,0,+} 2 / ( 3 - 1 ) {+} / ({+} - {+}) {+} / {-,0,+} . β {+,-} OR β
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env put-env Ο [x β¦ v] return v env β var β val eval(Op(o,e β ,e β )) β do val β β ( πΊ ) β β ({-,0,+}) v β β eval(e β ) v β β eval(e β ) Ξ΄ : op Γ val Γ val β val Γ πΊ (v β ,err) β Ξ΄ (o,v β ,v β ) β¨ β¦ _ β§ : val β β ( πΊ ) join-cases refine : exp Γ πΊ β M(void) β¨ err = true β fail always β return v β M(A) β env β β (A Γ env) Γ πΊ eval(If(e β ,e β ,e β )) β do v β β eval(e β ) Could the operation fail? join-cases β¦ v ββ§ β true β do refine (e β ,true) eval(e β ) β¦ v ββ§ β false β do refine (e β ,false) eval(e β )
Abstract Values Join Results Variable Refinement
eval : exp β M(val) eval(Var(x)) β do Ο β get-env return Ο (x) eval(Assign(x,e)) β do v β eval(e) Ο β get-env put-env Ο [x β¦ v] return v env β var β val eval(Op(o,e β ,e β )) β do val β β ( πΊ ) β β ({-,0,+}) v β β eval(e β ) v β β eval(e β ) Ξ΄ : op Γ val Γ val β val Γ πΊ (v β ,err) β Ξ΄ (o,v β ,v β ) β¨ β¦ _ β§ : val β β ( πΊ ) join-cases refine : exp Γ πΊ β M(void) β¨ err = true β fail always β return v β M(A) β env β β (A Γ env) Γ πΊ eval(If(e β ,e β ,e β )) β do v β β eval(e β ) join-cases β¦ v ββ§ β true β do refine (e β ,true) eval(e β ) β¦ v ββ§ β false β do refine (e β ,false) eval(e β )
Abstract Values Join Results Variable Refinement
if (N β 0){ x β 100/N } N=ANY
if (N β 0){ x β 100/N } N=ANY x β 100/N N β {-,+}
Recommend
More recommend