Issue #1279 show duplicate trait names with hash suffix

Fixed editing const/slot
Namespace testdata
This commit is contained in:
Jindra Petřík
2016-09-17 00:07:50 +02:00
parent 3304e69d8a
commit a5ab81747e
33 changed files with 4289 additions and 4108 deletions
@@ -692,19 +692,9 @@ public class ABC {
SWFDecompilerPlugin.fireMethodBodyParsed(this, mb, swf);
}
markSameContextMultinames();
getMethodIndexing();
/*for(int i=0;i<script_count;i++){
MethodBody bod=bodies.get(bodyIdxFromMethodIdx.get(script_info.get(i).init_index));
GraphTextWriter t=new HighlightedTextWriter(Configuration.getCodeFormatting(),false);
try {
bod.toString("script", ScriptExportMode.PCODE, this, null, constants, method_info, t, new ArrayList<>());
} catch (InterruptedException ex) {
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(""+t.toString());
}
//System.exit(0);*/
SWFDecompilerPlugin.fireAbcParsed(this, swf);
}
@@ -1119,6 +1109,60 @@ public class ABC {
return ret;
}
public void markSameContextMultinames() {
//Reset
for (int multinameIndex = 1; multinameIndex < constants.getMultinameCount(); multinameIndex++) {
constants.getMultiname(multinameIndex).setDisplayNamespace(false);
}
//group qnames with same name
Map<String, List<Integer>> nameToQNameIndices = new HashMap<>();
for (int multinameIndex = 1; multinameIndex < constants.getMultinameCount(); multinameIndex++) {
Multiname m = constants.getMultiname(multinameIndex);
if (m.kind == Multiname.QNAME || m.kind == Multiname.QNAMEA) {
String name = m.getName(constants, new ArrayList<>(), true);
if (!nameToQNameIndices.containsKey(name)) {
nameToQNameIndices.put(name, new ArrayList<>());
}
nameToQNameIndices.get(name).add(multinameIndex);
}
}
Set<MultinameUsage> collidingUsages = new HashSet<>();
//find context of names with count 2 or more
for (String name : nameToQNameIndices.keySet()) {
List<Integer> multinameIndices = nameToQNameIndices.get(name);
if (multinameIndices.size() > 1) {
List<List<MultinameUsage>> allUsages = new ArrayList<>();
for (int multinameIndex : multinameIndices) {
List<MultinameUsage> usages = findMultinameUsage(multinameIndex);
for (MultinameUsage usage : usages) {
for (List<MultinameUsage> prevUsages : allUsages) {
for (MultinameUsage prevUsage : prevUsages) {
if (prevUsage.collides(usage)) {
collidingUsages.add(usage);
collidingUsages.add(prevUsage);
}
}
}
}
allUsages.add(usages);
}
}
}
Set<Integer> collidingMultinameIndices = new HashSet<>();
for (MultinameUsage col : collidingUsages) {
collidingMultinameIndices.add(col.multinameIndex);
}
for (int multinameIndex : collidingMultinameIndices) {
constants.getMultiname(multinameIndex).setDisplayNamespace(true);
}
}
public List<MultinameUsage> findMultinameUsage(int multinameIndex) {
List<MultinameUsage> ret = new ArrayList<>();
if (multinameIndex == 0) {
@@ -34,8 +34,10 @@ import com.jpexs.helpers.HashArrayList;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -1129,6 +1129,7 @@ public class ASM3Parser {
info.optional[i] = optional.get(i);
}
}
abc.markSameContextMultinames();
return code;
}
}
File diff suppressed because it is too large Load Diff
@@ -35,5 +35,6 @@ public enum SymbolGroup {
//GLOBALFUNC,
GLOBALCONST,
PREPROCESSOR,
REGEXP
REGEXP,
NAMESPACESUFFIX
}
@@ -207,7 +207,8 @@ public enum SymbolType {
DESCENDANTS(GraphTargetItem.PRECEDENCE_PRIMARY, false),
NATIVE,
PREPROCESSOR(GraphTargetItem.PRECEDENCE_PRIMARY, false),
REGEXP(GraphTargetItem.PRECEDENCE_PRIMARY, false);
REGEXP(GraphTargetItem.PRECEDENCE_PRIMARY, false),
NAMESPACESUFFIX;
private int precedence = GraphTargetItem.NOPRECEDENCE;
@@ -73,6 +73,13 @@ public class Multiname {
@Internal
public boolean deleted;
@Internal
private boolean displayNamespace = false;
public void setDisplayNamespace(boolean displayNamespace) {
this.displayNamespace = displayNamespace;
}
private boolean validType() {
boolean cnt = false;
for (int i = 0; i < multinameKinds.length; i++) {
@@ -335,11 +342,15 @@ public class Multiname {
return isAttribute() ? "@*" : "*";
} else {
String name = constants.getString(name_index);
String nssuffix = "";
if (displayNamespace) {
nssuffix += "#" + namespace_index;
}
if (fullyQualifiedNames != null && fullyQualifiedNames.contains(DottedChain.parse(name))) {
DottedChain dc = getNameWithNamespace(constants);
return raw ? dc.toRawString() : dc.toPrintableString(true);
}
return (isAttribute() ? "@" : "") + (raw ? name : IdentifiersDeobfuscation.printIdentifier(true, name));
return (isAttribute() ? "@" : "") + (raw ? name : IdentifiersDeobfuscation.printIdentifier(true, name) + nssuffix);
}
}
@@ -22,14 +22,31 @@ import com.jpexs.decompiler.flash.abc.ABC;
*
* @author JPEXS
*/
public class ClassNameMultinameUsage extends InsideClassMultinameUsage implements DefinitionUsage {
public class ClassNameMultinameUsage extends MultinameUsage implements DefinitionUsage, InsideClassMultinameUsageInterface {
private int classIndex;
public ClassNameMultinameUsage(ABC abc, int multinameIndex, int classIndex) {
super(abc, multinameIndex, classIndex);
super(abc, multinameIndex);
this.classIndex = classIndex;
}
@Override
public int getClassIndex() {
return classIndex;
}
@Override
public String toString() {
return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(true);
}
@Override
public boolean collides(MultinameUsage other) {
if (other instanceof ClassNameMultinameUsage) {
return sameMultinameName(other);
}
return false;
}
}
@@ -68,7 +68,7 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage {
} catch (InterruptedException ex) {
// ignore
}
return writer.toString();
return writer.toString().trim();
}
public int getTraitIndex() {
@@ -33,4 +33,18 @@ public class ConstVarNameMultinameUsage extends ConstVarMultinameUsage implement
public String toString() {
return super.toString() + " name";
}
@Override
public boolean collides(MultinameUsage other) {
if ((other instanceof ConstVarNameMultinameUsage) || (other instanceof MethodNameMultinameUsage)) {
TraitMultinameUsage otherTrait = (TraitMultinameUsage) other;
if (otherTrait.classIndex == classIndex && otherTrait.traitsType == traitsType) {
if (other.sameMultinameName(this)) {
return true;
}
}
}
return false;
}
}
@@ -33,4 +33,10 @@ public class ConstVarTypeMultinameUsage extends ConstVarMultinameUsage {
public String toString() {
return super.toString() + " type";
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
}
@@ -22,14 +22,28 @@ import com.jpexs.decompiler.flash.abc.ABC;
*
* @author JPEXS
*/
public class ExtendsMultinameUsage extends InsideClassMultinameUsage {
public class ExtendsMultinameUsage extends MultinameUsage implements InsideClassMultinameUsageInterface {
private int classIndex;
public ExtendsMultinameUsage(ABC abc, int multinameIndex, int classIndex) {
super(abc, multinameIndex, classIndex);
super(abc, multinameIndex);
this.classIndex = classIndex;
}
@Override
public int getClassIndex() {
return classIndex;
}
@Override
public String toString() {
return super.toString() + " extends";
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
}
@@ -22,14 +22,28 @@ import com.jpexs.decompiler.flash.abc.ABC;
*
* @author JPEXS
*/
public class ImplementsMultinameUsage extends InsideClassMultinameUsage {
public class ImplementsMultinameUsage extends MultinameUsage implements InsideClassMultinameUsageInterface {
private int classIndex;
public ImplementsMultinameUsage(ABC abc, int multinameIndex, int classIndex) {
super(abc, multinameIndex, classIndex);
super(abc, multinameIndex);
this.classIndex = classIndex;
}
@Override
public int getClassIndex() {
return classIndex;
}
@Override
public String toString() {
return super.toString() + " implements";
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
}
@@ -22,21 +22,9 @@ import com.jpexs.decompiler.flash.abc.ABC;
*
* @author JPEXS
*/
public abstract class InsideClassMultinameUsage extends MultinameUsage {
public interface InsideClassMultinameUsageInterface {
public int classIndex;
public int getClassIndex();
public InsideClassMultinameUsage(ABC abc, int multinameIndex, int classIndex) {
super(abc, multinameIndex);
this.classIndex = classIndex;
}
@Override
public String toString() {
return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(true);
}
public int getClassIndex() {
return classIndex;
}
public ABC getAbc();
}
@@ -33,4 +33,10 @@ public class MethodBodyMultinameUsage extends MethodMultinameUsage {
public String toString() {
return super.toString() + " body";
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
}
@@ -86,7 +86,7 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage {
}
((TraitMethodGetterSetter) traits.traits.get(traitIndex)).toStringHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false);
}
return writer.toString();
return writer.toString().trim();
}
public int getTraitIndex() {
@@ -33,4 +33,17 @@ public class MethodNameMultinameUsage extends MethodMultinameUsage implements De
public String toString() {
return super.toString() + " name";
}
@Override
public boolean collides(MultinameUsage other) {
if ((other instanceof MethodNameMultinameUsage) || (other instanceof ConstVarNameMultinameUsage)) {
TraitMultinameUsage otherTrait = (TraitMultinameUsage) other;
if (otherTrait.classIndex == classIndex && otherTrait.traitsType == traitsType) {
if (other.sameMultinameName(this)) {
return true;
}
}
}
return false;
}
}
@@ -17,6 +17,10 @@
package com.jpexs.decompiler.flash.abc.usages;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import java.util.ArrayList;
import java.util.Objects;
/**
*
@@ -40,4 +44,47 @@ public abstract class MultinameUsage {
return abc;
}
protected boolean sameMultinameName(MultinameUsage other) {
Multiname thisM = abc.constants.getMultiname(multinameIndex);
Multiname otherM = other.abc.constants.getMultiname(other.multinameIndex);
if (thisM == null && otherM == null) {
return false;
}
if (thisM == null || otherM == null) {
return false;
}
if ((thisM.kind == Multiname.QNAME || thisM.kind == Multiname.QNAMEA) && otherM.kind == thisM.kind) {
String thisName = thisM.getName(abc.constants, new ArrayList<>(), true);
String otherName = otherM.getName(other.abc.constants, new ArrayList<>(), true);
Namespace thisNs = thisM.getNamespace(abc.constants);
Namespace otherNs = otherM.getNamespace(other.abc.constants);
if (!Objects.equals(thisName, otherName)) {
System.err.println("not equal name: " + thisName + ", " + otherName);
return false;
}
//Both are custom namespaced
if (thisNs.kind == Namespace.KIND_NAMESPACE && otherNs.kind == Namespace.KIND_NAMESPACE) {
//compare those custom
return Objects.equals(thisNs.getName(abc.constants), otherNs.getName(other.abc.constants));
}
//One is custom namespaced, other cannot be the same
if (thisNs.kind == Namespace.KIND_NAMESPACE || otherNs.kind == Namespace.KIND_NAMESPACE) {
return false;
}
//public or package internal are colliding when have same package ns
if ((thisNs.kind == Namespace.KIND_PACKAGE || thisNs.kind == Namespace.KIND_PACKAGE_INTERNAL)
&& (otherNs.kind == Namespace.KIND_PACKAGE || otherNs.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
return Objects.equals(thisNs.getName(abc.constants), otherNs.getName(other.abc.constants));
}
//one of them is private/protected
return true;
}
return false;
}
public abstract boolean collides(MultinameUsage other);
}
@@ -23,7 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Traits;
*
* @author JPEXS
*/
public abstract class TraitMultinameUsage extends MultinameUsage {
public abstract class TraitMultinameUsage extends MultinameUsage implements InsideClassMultinameUsageInterface {
public int traitIndex;
@@ -53,4 +53,15 @@ public abstract class TraitMultinameUsage extends MultinameUsage {
public String toString() {
return "class " + abc.constants.getMultiname(abc.instance_info.get(classIndex).name_index).getNameWithNamespace(abc.constants).toPrintableString(true);
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
@Override
public int getClassIndex() {
return classIndex;
}
}
@@ -36,4 +36,9 @@ public class TypeNameMultinameUsage extends MultinameUsage {
public String toString() {
return "TypeName " + abc.constants.getMultiname(typename_index).toString(abc.constants, new ArrayList<>());
}
@Override
public boolean collides(MultinameUsage other) {
return false;
}
}