Merge origin/master

This commit is contained in:
Jindra Petřík
2015-05-04 10:49:42 +02:00
28 changed files with 728 additions and 1039 deletions

View File

@@ -659,6 +659,7 @@ public final class SWF implements SWFContainerItem, Timelined {
if (hasEndTag) {
sos.writeUI16(0);
}
sos.close();
os.write(Utf8Helper.getBytes(getHeaderBytes(compression, gfx)));
os.write(version);
@@ -711,6 +712,7 @@ public final class SWF implements SWFContainerItem, Timelined {
} else if (compression == SWFCompression.ZLIB) {
os = new DeflaterOutputStream(os);
}
os.write(data);
} finally {
if (os != null) {
@@ -2028,11 +2030,13 @@ public final class SWF implements SWFContainerItem, Timelined {
ret++;
}
}
for (ASMSource src : actionsMap.keySet()) {
actionsMap.get(src).removeNops();
src.setActions(actionsMap.get(src));
src.setModified();
}
deobfuscation.deobfuscateInstanceNames(false, deobfuscated, renameType, tags, selected);
return ret;
}

View File

@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.special.ActionEnd;
import com.jpexs.decompiler.flash.action.special.ActionNop;
import com.jpexs.decompiler.flash.action.swf3.ActionGetURL;
@@ -1565,11 +1564,10 @@ public class SWFInputStream implements AutoCloseable {
/**
* Reads one Action from the stream
*
* @param cpool
* @return Action or null when ActionEndFlag or end of the stream
* @throws IOException
*/
public Action readAction(ConstantPool cpool) throws IOException {
public Action readAction() throws IOException {
int actionCode = -1;
try {
@@ -1603,7 +1601,7 @@ public class SWFInputStream implements AutoCloseable {
case 0x09:
return new ActionStopSounds();
case 0x8A:
return new ActionWaitForFrame(actionLength, this, cpool);
return new ActionWaitForFrame(actionLength, this);
case 0x8B:
return new ActionSetTarget(actionLength, this, swf.version);
case 0x8C:
@@ -1684,7 +1682,7 @@ public class SWFInputStream implements AutoCloseable {
case 0x28:
return new ActionEndDrag();
case 0x8D:
return new ActionWaitForFrame2(actionLength, this, cpool);
return new ActionWaitForFrame2(actionLength, this);
case 0x26:
return new ActionTrace();
case 0x34:

View File

@@ -153,11 +153,15 @@ public class SWFOutputStream extends OutputStream {
/**
* Writes UI8 (Unsigned 8bit integer) value to the stream
*
* @param val UI8 value to write
* @param value UI8 value to write
* @throws IOException
*/
public void writeUI8(int val) throws IOException {
write(val);
public void writeUI8(int value) throws IOException {
if (value > 0xff) {
throw new Error("Value is too large for UI8: " + value);
}
write(value);
}
/**
@@ -167,7 +171,14 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeString(String value) throws IOException {
write(Utf8Helper.getBytes(value));
byte[] data = Utf8Helper.getBytes(value);
for (int i = 0; i < data.length; i++) {
if (data[i] == 0) {
throw new IOException("String should not contain null character.");
}
}
write(data);
write(0);
}
@@ -178,6 +189,10 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeUI32(long value) throws IOException {
if (value > 0xffffffffL) {
throw new Error("Value is too large for UI32: " + value);
}
write((int) (value & 0xff));
write((int) ((value >> 8) & 0xff));
write((int) ((value >> 16) & 0xff));
@@ -191,6 +206,10 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeUI16(int value) throws IOException {
if (value > 0xffff) {
throw new Error("Value is too large for UI16: " + value);
}
write((int) (value & 0xff));
write((int) ((value >> 8) & 0xff));
}
@@ -202,6 +221,10 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeSI32(long value) throws IOException {
if (value > 0x7fffffffL) {
throw new Error("Value is too large for SI32: " + value);
}
writeUI32(value);
}
@@ -212,6 +235,10 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeSI16(int value) throws IOException {
if (value > 0x7fff) {
throw new Error("Value is too large for SI16: " + value);
}
writeUI16(value);
}
@@ -222,6 +249,10 @@ public class SWFOutputStream extends OutputStream {
* @throws IOException
*/
public void writeSI8(int value) throws IOException {
if (value > 0x7ff) {
throw new Error("Value is too large for SI8: " + value);
}
writeUI8(value);
}

View File

@@ -1,16 +1,16 @@
/*
* Copyright (C) 2010-2015 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.
*/
@@ -131,13 +131,11 @@ public class ActionListReader {
* @throws java.lang.InterruptedException
*/
public static ActionList readActionList(List<DisassemblyListener> listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException {
ConstantPool cpool = new ConstantPool();
// Map of the actions. Use TreeMap to sort the keys in ascending order
// actionMap and nextOffsets should contain exaclty the same keys
Map<Long, Action> actionMap = new TreeMap<>();
Map<Long, Long> nextOffsets = new HashMap<>();
Action entryAction = readActionListAtPos(listeners, cpool,
Action entryAction = readActionListAtPos(listeners, null,
sis, actionMap, nextOffsets,
ip, 0, endIp, path, false, new ArrayList<Long>());
@@ -238,12 +236,10 @@ public class ActionListReader {
}
public static List<Action> getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException {
ConstantPool cpool = new ConstantPool();
// Map of the actions. Use TreeMap to sort the keys in ascending order
Map<Long, Action> actionMap = new TreeMap<>();
Map<Long, Long> nextOffsets = new HashMap<>();
readActionListAtPos(new ArrayList<DisassemblyListener>(), cpool,
readActionListAtPos(new ArrayList<DisassemblyListener>(), null,
sis, actionMap, nextOffsets,
startIp, startIp, endIp + 1, "", false, new ArrayList<Long>());
@@ -690,7 +686,7 @@ public class ActionListReader {
sis.seek((int) ip);
Action a;
if ((a = sis.readAction(cpool)) == null) {
if ((a = sis.readAction()) == null) {
break;
}
@@ -729,10 +725,7 @@ public class ActionListReader {
if (a instanceof ActionPush && cpool != null) {
((ActionPush) a).constantPool = cpool.constants;
} else if (a instanceof ActionConstantPool) {
if (cpool == null) {
cpool = new ConstantPool();
}
cpool.setNew(((ActionConstantPool) a).constantPool);
cpool = new ConstantPool(((ActionConstantPool) a).constantPool);
} else if (a instanceof ActionIf) {
ActionIf aIf = (ActionIf) a;
long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset();

View File

@@ -1,18 +1,19 @@
/*
* Copyright (C) 2010-2015 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.
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.parser.pcode;
import com.jpexs.decompiler.flash.action.Action;
@@ -128,14 +129,16 @@ import com.jpexs.helpers.Helper;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ASMParser {
public static ActionList parse(boolean ignoreNops, List<Label> labels, Map<Action, Integer> lineMap, long address, FlasmLexer lexer, List<String> constantPool, int version) throws IOException, ActionParseException {
ActionList list = new ActionList();
Stack<GraphSourceItemContainer> containers = new Stack<>();
@@ -192,6 +195,7 @@ public class ASMParser {
}
if (a != null) {
list.add(a);
lineMap.put(a, lexer.yyline());
}
} else if (symb.type == ASMParsedSymbol.TYPE_EOL) {
} else if ((symb.type == ASMParsedSymbol.TYPE_BLOCK_END) || (symb.type == ASMParsedSymbol.TYPE_EOF)) {
@@ -464,7 +468,8 @@ public class ASMParser {
lexer = new FlasmLexer(new StringReader(source));
List<Label> labels = new ArrayList<>();
List<Label> labels = new ArrayList<>();
Map<Action, Integer> lineMap = new HashMap<>();
ActionList ret = parse(ignoreNops, labels, lineMap, address, lexer, constantPool, version);
//Action.setActionsAddresses(ret, address, version);
for (Action link : ret) {
if (!(link instanceof ActionIf || link instanceof ActionJump)) {
@@ -480,7 +485,22 @@ public class ASMParser {
ActionJump actionJump = (ActionJump) link;
if (actionJump.identifier.equals(label.name)) {
if (actionJump.identifier.equals(label.name)) {
int offset = (int) (label.address - (actionJump.getAddress() + actionJump.getTotalActionLength()));
if (offset < -0x8000 || offset > 0x7fff) {
String message = "Jump offset is too large:" + offset + " addr: ofs" + Helper.formatAddress(link.getAddress());
if (throwOnError) {
Integer line = lineMap.get(link);
if (line == null) {
line = -1;
}
throw new ActionParseException(message, line);
} else {
Logger.getLogger(ASMParser.class.getName()).log(Level.SEVERE, message);
}
}
actionJump.setJumpOffset(offset);
found = true;
break;
}
@@ -491,7 +511,22 @@ public class ASMParser {
for (Label label : labels) {
if (actionIf.identifier.equals(label.name)) {
if (actionIf.identifier.equals(label.name)) {
int offset = (int) (label.address - (actionIf.getAddress() + actionIf.getTotalActionLength()));
if (offset < -0x8000 || offset > 0x7fff) {
String message = "If offset is too large:" + offset + " addr: ofs" + Helper.formatAddress(link.getAddress());
if (throwOnError) {
Integer line = lineMap.get(link);
if (line == null) {
line = -1;
}
throw new ActionParseException(message, line);
} else {
Logger.getLogger(ASMParser.class.getName()).log(Level.SEVERE, message);
}
}
actionIf.setJumpOffset(offset);
found = true;
break;
}
@@ -499,13 +534,20 @@ public class ASMParser {
}
if (!found) {
String message = "TARGET NOT FOUND - identifier:" + identifier + " addr: ofs" + Helper.formatAddress(link.getAddress());
if (throwOnError) {
if (throwOnError) {
Integer line = lineMap.get(link);
if (line == null) {
line = -1;
}
throw new ActionParseException(message, line);
} else {
} else {
Logger.getLogger(ASMParser.class.getName()).log(Level.SEVERE, message);
}
}
}
return ret;
}
}

View File

@@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraph;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.IfFrameLoadedActionItem;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
@@ -46,7 +45,7 @@ public class ActionWaitForFrame extends Action implements ActionStore {
public List<Action> skipped;
public ActionWaitForFrame(int actionLength, SWFInputStream sis, ConstantPool cpool) throws IOException {
public ActionWaitForFrame(int actionLength, SWFInputStream sis) throws IOException {
super(0x8A, actionLength);
frame = sis.readUI16("frame");
skipCount = sis.readUI8("skipCount");

View File

@@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraph;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.clauses.IfFrameLoadedActionItem;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
@@ -60,7 +59,7 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
skipCount = store.size();
}
public ActionWaitForFrame2(int actionLength, SWFInputStream sis, ConstantPool cpool) throws IOException {
public ActionWaitForFrame2(int actionLength, SWFInputStream sis) throws IOException {
super(0x8D, actionLength);
skipCount = sis.readUI8("skipCount");
skipped = new ArrayList<>();

View File

@@ -46,6 +46,7 @@ public class ConstantIndex implements Serializable {
}
}
}
return "constant" + index;
}
@@ -58,6 +59,7 @@ public class ConstantIndex implements Serializable {
}
}
}
return "constant" + index;
}
}

View File

@@ -196,6 +196,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {

View File

@@ -282,6 +282,14 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
super.setModified(value);
}
@Override
public void createOriginalData() {
super.createOriginalData();
for (Tag subTag : subTags) {
subTag.createOriginalData();
}
}
public static void clearCache() {
rectCache.clear();
}

View File

@@ -131,6 +131,7 @@ public class DoActionTag extends Tag implements ASMSource {
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {

View File

@@ -138,6 +138,7 @@ public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {

View File

@@ -205,6 +205,7 @@ public class BUTTONCONDACTION implements ASMSource, Serializable {
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, swf.version, prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;

View File

@@ -199,6 +199,7 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable {
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, swf.version, prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {