From 3f70d08442fadd8f2af225f86ca2a41334182dec Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Mon, 14 May 2012 22:03:11 -0700 Subject: [PATCH] Gracefully handle duplicate methods and fields in baksmali baksmali will emit duplicate methods and fields as commented blocks, when it is safe to do so. --- .../jf/baksmali/Adaptors/ClassDefinition.java | 53 ++++++++++++++----- .../main/java/org/jf/dexlib/FieldIdItem.java | 19 +++++++ .../jf/util/CommentingIndentingWriter.java | 48 +++++++++++++++++ .../java/org/jf/util/IndentingWriter.java | 24 ++++++--- 4 files changed, 123 insertions(+), 21 deletions(-) create mode 100644 util/src/main/java/org/jf/util/CommentingIndentingWriter.java diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java index 17c3c6e6..3849cd30 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java @@ -29,6 +29,7 @@ package org.jf.baksmali.Adaptors; import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.CommentingIndentingWriter; import org.jf.util.IndentingWriter; import org.jf.dexlib.*; import org.jf.dexlib.Code.Analysis.ValidationException; @@ -208,12 +209,10 @@ public class ClassDefinition { writer.write("\n\n"); writer.write("# static fields\n"); - boolean first = true; for (int i=0; i 0) { writer.write('\n'); } - first = false; ClassDataItem.EncodedField field = encodedFields.get(i); EncodedValue encodedValue = null; @@ -226,10 +225,19 @@ public class ClassDefinition { fieldAnnotations = annotations.getFieldAnnotations(field.field); } + IndentingWriter fieldWriter = writer; + // the encoded fields are sorted, so we just have to compare with the previous one to detect duplicates + if (i > 0 && field.equals(encodedFields.get(i-1))) { + fieldWriter = new CommentingIndentingWriter(writer, "#"); + fieldWriter.write("Ignoring field with duplicate signature\n"); + System.err.println(String.format("Warning: class %s has duplicate static field %s, Ignoring.", + classDefItem.getClassType().getTypeDescriptor(), field.field.getShortFieldString())); + } + boolean setInStaticConstructor = fieldsSetInStaticConstructor.get(field.field.getIndex()) != null; - FieldDefinition.writeTo(writer, field, encodedValue, fieldAnnotations, setInStaticConstructor); + FieldDefinition.writeTo(fieldWriter, field, encodedValue, fieldAnnotations, setInStaticConstructor); } } @@ -245,12 +253,12 @@ public class ClassDefinition { writer.write("\n\n"); writer.write("# instance fields\n"); - boolean first = true; - for (ClassDataItem.EncodedField field: encodedFields) { - if (!first) { + for (int i=0; i 0) { writer.write('\n'); } - first = false; AnnotationSetItem fieldAnnotations = null; AnnotationDirectoryItem annotations = classDefItem.getAnnotations(); @@ -258,7 +266,16 @@ public class ClassDefinition { fieldAnnotations = annotations.getFieldAnnotations(field.field); } - FieldDefinition.writeTo(writer, field, null, fieldAnnotations, false); + IndentingWriter fieldWriter = writer; + // the encoded fields are sorted, so we just have to compare with the previous one to detect duplicates + if (i > 0 && field.equals(encodedFields.get(i-1))) { + fieldWriter = new CommentingIndentingWriter(writer, "#"); + fieldWriter.write("Ignoring field with duplicate signature\n"); + System.err.println(String.format("Warning: class %s has duplicate instance field %s, Ignoring.", + classDefItem.getClassType().getTypeDescriptor(), field.field.getShortFieldString())); + } + + FieldDefinition.writeTo(fieldWriter, field, null, fieldAnnotations, false); } } @@ -294,12 +311,11 @@ public class ClassDefinition { } private void writeMethods(IndentingWriter writer, List methods) throws IOException { - boolean first = true; - for (ClassDataItem.EncodedMethod method: methods) { - if (!first) { + for (int i=0; i 0) { writer.write('\n'); } - first = false; AnnotationSetItem methodAnnotations = null; AnnotationSetRefList parameterAnnotations = null; @@ -309,8 +325,17 @@ public class ClassDefinition { parameterAnnotations = annotations.getParameterAnnotations(method.method); } + IndentingWriter methodWriter = writer; + // the encoded methods are sorted, so we just have to compare with the previous one to detect duplicates + if (i > 0 && method.equals(methods.get(i-1))) { + methodWriter = new CommentingIndentingWriter(writer, "#"); + methodWriter.write("Ignoring method with duplicate signature\n"); + System.err.println(String.format("Warning: class %s has duplicate method %s, Ignoring.", + classDefItem.getClassType().getTypeDescriptor(), method.method.getShortMethodString())); + } + MethodDefinition methodDefinition = new MethodDefinition(method); - methodDefinition.writeTo(writer, methodAnnotations, parameterAnnotations); + methodDefinition.writeTo(methodWriter, methodAnnotations, parameterAnnotations); ValidationException validationException = methodDefinition.getValidationException(); if (validationException != null) { diff --git a/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java b/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java index 6af0ccdc..c9fe05f0 100644 --- a/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java +++ b/dexlib/src/main/java/org/jf/dexlib/FieldIdItem.java @@ -201,6 +201,25 @@ public class FieldIdItem extends Item implements Convertible