Fixed: #2473, #2530 Always-break loops containing breaks (forward gotos)

This commit is contained in:
Jindra Petřík
2026-01-25 12:49:05 +01:00
parent 8397d32772
commit 281b35f3bf
22 changed files with 686 additions and 332 deletions

View File

@@ -2608,5 +2608,44 @@ public class ActionScript2Test extends ActionScript2TestBase {
+ "trace(\"breakDetectionTest\");\r\n"
);
}
@Test
public void frame96_doWhileTwiceTest() {
compareSrc(96, "trace(\"doWhileTwiceTest\");\r\n"
+ "var a = 1;\r\n"
+ "var b = 2;\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(a)\r\n"
+ "{\r\n"
+ "trace(\"x\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"y\");\r\n"
+ "}\r\n"
+ "trace(\"z\");\r\n"
+ "if(false)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"g\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"h\");\r\n"
+ "if(false)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"finish\");\r\n"
);
}
//--FRAMES-END--
}

View File

@@ -40,28 +40,23 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
@Test
public void testAlwaysBreak() {
decompileMethod("assembled", "testAlwaysBreak", "if(true)\r\n"
+ "{\r\n"
+ "var v:* = 5;\r\n"
decompileMethod("assembled", "testAlwaysBreak", "var v:* = 5;\r\n"
+ "trace(\"a\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 4)\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "if(v > 10)\r\n"
+ "{\r\n"
+ "trace(\"c\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"d\");\r\n"
+ "addr003e:\r\n"
+ "}\r\n"
+ "trace(\"e\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "§§goto(addr004e);\r\n"
+ "}\r\n"
+ "§§goto(addr003e);\r\n"
+ "}\r\n"
+ "addr004e:\r\n"
+ "trace(\"f\");\r\n",
false);
}
@@ -70,23 +65,22 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
public void testAlwaysBreak2() {
decompileMethod("assembled", "testAlwaysBreak2", "var v:* = 5;\r\n"
+ "trace(\"a\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 4)\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "if(v > 10)\r\n"
+ "{\r\n"
+ "trace(\"c\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"d\");\r\n"
+ "addr003e:\r\n"
+ "}\r\n"
+ "trace(\"e\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"f\");\r\n"
+ "return;\r\n"
+ "}\r\n"
+ "§§goto(addr003e);\r\n",
+ "trace(\"f\");\r\n",
false);
}
@@ -206,56 +200,66 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
@Test
public void testGoto() {
decompileMethod("assembled", "testGoto", "var v:* = 5;\r\n"
+ "loop0:\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 1)\r\n"
+ "{\r\n"
+ "trace(\"a\");\r\n"
+ "if(v > 2)\r\n"
+ "{\r\n"
+ "trace(\"goto\");\r\n"
+ "addr0052:\r\n"
+ "trace(\"f\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"b\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "addr003d:\r\n"
+ "trace(\"c\");\r\n"
+ "}\r\n"
+ "trace(\"d\");\r\n"
+ "if(v > 3)\r\n"
+ "{\r\n"
+ "trace(\"e\");\r\n"
+ "§§goto(addr0052);\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"g\");\r\n"
+ "break loop0;\r\n"
+ "}\r\n"
+ "trace(\"f\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n"
+ "return;\r\n"
+ "}\r\n"
+ "trace(\"c\");\r\n"
+ "§§goto(addr003d);\r\n",
+ "trace(\"end\");\r\n",
false);
}
@Test
public void testGoto2() {
decompileMethod("assembled", "testGoto2", "var v:* = 5;\r\n"
+ "loop0:\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "loop1:\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 1)\r\n"
+ "{\r\n"
+ "trace(\"a\");\r\n"
+ "if(v > 2)\r\n"
+ "{\r\n"
+ "trace(\"goto\");\r\n"
+ "addr0062:\r\n"
+ "trace(\"g\");\r\n"
+ "addr0069:\r\n"
+ "trace(\"h\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"b\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "addr003d:\r\n"
+ "trace(\"c\");\r\n"
+ "}\r\n"
+ "trace(\"d\");\r\n"
+ "if(v > 3)\r\n"
+ "{\r\n"
@@ -263,20 +267,20 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
+ "if(b > 5)\r\n"
+ "{\r\n"
+ "trace(\"f\");\r\n"
+ "§§goto(addr0062);\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "§§goto(addr0069);\r\n"
+ "break loop1;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"i\");\r\n"
+ "break loop0;\r\n"
+ "}\r\n"
+ "trace(\"g\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n"
+ "return;\r\n"
+ "trace(\"h\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"c\");\r\n"
+ "§§goto(addr003d);\r\n",
+ "trace(\"end\");\r\n",
false);
}

