Virtual Values for Language Extension Thomas H. Austin Tim Disney Cormac Flanagan University of California Santa Cruz ICFP’11
x + y
Extensibility in Python is clean class Complex (object): x = Complex(2, 1) y = Complex(3, 1) def __init__(self, real, imag): self.r = real x + y self.i = imag def __add__(self, other): return Complex(self.r + other.r, self.i + other.i)
Extensibility in JavaScript is ugly function Complex(real, imag) { var x = new Complex(2, 1); this .r = real; var y = new Complex(3, 1); this .i = imag; } x.plus(y); Complex.prototype.plus(other) { return new Complex( this .r + other.r, this .i + other.i); }
Even worse than ugly! function matrixMult(a, b) { ... } matrixMult([[-3,-8,3], [-2,1,4]]) matrixMult([[ new Complex(4,1), new Complex(2,1)], [ new Complex(5,1), new Complex(8,1)]])
x + y vs. x.plus(y)
Virtual Values: Virtualize the interface between code and data
Standard Addition Code Data x y x = 65 y = 1 65 1 + z = x + y z 66
Virtualized Addition Code Data handl handler handler = { ... ... ... plus: λ r. 65 plus λ ... 1 + r ... ... + } 65 p = proxy(handler) z = p + 65 z p 66
λ proxy Idealized JavaScript-like language proxy(handler) { f : v } 24 λ x. e o[f] true e 1 (e 2 ) o[f] = v !true 24 + 42 if b e 1 e 2
p = proxy(h) handler = { get: λ f... p[f] → h.get(f)
Code Data obj = { handl handler “f”: 42 ... ... } get λ ... ... ... handler = { “f” meta get: λ n. base log(...) obj[n] “f” ... “f” } obj obj p p = proxy(handler) “f” 42 p[“f”]
p = proxy(h) handler = { get: λ f... p[f] → h.get(f) set: λ f,v... p[f] = v → h.set(f,v) call: λ v... p(v) → h.call(v) geti: λ r... r[p] → h.geti(r) seti: λ r,v... r[p] = v → h.seti(r,v) unary: λ o... !p → h.unary(“!”) left: λ o,r... p + x → h.left(“+”,x) right: λ o,l... x + p → h.right(“+”,x) test: λ ... if p e e → if h.test() e e }
x = 4.0 + (1.0 * i) y = 3.0 + (1.0 * i) x + y 7 2 imaginary real
meter meter = makeUnit(“meter”) 1 second = makeUnit(“second”) 1 “meter” g = 9.81 * meter / second / second “second” print(g) // “9.81 meters seconds^-2” 9.81 g + 1 // Error: Units not compatible! “meter” 10.81 g + 1 * meter / second / second “second” -2 “meter” “second” -2
isTainted(taint(4) + 5) == true Tainting Extension 4 taint = λ x. + 4 5 ... 9 isTainted = λ x. ... true
Security Extensibility: wants to extend behavior of library extensions Security: wants to restrict behavior of adversaries
Security isProxy(x) Always tells the truth
Stop proxies... critical = λ x. if isProxy(x) then err() else ...
...not quite critical = λ x. if isProxy(x) then err() else y = x() ...
The nonProxy proxy! Trusted Module nonProxy Untrusted Module
The nonProxy proxy! nonProxy x y critical = λ x. x = nonProxy(x) isProxy? y = x() ... y no yes error! nonProxy y
handler = { JavaScript Proxies get: ... set: ... contracts nonProxy call: ... membranes geti: ... Virtual Values seti: ... unary: ... complex taint tracking left: ... units lazy evaluation right: ... test: ... } T. V. Cutsem and M. S. Miller. Proxies: Design principles for robust object-oriented intercession APIs
Recommend
More recommend