Forráskód Böngészése

Fixed panics when iterator returns values with missing properties.

Dmitry Panov 5 éve
szülő
commit
d63d7d53d2
5 módosított fájl, 87 hozzáadás és 5 törlés
  1. 2 2
      builtin_map.go
  2. 59 0
      builtin_map_test.go
  3. 23 0
      builtin_set_test.go
  4. 1 1
      builtin_weakmap.go
  5. 2 2
      runtime.go

+ 2 - 2
builtin_map.go

@@ -157,8 +157,8 @@ func (r *Runtime) builtin_newMap(args []Value) *Object {
 			if adder == r.global.mapAdder {
 				r.iterate(iter, func(item Value) {
 					itemObj := r.toObject(item)
-					k := itemObj.self.get(i0)
-					v := itemObj.self.get(i1)
+					k := nilSafe(itemObj.self.get(i0))
+					v := nilSafe(itemObj.self.get(i1))
 					mo.m.set(k, v)
 				})
 			} else {

+ 59 - 0
builtin_map_test.go

@@ -0,0 +1,59 @@
+package goja
+
+import "testing"
+
+func TestMapEvilIterator(t *testing.T) {
+	const SCRIPT = `
+	'use strict';
+	var o = {};
+
+	function Iter(value) {
+		this.value = value;
+		this.idx = 0;
+	}
+
+	Iter.prototype.next = function() {
+		var idx = this.idx;
+		if (idx === 0) {
+			this.idx++;
+			return this.value;
+		}
+		return {done: true};
+	}
+
+	o[Symbol.iterator] = function() {
+		return new Iter({});
+	}
+
+	assert.throws(TypeError, function() {
+		new Map(o);
+	});
+
+	o[Symbol.iterator] = function() {
+		return new Iter({value: []});
+	}
+
+	function t(prefix) {
+		var m = new Map(o);
+		assert.sameValue(1, m.size, prefix+": m.size");
+		assert.sameValue(true, m.has(undefined), prefix+": m.has(undefined)");
+		assert.sameValue(undefined, m.get(undefined), prefix+": m.get(undefined)");
+	}
+
+	t("standard adder");
+
+	var count = 0;
+	var origSet = Map.prototype.set;
+
+	Map.prototype.set = function() {
+		count++;
+		origSet.apply(this, arguments);
+	}
+
+	t("custom adder");
+	assert.sameValue(1, count, "count");
+
+	undefined;
+	`
+	testScript1(TESTLIB+SCRIPT, _undefined, t)
+}

+ 23 - 0
builtin_set_test.go

@@ -0,0 +1,23 @@
+package goja
+
+import "testing"
+
+func TestSetEvilIterator(t *testing.T) {
+	const SCRIPT = `
+	var o = {};
+	o[Symbol.iterator] = function() {
+		return {
+			next: function() {
+				if (!this.flag) {
+					this.flag = true;
+					return {};
+				}
+				return {done: true};
+			}
+		}
+	}
+	new Set(o);
+	undefined;
+	`
+	testScript1(SCRIPT, _undefined, t)
+}

+ 1 - 1
builtin_weakmap.go

@@ -153,7 +153,7 @@ func (r *Runtime) builtin_newWeakMap(args []Value) *Object {
 				r.iterate(iter, func(item Value) {
 					itemObj := r.toObject(item)
 					k := itemObj.self.get(i0)
-					v := itemObj.self.get(i1)
+					v := nilSafe(itemObj.self.get(i1))
 					wmo.m.set(r.toObject(k), v)
 				})
 			} else {

+ 2 - 2
runtime.go

@@ -1640,11 +1640,11 @@ func (r *Runtime) getIterator(obj *Object, method func(FunctionCall) Value) *Obj
 func (r *Runtime) iterate(iter *Object, step func(Value)) {
 	for {
 		res := r.toObject(toMethod(iter.self.getStr("next"))(FunctionCall{This: iter}))
-		if res.self.getStr("done").ToBoolean() {
+		if nilSafe(res.self.getStr("done")).ToBoolean() {
 			break
 		}
 		err := tryFunc(func() {
-			step(res.self.getStr("value"))
+			step(nilSafe(res.self.getStr("value")))
 		})
 		if err != nil {
 			retMethod := toMethod(iter.self.getStr("return"))