diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/VerificationErrorType.java b/dexlib/src/main/java/org/jf/dexlib/Code/VerificationErrorType.java index 2670eaf5..622be5d3 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/VerificationErrorType.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/VerificationErrorType.java @@ -28,6 +28,8 @@ package org.jf.dexlib.Code; +import java.util.HashMap; + public enum VerificationErrorType { None(0, "no-error"), Generic(1, "generic-error"), @@ -40,6 +42,16 @@ public enum VerificationErrorType { ClassChange(8, "class-change-error"), Instantiation(9, "instantiation-error"); + private static HashMap verificationErrorTypesByName; + + static { + verificationErrorTypesByName = new HashMap(); + + for (VerificationErrorType verificationErrorType: VerificationErrorType.values()) { + verificationErrorTypesByName.put(verificationErrorType.getName(), verificationErrorType); + } + } + private int value; private String name; private VerificationErrorType(int value, String name) { @@ -55,6 +67,10 @@ public enum VerificationErrorType { return name; } + public static VerificationErrorType fromString(String validationErrorType) { + return verificationErrorTypesByName.get(validationErrorType); + } + public static VerificationErrorType getValidationErrorType(int validationErrorType) { switch (validationErrorType) { case 0: diff --git a/smali/src/main/antlr3/org/jf/smali/smaliParser.g b/smali/src/main/antlr3/org/jf/smali/smaliParser.g index 9181a9a7..354a4b54 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliParser.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliParser.g @@ -93,6 +93,7 @@ tokens { I_STATEMENT_FORMAT11n; I_STATEMENT_FORMAT11x; I_STATEMENT_FORMAT12x; + I_STATEMENT_FORMAT20bc; I_STATEMENT_FORMAT20t; I_STATEMENT_FORMAT21c_TYPE; I_STATEMENT_FORMAT21c_FIELD; @@ -137,11 +138,16 @@ import org.jf.dexlib.Code.Format.*; @members { private boolean verboseErrors = false; + private boolean allowOdex = false; public void setVerboseErrors(boolean verboseErrors) { this.verboseErrors = verboseErrors; } + public void setAllowOdex(boolean allowOdex) { + this.allowOdex = allowOdex; + } + public String getErrorMessage(RecognitionException e, String[] tokenNames) { @@ -594,6 +600,9 @@ register_list register_range : REGISTER (DOTDOT REGISTER)? -> ^(I_REGISTER_RANGE[$start, "I_REGISTER_RANGE"] REGISTER REGISTER?); +verification_error_reference + : CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method; + catch_directive : CATCH_DIRECTIVE nonvoid_type_descriptor OPEN_BRACE from=label_ref_or_offset DOTDOT to=label_ref_or_offset CLOSE_BRACE using=label_ref_or_offset -> ^(I_CATCH[$start, "I_CATCH"] I_ADDRESS[$start, Integer.toString($method::currentAddress)] nonvoid_type_descriptor $from $to $using); @@ -686,10 +695,13 @@ instruction returns [int size] instruction_format12x REGISTER COMMA REGISTER {$size = Format.Format12x.size;} -> ^(I_STATEMENT_FORMAT12x[$start, "I_STATEMENT_FORMAT12x"] instruction_format12x REGISTER REGISTER) | //e.g. throw-verification-error generic-error, Lsome/class; - INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA (CLASS_DESCRIPTOR | fully_qualified_field | fully_qualified_method) + INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;} { - throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); + if (!allowOdex) { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); + } } + -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference) | //e.g. goto/16 endloop: INSTRUCTION_FORMAT20t label_ref_or_offset {$size = Format.Format20t.size;} -> ^(I_STATEMENT_FORMAT20t[$start, "I_STATEMENT_FORMAT20t"] INSTRUCTION_FORMAT20t label_ref_or_offset) @@ -704,7 +716,7 @@ instruction returns [int size] | //e.g. const-string v1 "Hello World!" INSTRUCTION_FORMAT21c_STRING REGISTER COMMA STRING_LITERAL {$size = Format.Format21c.size;} -> ^(I_STATEMENT_FORMAT21c_STRING[$start, "I_STATEMENT_FORMAT21c_STRING"] INSTRUCTION_FORMAT21c_STRING REGISTER STRING_LITERAL) - | //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2 + | //e.g. const-class v2 Lorg/jf/HelloWorld2/HelloWorld2; INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;} -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) | //e.g. const/high16 v1, 1234 diff --git a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g index 94dbb3e4..ddd7995f 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g @@ -914,6 +914,26 @@ register_range[int totalMethodRegisters, int methodParameterRegisters] returns[i } ; +verification_error_reference returns[Item item] + : CLASS_DESCRIPTOR + { + $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + } + | fully_qualified_field + { + $item = $fully_qualified_field.fieldIdItem; + } + | fully_qualified_method + { + $item = $fully_qualified_method.methodIdItem; + }; + +verification_error_type returns[VerificationErrorType verificationErrorType] + : VERIFICATION_ERROR_TYPE + { + $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text); + }; + instruction[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] : //e.g. goto endloop: {$outRegisters = 0;} @@ -959,6 +979,16 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List.dump by default)") .hasOptionalArg() @@ -407,6 +416,7 @@ public class main { basicOptions.addOption(versionOption); basicOptions.addOption(helpOption); basicOptions.addOption(outputOption); + basicOptions.addOption(allowOdexOption); debugOptions.addOption(dumpOption); debugOptions.addOption(sortOption);