Changed: #2228 AS1/2/3 bitwise operations use hexadecimal operands

This commit is contained in:
Jindra Petřík
2024-08-05 11:17:25 +02:00
parent 5fb20268b2
commit 9683dc6a6f
23 changed files with 226 additions and 33 deletions
+2
View File
@@ -90,6 +90,7 @@ All notable changes to this project will be documented in this file.
- [PR194] Default directory for storing config on Linux changed to `~/.config/FFDec`, when `~/.FFDec` does not exist yet
- Run/Debug command - executed SWF temp files (`~ffdec_run...swf` etc.) are now generated
in the directory where original SWF resides to allow loading relative assets
- [#2228] AS1/2/3 bitwise operations use hexadecimal operands
## [20.1.0] - 2023-12-30
### Added
@@ -3475,6 +3476,7 @@ Major version of SWF to XML export changed to 2.
[#2237]: https://www.free-decompiler.com/flash/issues/2237
[#2234]: https://www.free-decompiler.com/flash/issues/2234
[#2206]: https://www.free-decompiler.com/flash/issues/2206
[#2228]: https://www.free-decompiler.com/flash/issues/2228
[#2100]: https://www.free-decompiler.com/flash/issues/2100
[#2123]: https://www.free-decompiler.com/flash/issues/2123
[#2119]: https://www.free-decompiler.com/flash/issues/2119
@@ -24,8 +24,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +31,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitAndAVM2Item extends BinaryOpItem implements CompoundableBinaryOp {
public class BitAndAVM2Item extends BitwiseBinaryOpAVM2Item {
public BitAndAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEAND, leftSide, rightSide, "&", "Number", "Number");
@@ -62,5 +60,5 @@ public class BitAndAVM2Item extends BinaryOpItem implements CompoundableBinaryOp
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(new AVM2Instruction(0, AVM2Instructions.BitAnd, null));
return ret;
}
}
}
@@ -19,11 +19,14 @@ package com.jpexs.decompiler.flash.abc.avm2.model.operations;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.UnaryOpItem;
import java.util.List;
@@ -54,4 +57,20 @@ public class BitNotAVM2Item extends UnaryOpItem {
return TypeItem.INT; //?
//return TypeItem.UNBOUNDED;
}
@Override
protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException {
if (operand instanceof IntegerValueAVM2Item) {
Integer val = ((IntegerValueAVM2Item)operand).value;
if (val > 9) {
String valHex = Integer.toHexString(val).toUpperCase();
if (valHex.length() % 2 == 1) {
valHex = "0" + valHex;
}
writer.append("0x" + valHex);
return;
}
}
operand.toString(writer, localData, "");
}
}
@@ -24,8 +24,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +31,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitOrAVM2Item extends BinaryOpItem implements CompoundableBinaryOp {
public class BitOrAVM2Item extends BitwiseBinaryOpAVM2Item {
public BitOrAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEOR, leftSide, rightSide, "|", "Number", "Number");
@@ -24,8 +24,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +31,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitXorAVM2Item extends BinaryOpItem implements CompoundableBinaryOp {
public class BitXorAVM2Item extends BitwiseBinaryOpAVM2Item {
public BitXorAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEXOR, leftSide, rightSide, "^", "Number", "Number");
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.model.operations;
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
import com.jpexs.decompiler.graph.model.LocalData;
/**
*
* @author JPEXS
*/
public abstract class BitwiseBinaryOpAVM2Item extends BinaryOpItem implements CompoundableBinaryOp {
public BitwiseBinaryOpAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem leftSide, GraphTargetItem rightSide, String operator, String coerceLeft, String coerceRight) {
super(instruction, lineStartItem, precedence, leftSide, rightSide, operator, coerceLeft, coerceRight);
}
@Override
protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException {
if (operand instanceof IntegerValueAVM2Item) {
Integer val = ((IntegerValueAVM2Item)operand).value;
if (val > 9) {
String valHex = Integer.toHexString(val).toUpperCase();
if (valHex.length() % 2 == 1) {
valHex = "0" + valHex;
}
writer.append("0x" + valHex);
return;
}
}
operand.toString(writer, localData, "");
}
}
@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.action.model.operations;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.action.model.CompoundableBinaryOpAs12;
import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.graph.CompilationException;
@@ -25,7 +24,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +31,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitAndActionItem extends BinaryOpItem implements CompoundableBinaryOpAs12 {
public class BitAndActionItem extends BitwiseBinaryOpActionItem {
public BitAndActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEAND, leftSide, rightSide, "&", "int", "int");
@@ -63,5 +61,5 @@ public class BitAndActionItem extends BinaryOpItem implements CompoundableBinary
List<GraphSourceItem> ret = new ArrayList<>();
ret.add(new ActionBitAnd());
return ret;
}
}
}
@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.action.model.operations;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.action.model.CompoundableBinaryOpAs12;
import com.jpexs.decompiler.flash.action.swf5.ActionBitOr;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.graph.CompilationException;
@@ -25,7 +24,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +31,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitOrActionItem extends BinaryOpItem implements CompoundableBinaryOpAs12 {
public class BitOrActionItem extends BitwiseBinaryOpActionItem {
public BitOrActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEOR, leftSide, rightSide, "|", "int", "int");
@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.action.model.operations;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.action.model.CompoundableBinaryOpAs12;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.swf5.ActionBitXor;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
@@ -27,7 +26,6 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +34,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class BitXorActionItem extends BinaryOpItem implements CompoundableBinaryOpAs12 {
public class BitXorActionItem extends BitwiseBinaryOpActionItem {
public BitXorActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
super(instruction, lineStartIns, PRECEDENCE_BITWISEXOR, leftSide, rightSide, "^", "int", "int");
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model.operations;
import com.jpexs.decompiler.flash.action.model.CompoundableBinaryOpAs12;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.model.BinaryOpItem;
import com.jpexs.decompiler.graph.model.LocalData;
/**
*
* @author JPEXS
*/
public abstract class BitwiseBinaryOpActionItem extends BinaryOpItem implements CompoundableBinaryOpAs12 {
public BitwiseBinaryOpActionItem(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem leftSide, GraphTargetItem rightSide, String operator, String coerceLeft, String coerceRight) {
super(instruction, lineStartItem, precedence, leftSide, rightSide, operator, coerceLeft, coerceRight);
}
@Override
protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException {
if ((operand instanceof DirectValueActionItem) && (((DirectValueActionItem)operand).value instanceof Long)) {
long val = (long)(Long)((DirectValueActionItem)operand).value;
if (val > 9) {
String valHex = Long.toHexString(val).toUpperCase();
if (valHex.length() % 2 == 1) {
valHex = "0" + valHex;
}
writer.append("0x" + valHex);
return;
}
}
operand.toString(writer, localData, "");
}
}
@@ -73,10 +73,10 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp {
int leftPrecedence = leftSide.getPrecedence();
if (leftPrecedence > precedence && leftPrecedence != GraphTargetItem.NOPRECEDENCE) {
writer.append("(");
leftSide.toString(writer, localData, ""); //coerceLeft);
operandToString(leftSide, writer, localData);
writer.append(")");
} else {
leftSide.toString(writer, localData, ""); //coerceLeft);
operandToString(leftSide, writer, localData);
}
writer.append(" ");
@@ -86,13 +86,17 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp {
int rightPrecedence = rightSide.getPrecedence();
if (rightPrecedence >= precedence && rightPrecedence != GraphTargetItem.NOPRECEDENCE) {
writer.append("(");
rightSide.toString(writer, localData, ""); //coerceRight);
operandToString(rightSide, writer, localData);
writer.append(")");
} else {
rightSide.toString(writer, localData, ""); //coerceRight);
operandToString(rightSide, writer, localData);
}
return writer;
}
protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException {
operand.toString(writer, localData, "");
}
@Override
public List<GraphSourceItemPos> getNeededSources() {
@@ -53,10 +53,10 @@ public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp {
if (value != null) {
if (value.getPrecedence() > precedence) {
writer.append("(");
value.toString(writer, localData, ""); //coerce);
operandToString(value, writer, localData);
writer.append(")");
} else {
value.toString(writer, localData, ""); //coerce);
operandToString(value, writer, localData);
}
} else {
writer.append("null");
@@ -146,4 +146,8 @@ public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp {
int hash = 3;
return hash;
}
protected void operandToString(GraphTargetItem operand, GraphTextWriter writer, LocalData localData) throws InterruptedException {
operand.toString(writer, localData, "");
}
}
@@ -2465,4 +2465,17 @@ public class ActionScript2Test extends ActionScript2TestBase {
+ "trace(\"functionPostIncrementTest\");\r\n"
);
}
@Test
public void frame90_bitwiseOperandsTest() {
compareSrc(90, "trace(\"bitwiseOperandsTest\");\r\n"
+ "var a = 100;\r\n"
+ "var b = a & 0x08FF;\r\n"
+ "var c = 0x08FF & a;\r\n"
+ "var d = a | 0x0480;\r\n"
+ "var e = 0x0480 | a;\r\n"
+ "var f = a ^ 0x0641;\r\n"
+ "var g = 0x0641 ^ a;\r\n"
);
}
}
@@ -180,8 +180,8 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT
+ "§§push(50);\r\n"
+ "while(§§dup(§§pop()))\r\n"
+ "{\r\n"
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 41 ^ 111;\r\n"
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 84;\r\n"
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 0x29 ^ 0x6F;\r\n"
+ "§§dup(§§pop())[§§dup(§§dup(§§pop())).length] = 9 ^ 0x54;\r\n"
+ "§§push(§§pop() - 1);\r\n"
+ "}\r\n"
+ "§§pop();\r\n"
@@ -51,6 +51,19 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile
false);
}
@Test
public void testBitwiseOperands() {
decompileMethod("classic_air", "testBitwiseOperands", "var a:int = 100;\r\n"
+ "var b:* = a & 0x08FF;\r\n"
+ "var c:* = 0x08FF & a;\r\n"
+ "var d:* = a | 0x0480;\r\n"
+ "var e:* = 0x0480 | a;\r\n"
+ "var f:* = a ^ 0x0641;\r\n"
+ "var g:* = 0x0641 ^ a;\r\n"
+ "var h:int = -385;\r\n",
false);
}
@Test
public void testCallCall() {
decompileMethod("classic_air", "testCallCall", "var o:* = new getDefinitionByName(\"Object\");\r\n"
@@ -51,6 +51,19 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes
false);
}
@Test
public void testBitwiseOperands() {
decompileMethod("classic", "testBitwiseOperands", "var a:int = 100;\r\n"
+ "var b:int = a & 0x08FF;\r\n"
+ "var c:int = 0x08FF & a;\r\n"
+ "var d:int = a | 0x0480;\r\n"
+ "var e:int = 0x0480 | a;\r\n"
+ "var f:int = a ^ 0x0641;\r\n"
+ "var g:int = 0x0641 ^ a;\r\n"
+ "var h:int = ~0x0180;\r\n",
false);
}
@Test
public void testCallCall() {
decompileMethod("classic", "testCallCall", "var o:* = new getDefinitionByName(\"Object\")();\r\n"
@@ -182,7 +195,7 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes
+ "trace(\"arr[call()] /= 5\");\r\n"
+ "b[this.calc()] = b[this.calc()] / 5;\r\n"
+ "trace(\"arr[call()][call()] &= 10;\");\r\n"
+ "b[this.calc()][this.calc()] = b[this.calc()][this.calc()] & 10;\r\n"
+ "b[this.calc()][this.calc()] = b[this.calc()][this.calc()] & 0x0A;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "trace(\"in try\");\r\n"
Binary file not shown.
+18 -4
View File
@@ -31,7 +31,7 @@
<Include href="Tween 5.xml" itemIcon="1" loadImmediate="false" itemID="60429674-00000289" lastModified="1614976628"/>
</symbols>
<timelines>
<DOMTimeline name="Scene 1" currentFrame="88">
<DOMTimeline name="Scene 1" currentFrame="89">
<layers>
<DOMLayer name="Layer 16" color="#FF4F4F">
<frames>
@@ -3377,6 +3377,20 @@ function myFunc()
</Actionscript>
<elements/>
</DOMFrame>
<DOMFrame index="89" keyMode="9728">
<Actionscript>
<script><![CDATA[trace("bitwiseOperandsTest");
var a = 100;
var b = a & 0x08ff;
var c = 0x08ff & a;
var d = a | 0x0480;
var e = 0x0480 | a;
var f = a ^ 0x0641;
var g = 0x0641 ^ a;]]></script>
</Actionscript>
<elements/>
</DOMFrame>
</frames>
</DOMLayer>
</layers>
@@ -3384,6 +3398,9 @@ function myFunc()
</timelines>
<PrinterSettings/>
<publishHistory>
<PublishItem publishSize="108786" publishTime="1722543124"/>
<PublishItem publishSize="108700" publishTime="1722540660"/>
<PublishItem publishSize="108705" publishTime="1722540289"/>
<PublishItem publishSize="108706" publishTime="1722540140"/>
<PublishItem publishSize="108698" publishTime="1722538202"/>
<PublishItem publishSize="108707" publishTime="1722538175"/>
@@ -3401,8 +3418,5 @@ function myFunc()
<PublishItem publishSize="108238" publishTime="1678904397"/>
<PublishItem publishSize="107972" publishTime="1667644454"/>
<PublishItem publishSize="108067" publishTime="1667642777"/>
<PublishItem publishSize="107872" publishTime="1638135730"/>
<PublishItem publishSize="107854" publishTime="1638131849"/>
<PublishItem publishSize="107768" publishTime="1638096020"/>
</publishHistory>
</DOMDocument>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -18,6 +18,7 @@ package
{
TestActivationArguments;
TestArguments;
TestBitwiseOperands;
TestCallCall;
TestCallLocal;
TestCatchFinally;
@@ -0,0 +1,18 @@
package tests
{
public class TestBitwiseOperands
{
public function run():*
{
var a:int = 100;
var b:int = a & 0x08ff;
var c:int = 0x08ff & a;
var d:int = a | 0x0480;
var e:int = 0x0480 | a;
var f:int = a ^ 0x0641;
var g:int = 0x0641 ^ a;
var h:int = ~0x0180;
}
}
}