[ASYNC-201] (CLJS) Out-of-bounds index values passed in timers Created: 14/Jul/17 Updated: 15/Jul/17
|Reporter:||Mike Fikes||Assignee:||David Nolen|
|Patch:||Code and Test|
In the cljs.core.async.impl.timers namespace, there are places where an aget call is made with an out-of-bounds index value, with the code instead checking a post-condition that a nil is returned.
(These can be detected at runtime using the new :checked-arrays feature being added to the ClojureScript compiler.)
One specific example is in the SkipList remove implementation where the (aget (.-forward x) 0) call can evidently be made against an empty array (you can see that the code checks for nil as a result of the call instead of checking a precondition that the array has elements).
Another example that I've seen at runtime is the (aget (.-forward x) level) in least-greater-node where evidently level can be either equal to or greater than the length of the array.
|Comment by Mike Fikes [ 15/Jul/17 8:29 AM ]|
The attached ASYNC-201.patch adds tests for the skip list implementation used in the timers namespace and only makes revisions where they are empirically seen to be needed (in other words, it doesn't blindly add checks before every aget and aset call, as many may be fine).
You in addition to running the tests as-is, you can run them with the new checked arrays feature by temporarily changing the project.clj to specify [org.clojure/clojure "1.8.0"] and a locally-build copy of ClojureScript master, and by adding :checked-arrays :warn to the ClojureScript compiler options specified under :cljsbuld (this key-value pair could be added adjacent to every :static-fns setting. You can also run the tests this way without the patch and you will see warnings being emitted for the skip list implementation by virtue of being driven by the existing test suite.