Check for duplicate field/method definitions in ClassDataItem

This commit is contained in:
Ben Gruver 2012-06-19 12:04:58 -07:00
parent 0d2ce20ee4
commit 9c7c421f51

View File

@ -33,9 +33,7 @@ import org.jf.dexlib.Util.*;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.List;
public class ClassDataItem extends Item<ClassDataItem> { public class ClassDataItem extends Item<ClassDataItem> {
@Nullable @Nullable
@ -95,27 +93,71 @@ public class ClassDataItem extends Item<ClassDataItem> {
EncodedMethod[] virtualMethodsArray = null; EncodedMethod[] virtualMethodsArray = null;
if (staticFields != null && staticFields.size() > 0) { if (staticFields != null && staticFields.size() > 0) {
staticFieldsArray = new EncodedField[staticFields.size()]; SortedSet<EncodedField> staticFieldsSet = new TreeSet<EncodedField>();
staticFieldsArray = staticFields.toArray(staticFieldsArray); for (EncodedField staticField: staticFields) {
Arrays.sort(staticFieldsArray); if (staticFieldsSet.contains(staticField)) {
System.err.println(String.format("Ignoring duplicate static field definition: %s",
staticField.field.getFieldString()));
continue;
}
staticFieldsSet.add(staticField);
}
staticFieldsArray = new EncodedField[staticFieldsSet.size()];
staticFieldsArray = staticFieldsSet.toArray(staticFieldsArray);
} }
if (instanceFields != null && instanceFields.size() > 0) { if (instanceFields != null && instanceFields.size() > 0) {
instanceFieldsArray = new EncodedField[instanceFields.size()]; SortedSet<EncodedField> instanceFieldsSet = new TreeSet<EncodedField>();
instanceFieldsArray = instanceFields.toArray(instanceFieldsArray); for (EncodedField instanceField: instanceFields) {
Arrays.sort(instanceFieldsArray); if (instanceFieldsSet.contains(instanceField)) {
System.err.println(String.format("Ignoring duplicate instance field definition: %s",
instanceField.field.getFieldString()));
continue;
}
instanceFieldsSet.add(instanceField);
}
instanceFieldsArray = new EncodedField[instanceFieldsSet.size()];
instanceFieldsArray = instanceFieldsSet.toArray(instanceFieldsArray);
} }
TreeSet<EncodedMethod> directMethodSet = new TreeSet<EncodedMethod>();
if (directMethods != null && directMethods.size() > 0) { if (directMethods != null && directMethods.size() > 0) {
directMethodsArray = new EncodedMethod[directMethods.size()]; for (EncodedMethod directMethod: directMethods) {
directMethodsArray = directMethods.toArray(directMethodsArray); if (directMethodSet.contains(directMethod)) {
Arrays.sort(directMethodsArray); System.err.println(String.format("Ignoring duplicate direct method definition: %s",
directMethod.method.getMethodString()));
continue;
}
directMethodSet.add(directMethod);
}
directMethodsArray = new EncodedMethod[directMethodSet.size()];
directMethodsArray = directMethodSet.toArray(directMethodsArray);
} }
if (virtualMethods != null && virtualMethods.size() > 0) { if (virtualMethods != null && virtualMethods.size() > 0) {
virtualMethodsArray = new EncodedMethod[virtualMethods.size()]; TreeSet<EncodedMethod> virtualMethodSet = new TreeSet<EncodedMethod>();
virtualMethodsArray = virtualMethods.toArray(virtualMethodsArray); for (EncodedMethod virtualMethod: virtualMethods) {
Arrays.sort(virtualMethodsArray); if (directMethodSet.contains(virtualMethod)) {
// If both a direct and virtual definition is present, dalvik's behavior seems to be undefined,
// so we can't gracefully handle this case, like we can if the duplicates are all direct or all
// virtual -- in which case, we ignore all but the first definition
throw new RuntimeException(String.format("Duplicate direct+virtual method definition: %s",
virtualMethod.method.getMethodString()));
}
if (virtualMethodSet.contains(virtualMethod)) {
System.err.println(String.format("Ignoring duplicate virtual method definition: %s",
virtualMethod.method.getMethodString()));
continue;
}
virtualMethodSet.add(virtualMethod);
}
virtualMethodsArray = new EncodedMethod[virtualMethodSet.size()];
virtualMethodsArray = virtualMethodSet.toArray(virtualMethodsArray);
} }
ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray, ClassDataItem classDataItem = new ClassDataItem(dexFile, staticFieldsArray, instanceFieldsArray,
@ -596,6 +638,19 @@ public class ClassDataItem extends Item<ClassDataItem> {
return field.compareTo(other.field); return field.compareTo(other.field);
} }
/**
* Determines if this <code>EncodedField</code> is equal to other, based on the equality of the associated
* <code>FieldIdItem</code>
* @param other The <code>EncodedField</code> to test for equality
* @return true if other is equal to this instance, otherwise false
*/
public boolean equals(Object other) {
if (other instanceof EncodedField) {
return compareTo((EncodedField)other) == 0;
}
return false;
}
/** /**
* @return true if this is a static field * @return true if this is a static field
*/ */
@ -717,6 +772,19 @@ public class ClassDataItem extends Item<ClassDataItem> {
return method.compareTo(other.method); return method.compareTo(other.method);
} }
/**
* Determines if this <code>EncodedMethod</code> is equal to other, based on the equality of the associated
* <code>MethodIdItem</code>
* @param other The <code>EncodedMethod</code> to test for equality
* @return true if other is equal to this instance, otherwise false
*/
public boolean equals(Object other) {
if (other instanceof EncodedMethod) {
return compareTo((EncodedMethod)other) == 0;
}
return false;
}
/** /**
* @return true if this is a direct method * @return true if this is a direct method
*/ */