View File

@@ -45,6 +45,30 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile
false);
}
@Test
public void testAlwaysBreak() {
decompileMethod("classic_air", "testAlwaysBreak", "var v:* = undefined;\r\n"
+ "v = 5;\r\n"
+ "trace(\"a\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 4)\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "if(v > 10)\r\n"
+ "{\r\n"
+ "trace(\"c\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"d\");\r\n"
+ "}\r\n"
+ "trace(\"e\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"f\");\r\n",
false);
}
@Test
public void testAndOrCoercion() {
decompileMethod("classic_air", "testAndOrCoercion", "var x:TestInterface = ti || (ti = new TestClass()) && (ti = new TestClass());\r\n"
@@ -552,6 +576,36 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile
false);
}
@Test
public void testDoWhileTwice() {
decompileMethod("classic_air", "testDoWhileTwice", "var a:int = 1;\r\n"
+ "var b:int = 2;\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(a)\r\n"
+ "{\r\n"
+ "trace(\"x\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"y\");\r\n"
+ "}\r\n"
+ "trace(\"z\");\r\n"
+ "}\r\n"
+ "trace(\"g\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"h\");\r\n"
+ "}\r\n"
+ "trace(\"finish\");\r\n",
false);
}
@Test
public void testDotParent() {
decompileMethod("classic_air", "testDotParent", "var d:* = new TestClass1();\r\n"

View File

@@ -45,6 +45,30 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes
false);
}
@Test
public void testAlwaysBreak() {
decompileMethod("classic", "testAlwaysBreak", "var v:* = undefined;\r\n"
+ "v = 5;\r\n"
+ "trace(\"a\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(v > 4)\r\n"
+ "{\r\n"
+ "trace(\"b\");\r\n"
+ "if(v > 10)\r\n"
+ "{\r\n"
+ "trace(\"c\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"d\");\r\n"
+ "}\r\n"
+ "trace(\"e\");\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"f\");\r\n",
false);
}
@Test
public void testAndOrCoercion() {
decompileMethod("classic", "testAndOrCoercion", "var x:TestInterface = this.ti || (this.ti = new TestClass()) && (this.ti = new TestClass());\r\n"
@@ -553,6 +577,39 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes
false);
}
@Test
public void testDoWhileTwice() {
decompileMethod("classic", "testDoWhileTwice", "var a:* = 1;\r\n"
+ "var b:* = 2;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "do\r\n"
+ "{\r\n"
+ "if(a)\r\n"
+ "{\r\n"
+ "trace(\"x\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"y\");\r\n"
+ "}\r\n"
+ "trace(\"z\");\r\n"
+ "}\r\n"
+ "while(true);\r\n"
+ "\r\n"
+ "trace(\"g\");\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"h\");\r\n"
+ "}\r\n"
+ "while(true);\r\n"
+ "trace(\"finish\");\r\n",
false);
}
@Test
public void testDotParent() {
decompileMethod("classic", "testDotParent", "var d:* = undefined;\r\n"

View File

@@ -66,7 +66,7 @@ public class AS3Generator {
sortedPacks.put(pack.getClassPath().toRawString(), pack);
}
s.append("/*\r\n"
+ " * Copyright (C) 2010-2025 JPEXS, All rights reserved.\r\n"
+ " * Copyright (C) 2010-2026 JPEXS, All rights reserved.\r\n"
+ " * \r\n"
+ " * This library is free software; you can redistribute it and/or\r\n"
+ " * modify it under the terms of the GNU Lesser General Public\r\n"