<div dir="ltr"><div>Hi,</div><div><br></div><div>Last night I stumble into the Mealtdown and Spectre exploits news and read the papers, didn't sleep much. So I decided to see what could be done to get better Javascript protection against speculative buffer overruns.<br></div><div><br></div><div>I have wanted to check this out for some time but at last, I downloaded Firefox source code today and I started to figure out if some protections could be added. This is just dev poking around and I would like to ask if I am at least in the right direction.</div><div><br></div><div>I briefly when over the code and I figure that NativeObject.h seems to declare array indexing code used at least from the Javascript interpreter. So I made the following changes that I understand should cut short any speculative buffer overrun at least in these patched functions. I know this has performance issues but it is just a test.<br></div><div><br></div><div>I compiled this and I am running Firefox in safe mode (from what I gather this disables the jit compiler which I haven't even begin to look at).</div><div><br></div><div>I would like to ask if at least I am in the right direction or am I way off course.<br></div><div><br></div><div>diff -r f78a83244fbe js/src/vm/NativeObject.h<br>--- a/js/src/vm/NativeObject.h    Thu Jan 04 11:44:30 2018 +0200<br>+++ b/js/src/vm/NativeObject.h    Thu Jan 04 16:05:11 2018 -0300<br>@@ -496,11 +496,13 @@<br>         return HeapSlotArray(elements_, true);<br>     }<br>     const Value& getDenseElement(uint32_t idx) const {<br>-        MOZ_ASSERT(idx < getDenseInitializedLength());<br>-        return elements_[idx];<br>+        uint32_t len = getDenseInitializedLength();<br>+        MOZ_ASSERT(idx < len);<br>+        return elements_[idx % len];<br>     }<br>     bool containsDenseElement(uint32_t idx) {<br>-        return idx < getDenseInitializedLength() && !elements_[idx].isMagic(JS_ELEMENTS_HOLE);<br>+        uint32_t len = getDenseInitializedLength();<br>+        return idx < len && !elements_[idx % len].isMagic(JS_ELEMENTS_HOLE);<br>     }<br>     uint32_t getDenseInitializedLength() const {<br>         return getElementsHeader()->initializedLength;<br>@@ -1196,9 +1198,11 @@<br>     // objects, but should only be called in a few places, and should be<br>     // audited carefully!<br>     void setDenseElementUnchecked(uint32_t index, const Value& val) {<br>-        MOZ_ASSERT(index < getDenseInitializedLength());<br>+        uint32_t len = getDenseInitializedLength();<br>+        MOZ_ASSERT(index < len);<br>         MOZ_ASSERT(!denseElementsAreCopyOnWrite());<br>         checkStoredValue(val);<br>+        index %= len;<br>         elements_[index].set(this, HeapSlot::Element, unshiftedIndex(index), val);<br>     }<br> <br>@@ -1217,10 +1221,12 @@<br>     }<br> <br>     void initDenseElement(uint32_t index, const Value& val) {<br>-        MOZ_ASSERT(index < getDenseInitializedLength());<br>+        uint32_t len = getDenseInitializedLength();<br>+        MOZ_ASSERT(index < len);<br>         MOZ_ASSERT(!denseElementsAreCopyOnWrite());<br>         MOZ_ASSERT(!denseElementsAreFrozen());<br>         checkStoredValue(val);<br>+        index %= len;<br>         elements_[index].init(this, HeapSlot::Element, unshiftedIndex(index), val);<br>     }<br> </div><div><br></div><div>Regards,</div><div>llongeri<br></div></div>