mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-17 14:18:33 +00:00
avm2 instruction is not serializable anymore, AS2 swf in AS3 binarydata fix
This commit is contained in:
@@ -12,14 +12,17 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public class EndOfStreamException extends IOException {
|
||||
|
||||
public EndOfStreamException() {
|
||||
super("Premature end of the stream reached");
|
||||
|
||||
@@ -983,7 +983,7 @@ public class SWFInputStream implements AutoCloseable {
|
||||
dumpInfo.name = t.getName();
|
||||
}
|
||||
return t;
|
||||
} catch (EndOfStreamException ex) {
|
||||
} catch (Exception ex) {
|
||||
tag.getDataStream().endDumpLevelUntil(di);
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
return tag;
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc;
|
||||
|
||||
import com.jpexs.decompiler.flash.EndOfStreamException;
|
||||
import com.jpexs.decompiler.flash.abc.types.Decimal;
|
||||
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
@@ -103,6 +105,9 @@ public class ABCInputStream implements AutoCloseable {
|
||||
private int readInternal() throws IOException {
|
||||
bytesRead++;
|
||||
int i = is.read();
|
||||
if (i == -1) {
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
if (DEBUG_READ) {
|
||||
System.out.println("Read:0x" + Integer.toHexString(i));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2;
|
||||
|
||||
import com.jpexs.decompiler.flash.EndOfStreamException;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.ABCInputStream;
|
||||
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
@@ -234,10 +235,7 @@ import com.jpexs.helpers.Helper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -248,9 +246,8 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class AVM2Code implements Serializable {
|
||||
public class AVM2Code implements Cloneable {
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(AVM2Code.class.getName());
|
||||
private static final boolean DEBUG_MODE = false;
|
||||
public static int toSourceLimit = -1;
|
||||
@@ -787,54 +784,58 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
|
||||
public AVM2Code(ABCInputStream ais) throws IOException {
|
||||
while (ais.available() > 0) {
|
||||
DumpInfo di = ais.newDumpLevel("instruction", "instruction");
|
||||
long startOffset = ais.getPosition();
|
||||
int instructionCode = ais.read("instructionCode");
|
||||
InstructionDefinition instr = instructionSetByCode[instructionCode];
|
||||
if (di != null) {
|
||||
di.name = instr.instructionName;
|
||||
}
|
||||
if (instr != null) {
|
||||
int[] actualOperands = null;
|
||||
if (instructionCode == 0x1b) { //switch
|
||||
int firstOperand = ais.readS24("firstOperand");
|
||||
int case_count = ais.readU30("case_count");
|
||||
actualOperands = new int[case_count + 3];
|
||||
actualOperands[0] = firstOperand;
|
||||
actualOperands[1] = case_count;
|
||||
for (int c = 0; c < case_count + 1; c++) {
|
||||
actualOperands[2 + c] = ais.readS24("actualOperand");
|
||||
}
|
||||
} else {
|
||||
if (instr.operands.length > 0) {
|
||||
actualOperands = new int[instr.operands.length];
|
||||
for (int op = 0; op < instr.operands.length; op++) {
|
||||
switch (instr.operands[op] & 0xff00) {
|
||||
case OPT_U30:
|
||||
actualOperands[op] = ais.readU30("operand");
|
||||
break;
|
||||
case OPT_U8:
|
||||
actualOperands[op] = ais.read("operand");
|
||||
break;
|
||||
case OPT_BYTE:
|
||||
actualOperands[op] = (byte) ais.read("operand");
|
||||
break;
|
||||
case OPT_S24:
|
||||
actualOperands[op] = ais.readS24("operand");
|
||||
break;
|
||||
try {
|
||||
while (ais.available() > 0) {
|
||||
DumpInfo di = ais.newDumpLevel("instruction", "instruction");
|
||||
long startOffset = ais.getPosition();
|
||||
int instructionCode = ais.read("instructionCode");
|
||||
InstructionDefinition instr = instructionSetByCode[instructionCode];
|
||||
if (di != null) {
|
||||
di.name = instr.instructionName;
|
||||
}
|
||||
if (instr != null) {
|
||||
int[] actualOperands = null;
|
||||
if (instructionCode == 0x1b) { //switch
|
||||
int firstOperand = ais.readS24("default_offset");
|
||||
int case_count = ais.readU30("case_count");
|
||||
actualOperands = new int[case_count + 3];
|
||||
actualOperands[0] = firstOperand;
|
||||
actualOperands[1] = case_count;
|
||||
for (int c = 0; c < case_count + 1; c++) {
|
||||
actualOperands[2 + c] = ais.readS24("actualOperand");
|
||||
}
|
||||
} else {
|
||||
if (instr.operands.length > 0) {
|
||||
actualOperands = new int[instr.operands.length];
|
||||
for (int op = 0; op < instr.operands.length; op++) {
|
||||
switch (instr.operands[op] & 0xff00) {
|
||||
case OPT_U30:
|
||||
actualOperands[op] = ais.readU30("operand");
|
||||
break;
|
||||
case OPT_U8:
|
||||
actualOperands[op] = ais.read("operand");
|
||||
break;
|
||||
case OPT_BYTE:
|
||||
actualOperands[op] = (byte) ais.read("operand");
|
||||
break;
|
||||
case OPT_S24:
|
||||
actualOperands[op] = ais.readS24("operand");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code.add(new AVM2Instruction(startOffset, instr, actualOperands));
|
||||
ais.endDumpLevel(instr.instructionCode);
|
||||
} else {
|
||||
ais.endDumpLevel();
|
||||
break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions)
|
||||
//throw new UnknownInstructionCode(instructionCode);
|
||||
code.add(new AVM2Instruction(startOffset, instr, actualOperands));
|
||||
ais.endDumpLevel(instr.instructionCode);
|
||||
} else {
|
||||
ais.endDumpLevel();
|
||||
break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions)
|
||||
//throw new UnknownInstructionCode(instructionCode);
|
||||
}
|
||||
}
|
||||
} catch (EndOfStreamException ex) {
|
||||
// lookupswitch obfuscation, ignore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2433,24 +2434,6 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public AVM2Code deepCopy() {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
|
||||
oos.writeObject(this);
|
||||
oos.flush();
|
||||
}
|
||||
AVM2Code copy;
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
|
||||
copy = (AVM2Code) ois.readObject();
|
||||
}
|
||||
return copy;
|
||||
} catch (IOException | ClassNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Error during deepCopy", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Decision {
|
||||
|
||||
public boolean jumpUsed = false;
|
||||
@@ -2890,4 +2873,18 @@ public class AVM2Code implements Serializable {
|
||||
AVM2Graph.translateViaGraph(localData, "", code, new ArrayList<Integer>(), Graph.SOP_REMOVE_STATIC);
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
AVM2Code ret = (AVM2Code) super.clone();
|
||||
if (code != null) {
|
||||
List<AVM2Instruction> codeCopy = new ArrayList<>(code.size());
|
||||
for (AVM2Instruction ins : code) {
|
||||
codeCopy.add((AVM2Instruction) ins.clone());
|
||||
}
|
||||
ret.code = codeCopy;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,13 +35,12 @@ import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AVM2Instruction implements Serializable, GraphSourceItem {
|
||||
public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
public InstructionDefinition definition;
|
||||
public int[] operands;
|
||||
public long offset;
|
||||
@@ -360,4 +359,13 @@ public class AVM2Instruction implements Serializable, GraphSourceItem {
|
||||
public boolean isDeobfuscatePop() {
|
||||
return definition instanceof DeobfuscatePopIns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
AVM2Instruction ret = (AVM2Instruction) super.clone();
|
||||
if (operands != null) {
|
||||
ret.operands = Arrays.copyOf(operands, operands.length);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
@@ -100,7 +101,7 @@ public abstract class AssignableAVM2Item extends AVM2Item {
|
||||
ret.add(ins(new KillIns(), register.getVal()));
|
||||
return ret;
|
||||
}*/
|
||||
}*/
|
||||
|
||||
public static List<GraphSourceItem> killTemp(SourceGeneratorLocalData localData, SourceGenerator generator, List<Reference<Integer>> registers) {
|
||||
List<GraphSourceItem> ret = new ArrayList<>();
|
||||
for (Reference<Integer> register : registers) {
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -46,7 +45,7 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MethodBody implements Cloneable, Serializable {
|
||||
public class MethodBody implements Cloneable {
|
||||
|
||||
public boolean deleted;
|
||||
boolean debugMode = false;
|
||||
@@ -221,7 +220,7 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
}
|
||||
|
||||
public MethodBody convertMethodBody(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, AVM2ConstantPool constants, List<MethodInfo> method_info, ScopeStack scopeStack, boolean isStaticInitializer, List<String> fullyQualifiedNames, Traits initTraits) throws InterruptedException {
|
||||
MethodBody b = Helper.deepCopy(this);
|
||||
MethodBody b = (MethodBody) clone();
|
||||
AVM2Code deobfuscated = b.getCode();
|
||||
deobfuscated.markMappedOffsets();
|
||||
if (Configuration.autoDeobfuscate.get()) {
|
||||
@@ -237,18 +236,25 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
MethodBody ret = new MethodBody();
|
||||
ret.code = code;
|
||||
ret.codeBytes = codeBytes;
|
||||
ret.exceptions = exceptions;
|
||||
ret.max_regs = max_regs;
|
||||
ret.max_scope_depth = max_scope_depth;
|
||||
ret.max_stack = max_stack;
|
||||
ret.method_info = method_info;
|
||||
ret.init_scope_depth = init_scope_depth;
|
||||
ret.traits = traits; //maybe deep clone
|
||||
return ret;
|
||||
public Object clone() {
|
||||
try {
|
||||
MethodBody ret = (MethodBody) super.clone();
|
||||
if (code != null) {
|
||||
ret.code = (AVM2Code) code.clone();
|
||||
}
|
||||
ret.codeBytes = codeBytes;
|
||||
ret.exceptions = exceptions;
|
||||
ret.max_regs = max_regs;
|
||||
ret.max_scope_depth = max_scope_depth;
|
||||
ret.max_stack = max_stack;
|
||||
ret.method_info = method_info;
|
||||
ret.init_scope_depth = init_scope_depth;
|
||||
ret.traits = traits; //maybe deep clone
|
||||
return ret;
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean autoFillStats(ABC abc, int initScope, boolean hasThis) {
|
||||
|
||||
Reference in New Issue
Block a user