Browse Source

Fixed possible panic when sorting non-standard arrays.

Dmitry Panov 4 years ago
parent
commit
ad1be0d693
2 changed files with 61 additions and 5 deletions
  1. 29 5
      builtin_array.go
  2. 32 0
      builtin_arrray_test.go

+ 29 - 5
builtin_array.go

@@ -347,12 +347,36 @@ func (r *Runtime) arrayproto_sort(call FunctionCall) Value {
 		}
 		}
 	}
 	}
 
 
-	ctx := arraySortCtx{
-		obj:     o.self,
-		compare: compareFn,
-	}
+	if r.checkStdArrayObj(o) != nil {
+		ctx := arraySortCtx{
+			obj:     o.self,
+			compare: compareFn,
+		}
 
 
-	sort.Stable(&ctx)
+		sort.Stable(&ctx)
+	} else {
+		length := toLength(o.self.getStr("length", nil))
+		a := make([]Value, 0, length)
+		for i := int64(0); i < length; i++ {
+			idx := valueInt(i)
+			if o.self.hasPropertyIdx(idx) {
+				a = append(a, o.self.getIdx(idx, nil))
+			}
+		}
+		ar := r.newArrayValues(a)
+		ctx := arraySortCtx{
+			obj:     ar.self,
+			compare: compareFn,
+		}
+
+		sort.Stable(&ctx)
+		for i := 0; i < len(a); i++ {
+			o.self.setOwnIdx(valueInt(i), a[i], true)
+		}
+		for i := int64(len(a)); i < length; i++ {
+			o.self.deleteIdx(valueInt(i), true)
+		}
+	}
 	return o
 	return o
 }
 }
 
 

+ 32 - 0
builtin_arrray_test.go

@@ -232,6 +232,38 @@ func TestArraySort(t *testing.T) {
 	testScript1(TESTLIB+SCRIPT, _undefined, t)
 	testScript1(TESTLIB+SCRIPT, _undefined, t)
 }
 }
 
 
+func TestArraySortNonStdArray(t *testing.T) {
+	const SCRIPT = `
+	const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+	Object.defineProperty(array, '2', {
+	  get() {
+		array.pop();
+		array.pop();
+		return this.foo;
+	  },
+	  set(v) {
+		this.foo = v;
+	  }
+	});
+
+	array.sort();
+
+	assert.sameValue(array[0], 'b');
+	assert.sameValue(array[1], 'c');
+	assert.sameValue(array[3], undefined);
+	assert.sameValue(array[4], undefined);
+	assert.sameValue('5' in array, false);
+	assert.sameValue(array.hasOwnProperty('5'), false);
+	assert.sameValue(array.length, 6);
+	assert.sameValue(array.foo, undefined);
+
+	assert.sameValue(array[2], undefined);
+	assert.sameValue(array.length, 4);
+	`
+	testScript1(TESTLIB+SCRIPT, _undefined, t)
+}
+
 func TestArrayConcat(t *testing.T) {
 func TestArrayConcat(t *testing.T) {
 	const SCRIPT = `
 	const SCRIPT = `
 	var concat = Array.prototype.concat;
 	var concat = Array.prototype.concat;