on master help sign in
Fix potential use-after-free bugs introduced by `Cached<T>`
commit972657ccd198a8a832226ccead44b14731fbc5f4 authorNick Fitzgerald <fitzgen@gmail.com> dateTue 29 Jan 2019, 17:21 (8 years ago) parente457eeb
14 files changed+342−51
.travis.yml+6−2 Cargo.lock+158−16 Cargo.toml+1 compile-tests/Cargo.toml+11 compile-tests/compile-fail/cached_uaf.rs+58 compile-tests/src/main.rs+24 examples/counter/crate/src/lib.rs+5−5 examples/hello-world/crate/src/lib.rs+2−2 examples/input-form/crate/src/lib.rs+4−4 src/cached.rs+2 src/lib.rs+12 src/vdom.rs+50−13 tests/web/cached.rs+7−7 tests/web/main.rs+2−2
.travis.yml+6−2
@@ -29,13 +29,17 @@ matrix:
2929 - name: "build (nightly)"
3030 rust: nightly
3131 script: INSTALL=1 ./build.sh
32− - name: "test (firefox)"
32+ - name: "headless browser tests (firefox)"
3333 rust: stable
3434 addons:
3535 firefox: latest
3636 script: wasm-pack test --firefox --headless
37− - name: "test (chrome)"
37+ - name: "headless browser tests (chrome)"
3838 rust: stable
3939 addons:
4040 chrome: stable
4141 script: wasm-pack test --chrome --headless
42+ - name: "native tests"
43+ rust: stable
44+ install: echo "no install"
45+ script: cargo test --all
Cargo.lock+158−16
@@ -11,7 +11,7 @@ name = "atty"
1111version = "0.2.11"
1212source = "registry+https://github.com/rust-lang/crates.io-index"
1313dependencies = [
14− "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
14+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
1515 "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1616 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
1717]
@@ -29,7 +29,7 @@ dependencies = [
2929 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
3030 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
3131 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
32− "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
32+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
3333 "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
3434 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
3535]
@@ -40,7 +40,7 @@ version = "0.1.28"
4040source = "registry+https://github.com/rust-lang/crates.io-index"
4141dependencies = [
4242 "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
43− "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
43+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
4444]
4545
4646[[package]]
@@ -58,6 +58,33 @@ name = "cfg-if"
5858version = "0.1.6"
5959source = "registry+https://github.com/rust-lang/crates.io-index"
6060
61+[[package]]
62+name = "compile-tests"
63+version = "0.1.0"
64+dependencies = [
65+ "compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
66+ "dodrio 0.1.0",
67+]
68+
69+[[package]]
70+name = "compiletest_rs"
71+version = "0.3.18"
72+source = "registry+https://github.com/rust-lang/crates.io-index"
73+dependencies = [
74+ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
75+ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
76+ "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
77+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
78+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
79+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
80+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
81+ "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
82+ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
83+ "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
84+ "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
85+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
86+]
87+
6188[[package]]
6289name = "console_error_panic_hook"
6390version = "0.1.5"
@@ -76,6 +103,11 @@ dependencies = [
76103 "web-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
77104]
78105
106+[[package]]
107+name = "diff"
108+version = "0.1.11"
109+source = "registry+https://github.com/rust-lang/crates.io-index"
110+
79111[[package]]
80112name = "dodrio"
81113version = "0.1.0"
@@ -157,11 +189,29 @@ dependencies = [
157189 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
158190]
159191
192+[[package]]
193+name = "filetime"
194+version = "0.2.4"
195+source = "registry+https://github.com/rust-lang/crates.io-index"
196+dependencies = [
197+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
198+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
199+ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
200+]
201+
160202[[package]]
161203name = "futures"
162204version = "0.1.25"
163205source = "registry+https://github.com/rust-lang/crates.io-index"
164206
207+[[package]]
208+name = "getopts"
209+version = "0.2.18"
210+source = "registry+https://github.com/rust-lang/crates.io-index"
211+dependencies = [
212+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
213+]
214+
165215[[package]]
166216name = "heck"
167217version = "0.3.1"
@@ -178,6 +228,11 @@ dependencies = [
178228 "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
179229]
180230
231+[[package]]
232+name = "itoa"
233+version = "0.4.3"
234+source = "registry+https://github.com/rust-lang/crates.io-index"
235+
181236[[package]]
182237name = "js-sys"
183238version = "0.3.10"
@@ -193,7 +248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
193248
194249[[package]]
195250name = "libc"
196−version = "0.2.47"
251+version = "0.2.48"
197252source = "registry+https://github.com/rust-lang/crates.io-index"
198253
199254[[package]]
@@ -210,15 +265,25 @@ version = "2.1.3"
210265source = "registry+https://github.com/rust-lang/crates.io-index"
211266dependencies = [
212267 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
213− "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
268+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
269+]
270+
271+[[package]]
272+name = "miow"
273+version = "0.3.3"
274+source = "registry+https://github.com/rust-lang/crates.io-index"
275+dependencies = [
276+ "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
277+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
214278]
215279
216280[[package]]
217281name = "nom"
218−version = "4.1.1"
282+version = "4.2.0"
219283source = "registry+https://github.com/rust-lang/crates.io-index"
220284dependencies = [
221285 "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
286+ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
222287]
223288
224289[[package]]
@@ -262,14 +327,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
262327dependencies = [
263328 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
264329 "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
265− "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
330+ "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
266331 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
267332 "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
268333]
269334
270335[[package]]
271336name = "regex-syntax"
272−version = "0.6.4"
337+version = "0.6.5"
273338source = "registry+https://github.com/rust-lang/crates.io-index"
274339dependencies = [
275340 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -280,11 +345,64 @@ name = "rustc-demangle"
280345version = "0.1.13"
281346source = "registry+https://github.com/rust-lang/crates.io-index"
282347
348+[[package]]
349+name = "rustfix"
350+version = "0.4.4"
351+source = "registry+https://github.com/rust-lang/crates.io-index"
352+dependencies = [
353+ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
354+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
355+ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
356+ "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
357+ "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
358+]
359+
360+[[package]]
361+name = "ryu"
362+version = "0.2.7"
363+source = "registry+https://github.com/rust-lang/crates.io-index"
364+
283365[[package]]
284366name = "scoped-tls"
285367version = "0.1.2"
286368source = "registry+https://github.com/rust-lang/crates.io-index"
287369
370+[[package]]
371+name = "serde"
372+version = "1.0.85"
373+source = "registry+https://github.com/rust-lang/crates.io-index"
374+
375+[[package]]
376+name = "serde_derive"
377+version = "1.0.85"
378+source = "registry+https://github.com/rust-lang/crates.io-index"
379+dependencies = [
380+ "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
381+ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
382+ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
383+]
384+
385+[[package]]
386+name = "serde_json"
387+version = "1.0.37"
388+source = "registry+https://github.com/rust-lang/crates.io-index"
389+dependencies = [
390+ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
391+ "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
392+ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
393+]
394+
395+[[package]]
396+name = "socket2"
397+version = "0.3.8"
398+source = "registry+https://github.com/rust-lang/crates.io-index"
399+dependencies = [
400+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
401+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
402+ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
403+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
404+]
405+
288406[[package]]
289407name = "sourcefile"
290408version = "0.1.4"
@@ -324,7 +442,7 @@ name = "termion"
324442version = "1.5.1"
325443source = "registry+https://github.com/rust-lang/crates.io-index"
326444dependencies = [
327− "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
445+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
328446 "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
329447 "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
330448]
@@ -347,6 +465,11 @@ name = "unicode-segmentation"
347465version = "1.2.1"
348466source = "registry+https://github.com/rust-lang/crates.io-index"
349467
468+[[package]]
469+name = "unicode-width"
470+version = "0.1.5"
471+source = "registry+https://github.com/rust-lang/crates.io-index"
472+
350473[[package]]
351474name = "unicode-xid"
352475version = "0.1.0"
@@ -357,6 +480,11 @@ name = "utf8-ranges"
357480version = "1.0.2"
358481source = "registry+https://github.com/rust-lang/crates.io-index"
359482
483+[[package]]
484+name = "version_check"
485+version = "0.1.5"
486+source = "registry+https://github.com/rust-lang/crates.io-index"
487+
360488[[package]]
361489name = "wasm-bindgen"
362490version = "0.2.33"
@@ -470,7 +598,7 @@ name = "weedle"
470598version = "0.8.0"
471599source = "registry+https://github.com/rust-lang/crates.io-index"
472600dependencies = [
473− "nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
601+ "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
474602]
475603
476604[[package]]
@@ -489,7 +617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
489617
490618[[package]]
491619name = "winapi-util"
492−version = "0.1.1"
620+version = "0.1.2"
493621source = "registry+https://github.com/rust-lang/crates.io-index"
494622dependencies = [
495623 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -506,7 +634,7 @@ version = "1.0.1"
506634source = "registry+https://github.com/rust-lang/crates.io-index"
507635dependencies = [
508636 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
509− "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
637+ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
510638]
511639
512640[metadata]
@@ -518,29 +646,41 @@ dependencies = [
518646"checksum bumpalo 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38da2bd7a4195f03c07e3cb21d7963729722541c6b94ec245ac818eab48b2ff7"
519647"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
520648"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
649+"checksum compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0d76d4322a40f6b0db7259d4f2c8a65ed8b0d84fce0bbc61b98cf47f8ec6eec3"
521650"checksum console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5dd2c094474ec60a6acaf31780af270275e3153bafff2db5995b715295762e"
522651"checksum console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e7871d2947441b0fdd8e2bd1ce2a2f75304f896582c0d572162d48290683c48"
652+"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
523653"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
524654"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
525655"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
656+"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
526657"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
658+"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
527659"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
528660"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
661+"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
529662"checksum js-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f0edfcbe54ba2071053f2e67f5dfbcea344b69aedfb371b76e27392427a5750f"
530663"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
531−"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
664+"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
532665"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
533666"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8"
534−"checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
667+"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
668+"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588"
535669"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978"
536670"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
537671"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
538672"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
539673"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
540674"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
541−"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
675+"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
542676"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
677+"checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56"
678+"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
543679"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
680+"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752"
681+"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4"
682+"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e"
683+"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
544684"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
545685"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
546686"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
@@ -549,8 +689,10 @@ dependencies = [
549689"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
550690"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
551691"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
692+"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
552693"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
553694"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
695+"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
554696"checksum wasm-bindgen 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "2d8c1eb210a0e91e24feb8ccd6f7484a5d442bfdf2ff179204b3a1d16e1029cc"
555697"checksum wasm-bindgen-backend 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "57ab9a5e88bf5dea5be82bb5f8b68c0f8e550675796ac88570ea4c4e89923413"
556698"checksum wasm-bindgen-futures 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d35a917b7c857bf8bce3e47d51d7d74a074d467aa2b750857fc7d9f878483124"
@@ -564,6 +706,6 @@ dependencies = [
564706"checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
565707"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
566708"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
567−"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
709+"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
568710"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
569711"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
Cargo.toml+1
@@ -41,6 +41,7 @@ opt-level = "s"
4141
4242[workspace]
4343members = [
44+ "./compile-tests",
4445 "./examples/counter/crate",
4546 "./examples/hello-world/crate",
4647 "./examples/input-form/crate",
compile-tests/Cargo.tomlnew file+11
@@ -0,0 +1,11 @@
1+[package]
2+name = "compile-tests"
3+version = "0.1.0"
4+authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
5+publish = false
6+
7+[dependencies]
8+dodrio = { path = ".." }
9+
10+[dev-dependencies]
11+compiletest_rs = "0.3.18"
compile-tests/compile-fail/cached_uaf.rsnew file+58
@@ -0,0 +1,58 @@
1+extern crate bumpalo;
2+extern crate dodrio;
3+extern crate web_sys;
4+
5+use bumpalo::Bump;
6+use dodrio::{Cached, Node, Render, Vdom};
7+use std::cell::Cell;
8+
9+pub struct CountRenders {
10+ render_count: Cell<usize>,
11+}
12+
13+impl CountRenders {
14+ pub fn new() -> CountRenders {
15+ CountRenders {
16+ render_count: Cell::new(0),
17+ }
18+ }
19+}
20+
21+impl Render for CountRenders {
22+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
23+ where
24+ 'a: 'bump,
25+ {
26+ let count = self.render_count.get() + 1;
27+ self.render_count.set(count);
28+
29+ let s = bumpalo::format!(in bump, "{}", count);
30+ Node::text(s.into_bump_str())
31+ }
32+}
33+
34+fn use_after_free_with_cached_components() {
35+ let container = web_sys::window()
36+ .unwrap()
37+ .document()
38+ .unwrap()
39+ .create_element("div")
40+ .unwrap();
41+
42+ // Create a component that caches its own rendered results.
43+ let mut cached = Cached::new(CountRenders::new());
44+
45+ // The vdom's current root is pointing into cached's bump memory.
46+ let mut vdom = Vdom::new(&container, &cached);
47+
48+ // Drop the cached component and its bump memory.
49+ drop(cached);
50+ //~^ ERROR
51+
52+ // Rendering a new component will diff against the current component's last
53+ // render, which will be stored in the (now freed) bump inside
54+ // `Cached`. Yikes!
55+ vdom.render_component(&CountRenders::new());
56+}
57+
58+fn main() {}
compile-tests/src/main.rsnew file+24
@@ -0,0 +1,24 @@
1+#![cfg(test)]
2+
3+extern crate compiletest_rs as compiletest;
4+
5+use std::path::PathBuf;
6+
7+fn run_mode(mode: &'static str) {
8+ let mut config = compiletest::Config::default();
9+
10+ config.mode = mode.parse().expect("Invalid mode");
11+ config.src_base = PathBuf::from(format!("{}", mode));
12+
13+ // Populate config.target_rustcflags with dependencies on the path.
14+ config.link_deps();
15+ // If your tests import the parent crate, this helps with E0464
16+ config.clean_rmeta();
17+
18+ compiletest::run_tests(&config);
19+}
20+
21+#[test]
22+fn compile_test() {
23+ run_mode("compile-fail");
24+}
examples/counter/crate/src/lib.rs+5−5
@@ -65,8 +65,8 @@ pub fn run() {
6565 let document = window.document().unwrap();
6666 let body = document.body().unwrap();
6767
68− let mut counter = Counter::new();
69− let mut vdom = dodrio::Vdom::new(&body, &counter);
68+ let counter = Counter::new();
69+ let mut vdom = dodrio::Vdom::new(&body, counter);
7070
7171 let on_click = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
7272 match event
@@ -74,11 +74,11 @@ pub fn run() {
7474 .and_then(|t| t.dyn_into::<web_sys::Element>().ok())
7575 .and_then(|e| e.get_attribute("data-action"))
7676 {
77− Some(ref s) if s == "increment" => counter.increment(),
78− Some(ref s) if s == "decrement" => counter.decrement(),
77+ Some(ref s) if s == "increment" => vdom.component_mut().increment(),
78+ Some(ref s) if s == "decrement" => vdom.component_mut().decrement(),
7979 _ => {}
8080 }
81− vdom.render(&counter);
81+ vdom.render();
8282 }) as Box<FnMut(_)>);
8383
8484 let _ = body.add_event_listener_with_callback("click", on_click.as_ref().unchecked_ref());
examples/hello-world/crate/src/lib.rs+2−2
@@ -34,8 +34,8 @@ pub fn run() {
3434
3535 // Create a new dodrio vdom contained in the body, with an initial virtual
3636 // dom.
37− let mut vdom = dodrio::Vdom::new(body.as_ref(), &HelloWorld::new("World"));
37+ let vdom = dodrio::Vdom::new(body.as_ref(), HelloWorld::new("World"));
3838
3939 // Render a new node tree into the virtual dom.
40− vdom.render(&HelloWorld::new("Dodrio"));
40+ vdom.render_component(HelloWorld::new("Dodrio"));
4141}
examples/input-form/crate/src/lib.rs+4−4
@@ -54,8 +54,8 @@ pub fn run() {
5454 let document = window.document().unwrap();
5555 let body = document.body().unwrap();
5656
57− let mut say_hello = SayHelloTo::new("World");
58− let mut vdom = dodrio::Vdom::new(&body, &say_hello);
57+ let say_hello = SayHelloTo::new("World");
58+ let mut vdom = dodrio::Vdom::new(&body, say_hello);
5959
6060 let on_input = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
6161 let input = match event
@@ -66,8 +66,8 @@ pub fn run() {
6666 None => return,
6767 };
6868
69− say_hello.set_who(input.value());
70− vdom.render(&say_hello);
69+ vdom.component_mut().set_who(input.value());
70+ vdom.render();
7171 }) as Box<FnMut(_)>);
7272
7373 let _ = body.add_event_listener_with_callback("input", on_input.as_ref().unchecked_ref());
src/cached.rs+2
@@ -28,6 +28,7 @@ impl<R> Cached<R> {
2828 /// # Example
2929 ///
3030 /// ```
31+ /// use bumpalo::Bump;
3132 /// use dodrio::{Cached, Node, Render};
3233 ///
3334 /// pub struct Counter {
@@ -74,6 +75,7 @@ impl<R> Cached<R> {
7475 /// displaying greetings to old `who`s.
7576 ///
7677 /// ```
78+ /// use bumpalo::Bump;
7779 /// use dodrio::{Cached, Node, Render};
7880 ///
7981 /// /// A component that renders to "<p>Hello, {who}!</p>"
src/lib.rs+12
@@ -18,3 +18,15 @@ pub trait Render {
1818 where
1919 'a: 'bump;
2020}
21+
22+impl<'r, R> Render for &'r R
23+where
24+ R: Render,
25+{
26+ fn render<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
27+ where
28+ 'a: 'bump,
29+ {
30+ (**self).render(bump)
31+ }
32+}
src/vdom.rs+50−13
@@ -6,12 +6,14 @@ use log::*;
66use std::cmp;
77use std::mem;
88
9−pub struct Vdom {
9+pub struct Vdom<R> {
10+ component: R,
1011 dom_buffers: [Bump; 2],
1112 change_list: ChangeList,
1213 container: web_sys::Element,
1314
14− // Actually a reference into `self.dom_buffers[0]`.
15+ // Actually a reference into `self.dom_buffers[0]` or if `self.component` is
16+ // caching renders, into `self.component`'s bump.
1517 current_root: Option<Node<'static>>,
1618}
1719
@@ -19,11 +21,11 @@ unsafe fn extend_node_lifetime<'a>(node: Node<'a>) -> Node<'static> {
1921 mem::transmute(node)
2022}
2123
22−impl Vdom {
23− pub fn new<R>(container: &web_sys::Element, contents: &R) -> Vdom
24− where
25− R: Render,
26− {
24+impl<R> Vdom<R>
25+where
26+ R: Render,
27+{
28+ pub fn new(container: &web_sys::Element, component: R) -> Vdom<R> {
2729 let dom_buffers = [Bump::new(), Bump::new()];
2830 let change_list = ChangeList::new(container);
2931
@@ -49,26 +51,45 @@ impl Vdom {
4951 // Diff and apply the `contents` against our dummy `<div/>`.
5052 let container = container.clone();
5153 let mut vdom = Vdom {
54+ component,
5255 dom_buffers,
5356 change_list,
5457 container,
5558 current_root,
5659 };
57− vdom.render(contents);
60+ vdom.render();
5861 vdom
5962 }
6063
64+ /// Get a shared reference to the underlying render component.
65+ #[inline]
66+ pub fn component(&self) -> &R {
67+ &self.component
68+ }
69+
70+ /// Get an exclusive reference to the underlying render component.
71+ #[inline]
72+ pub fn component_mut(&mut self) -> &mut R {
73+ &mut self.component
74+ }
75+
76+ /// Take the render component out of this virtual DOM.
77+ #[inline]
78+ pub fn into_component(self) -> R {
79+ self.component
80+ }
81+
82+ /// Get a reference to the physical DOM node that reflects this virtual DOM
83+ /// tree.
6184 pub fn container(&self) -> &web_sys::Element {
6285 &self.container
6386 }
6487
65− pub fn render<R>(&mut self, contents: &R)
66− where
67− R: Render,
68− {
88+ /// Re-render this virtual dom's current component.
89+ pub fn render(&mut self) {
6990 unsafe {
7091 self.dom_buffers[1].reset();
71− let new_contents = contents.render(&self.dom_buffers[1]);
92+ let new_contents = self.component.render(&self.dom_buffers[1]);
7293 let new_contents = extend_node_lifetime(new_contents);
7394
7495 let old_contents = self.current_root.take().unwrap();
@@ -81,6 +102,22 @@ impl Vdom {
81102 }
82103 }
83104
105+ /// Render a new component.
106+ pub fn render_component<S>(self, component: S) -> Vdom<S>
107+ where
108+ S: Render,
109+ {
110+ let mut vdom = Vdom {
111+ component,
112+ dom_buffers: self.dom_buffers,
113+ change_list: self.change_list,
114+ container: self.container,
115+ current_root: self.current_root,
116+ };
117+ vdom.render();
118+ vdom
119+ }
120+
84121 fn swap_buffers(&mut self) {
85122 let (first, second) = self.dom_buffers.as_mut().split_at_mut(1);
86123 mem::swap(&mut first[0], &mut second[0]);
tests/web/cached.rs+7−7
@@ -32,20 +32,20 @@ impl Render for CountRenders {
3232#[wasm_bindgen_test]
3333fn uses_cached_render() {
3434 let container = create_element("div");
35− let mut cached = Cached::new(CountRenders::new());
36− let mut vdom = Vdom::new(&container, &cached);
35+ let cached = Cached::new(CountRenders::new());
36+ let mut vdom = Vdom::new(&container, cached);
3737
3838 for _ in 0..10 {
39− vdom.render(&cached);
40− assert_eq!(cached.render_count.get(), 1);
39+ vdom.render();
40+ assert_eq!(vdom.component().render_count.get(), 1);
4141 assert_rendered(&container, &RenderFn(|_| Node::text("1")))
4242 }
4343
44− Cached::invalidate(&mut cached);
44+ Cached::invalidate(vdom.component_mut());
4545
4646 for _ in 0..10 {
47− vdom.render(&cached);
48− assert_eq!(cached.render_count.get(), 2);
47+ vdom.render();
48+ assert_eq!(vdom.component().render_count.get(), 2);
4949 assert_rendered(&container, &RenderFn(|_| Node::text("2")))
5050 }
5151}
tests/web/main.rs+2−2
@@ -150,12 +150,12 @@ where
150150 let container = create_element("div");
151151
152152 debug!("====== Rendering the *before* DOM into the physical DOM ======");
153− let mut vdom = Vdom::new(&container, &before);
153+ let vdom = Vdom::new(&container, &before);
154154 debug!("====== Checking the *before* DOM against the physical DOM ======");
155155 assert_rendered(&container, &before);
156156
157157 debug!("====== Rendering the *after* DOM into the physical DOM ======");
158− vdom.render(&after);
158+ vdom.render_component(&after);
159159 debug!("====== Checking the *after* DOM against the physical DOM ======");
160160 assert_rendered(&container, &after);
161161}