浏览代码

LibJS: Add bounds check to Array.prototype.{find,findIndex}

The number of iterations is limited to the initial array size, but we
still need to check if the array did shrink since then before accessing
each element.

Fixes #1992.
Linus Groh 5 年之前
父节点
当前提交
c14fedd562
共有 2 个文件被更改,包括 31 次插入0 次删除
  1. 6 0
      Libraries/LibJS/Runtime/ArrayPrototype.cpp
  2. 25 0
      Libraries/LibJS/Tests/array-shrink-during-find-crash.js

+ 6 - 0
Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -441,6 +441,9 @@ Value ArrayPrototype::find(Interpreter& interpreter)
     auto array_size = array->elements().size();
     auto array_size = array->elements().size();
 
 
     for (size_t i = 0; i < array_size; ++i) {
     for (size_t i = 0; i < array_size; ++i) {
+        if (i >= array->elements().size())
+            break;
+
         auto value = array->elements().at(i);
         auto value = array->elements().at(i);
         if (value.is_empty())
         if (value.is_empty())
             continue;
             continue;
@@ -475,6 +478,9 @@ Value ArrayPrototype::find_index(Interpreter& interpreter)
     auto array_size = array->elements().size();
     auto array_size = array->elements().size();
 
 
     for (size_t i = 0; i < array_size; ++i) {
     for (size_t i = 0; i < array_size; ++i) {
+        if (i >= array->elements().size())
+            break;
+
         auto value = array->elements().at(i);
         auto value = array->elements().at(i);
         if (value.is_empty())
         if (value.is_empty())
             continue;
             continue;

+ 25 - 0
Libraries/LibJS/Tests/array-shrink-during-find-crash.js

@@ -0,0 +1,25 @@
+load("test-common.js");
+
+try {
+    var a, callbackCalled;
+
+    callbackCalled = 0;
+    a = [1, 2, 3, 4, 5];
+    a.find(() => {
+        callbackCalled++;
+        a.pop();
+    });
+    assert(callbackCalled === 3);
+
+    callbackCalled = 0;
+    a = [1, 2, 3, 4, 5];
+    a.findIndex(() => {
+        callbackCalled++;
+        a.pop();
+    });
+    assert(callbackCalled === 3);
+
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e);
+}