Prechádzať zdrojové kódy

detect out-of-bounds array access and cancel inlining (closes #2999)

Simon Krajewski 11 rokov pred
rodič
commit
e521c6cc86

+ 4 - 2
optimizer.ml

@@ -1242,8 +1242,10 @@ let inline_constructors ctx e =
 			end
 		| TField({eexpr = TLocal v}, (FInstance(_, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) ->
 			()
-		| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) ->
-			()
+		| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
+			let (_,_,fields,_,_) = PMap.find (-v.v_id) !vars in
+			let i = Int32.to_int i in
+			if i < 0 || i >= List.length fields then cancel v
 		| TBinop((OpAssign | OpAssignOp _),e1,e2) ->
 			begin match e1.eexpr with
 				| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 && not (is_valid_field v (Int32.to_string i)) ->

+ 18 - 0
tests/optimization/src/Test.hx

@@ -110,4 +110,22 @@ class Test {
 		var a = [1, 2];
 		var b = a.length;
 	}
+
+	@:js('
+		var a = [1,2];
+		a[-1];
+	')
+	static function testArrayInlineCancelNegative() {
+		var a = [1, 2];
+		a[-1];
+	}
+
+	@:js('
+		var a = [1,2];
+		a[2];
+	')
+	static function testArrayInlineCancelExceeds() {
+		var a = [1, 2];
+		a[2];
+	}
 }

+ 17 - 0
tests/unit/issues/Issue2999.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+class Issue2999 extends Test {
+	function test1() {
+		var a = [1, 2];
+		eq(1, a[0]);
+		eq(2, a[1]);
+		a[-1];
+	}
+
+	function test2() {
+		var a = [1, 2];
+		eq(1, a[0]);
+		eq(2, a[1]);
+		a[2];
+	}
+}