mirror of
https://github.com/revanced/smali.git
synced 2025-05-09 10:54:29 +02:00
Various tweaks to improve error handling
git-svn-id: https://smali.googlecode.com/svn/trunk@719 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
4c114f0918
commit
4d9801a89d
@ -511,7 +511,7 @@ fully_qualified_field
|
|||||||
-> reference_type_descriptor simple_name nonvoid_type_descriptor;
|
-> reference_type_descriptor simple_name nonvoid_type_descriptor;
|
||||||
|
|
||||||
label
|
label
|
||||||
: COLON simple_name -> ^(I_LABEL simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
: COLON simple_name -> ^(I_LABEL[$COLON, "I_LABEL"] simple_name I_ADDRESS[$start, Integer.toString($method::currentAddress)]);
|
||||||
|
|
||||||
label_ref_or_offset
|
label_ref_or_offset
|
||||||
: COLON simple_name -> simple_name
|
: COLON simple_name -> simple_name
|
||||||
@ -741,7 +741,8 @@ instruction returns [int size]
|
|||||||
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
-> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"])
|
||||||
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*))
|
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*))
|
||||||
|
|
||||||
-> ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*))
|
-> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal)
|
||||||
|
^(I_ARRAY_ELEMENTS fixed_literal*))
|
||||||
|
|
|
|
||||||
PACKED_SWITCH_DIRECTIVE
|
PACKED_SWITCH_DIRECTIVE
|
||||||
{
|
{
|
||||||
|
@ -502,21 +502,64 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
List<CodeItem.TryItem> tries = temp.first;
|
List<CodeItem.TryItem> tries = temp.first;
|
||||||
List<CodeItem.EncodedCatchHandler> handlers = temp.second;
|
List<CodeItem.EncodedCatchHandler> handlers = temp.second;
|
||||||
|
|
||||||
|
|
||||||
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
||||||
|
|
||||||
CodeItem codeItem;
|
CodeItem codeItem;
|
||||||
|
|
||||||
|
boolean isAbstract = false;
|
||||||
|
boolean isNative = false;
|
||||||
|
|
||||||
if (totalMethodRegisters == 0 &&
|
if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) {
|
||||||
$statements.instructions.size() == 0 &&
|
isAbstract = true;
|
||||||
$method::labels.size()== 0 &&
|
} else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) {
|
||||||
(tries == null || tries.size() == 0) &&
|
isNative = true;
|
||||||
(handlers == null || handlers.size() == 0) &&
|
}
|
||||||
debugInfoItem == null) {
|
|
||||||
|
|
||||||
codeItem = null;
|
if ($statements.instructions.size() == 0) {
|
||||||
|
if (!isAbstract && !isNative) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction");
|
||||||
|
}
|
||||||
|
|
||||||
|
String methodType;
|
||||||
|
if (isAbstract) {
|
||||||
|
methodType = "an abstract";
|
||||||
|
} else {
|
||||||
|
methodType = "a native";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($registers_directive.start != null) {
|
||||||
|
if ($registers_directive.isLocalsDirective) {
|
||||||
|
throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType);
|
||||||
|
} else {
|
||||||
|
throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($method::labels.size() > 0) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debugInfoItem != null) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeItem = null;
|
||||||
} else {
|
} else {
|
||||||
|
if (isAbstract) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions");
|
||||||
|
}
|
||||||
|
if (isNative) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($registers_directive.start == null) {
|
||||||
|
throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method");
|
||||||
|
}
|
||||||
|
|
||||||
if ($registers_directive.isLocalsDirective) {
|
if ($registers_directive.isLocalsDirective) {
|
||||||
totalMethodRegisters = $registers_directive.registers + methodParameterRegisters;
|
totalMethodRegisters = $registers_directive.registers + methodParameterRegisters;
|
||||||
} else {
|
} else {
|
||||||
@ -524,14 +567,14 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (totalMethodRegisters < methodParameterRegisters) {
|
if (totalMethodRegisters < methodParameterRegisters) {
|
||||||
throw new SemanticException(input, "This method requires at least " +
|
throw new SemanticException(input, $registers_directive.start, "This method requires at least " +
|
||||||
Integer.toString(methodParameterRegisters) +
|
Integer.toString(methodParameterRegisters) +
|
||||||
" registers, for the method parameters");
|
" registers, for the method parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount();
|
int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount();
|
||||||
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
||||||
throw new SemanticException(input, "Too many parameter names specified. This method only has " +
|
throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " +
|
||||||
Integer.toString(methodParameterCount) +
|
Integer.toString(methodParameterCount) +
|
||||||
" parameters.");
|
" parameters.");
|
||||||
}
|
}
|
||||||
@ -809,7 +852,7 @@ label_ref returns[int labelAddress]
|
|||||||
Integer labelAdd = $method::labels.get($SIMPLE_NAME.text);
|
Integer labelAdd = $method::labels.get($SIMPLE_NAME.text);
|
||||||
|
|
||||||
if (labelAdd == null) {
|
if (labelAdd == null) {
|
||||||
throw new SemanticException(input, "Label \"" + $SIMPLE_NAME.text + "\" is not defined.");
|
throw new SemanticException(input, $SIMPLE_NAME, "Label \"" + $SIMPLE_NAME.text + "\" is not defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$labelAddress = labelAdd;
|
$labelAddress = labelAdd;
|
||||||
@ -844,7 +887,7 @@ register_list[int totalMethodRegisters, int methodParameterRegisters] returns[by
|
|||||||
(REGISTER
|
(REGISTER
|
||||||
{
|
{
|
||||||
if ($registerCount == 5) {
|
if ($registerCount == 5) {
|
||||||
throw new SemanticException(input, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
|
throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
|
||||||
}
|
}
|
||||||
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
})*);
|
})*);
|
||||||
@ -858,6 +901,14 @@ register_range[int totalMethodRegisters, int methodParameterRegisters] returns[i
|
|||||||
} else {
|
} else {
|
||||||
$endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
$endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int registerCount = $endRegister-$startRegister+1;
|
||||||
|
if (registerCount > 256) {
|
||||||
|
throw new SemanticException(input, $I_REGISTER_RANGE, "A register range can span a maximum of 256 registers");
|
||||||
|
}
|
||||||
|
if (registerCount < 1) {
|
||||||
|
throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -974,7 +1025,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
int addressOffset = $offset_or_label.offsetValue;
|
int addressOffset = $offset_or_label.offsetValue;
|
||||||
|
|
||||||
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instructions.add(new Instruction21t(opcode, regA, (short)addressOffset));
|
$instructions.add(new Instruction21t(opcode, regA, (short)addressOffset));
|
||||||
@ -1034,7 +1085,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
int addressOffset = $offset_or_label.offsetValue;
|
int addressOffset = $offset_or_label.offsetValue;
|
||||||
|
|
||||||
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
if (addressOffset < Short.MIN_VALUE || addressOffset > Short.MAX_VALUE) {
|
||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
throw new SemanticException(input, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset));
|
$instructions.add(new Instruction22t(opcode, regA, regB, (short)addressOffset));
|
||||||
@ -1146,13 +1197,6 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
int endRegister = $register_range.endRegister;
|
int endRegister = $register_range.endRegister;
|
||||||
|
|
||||||
int registerCount = endRegister-startRegister+1;
|
int registerCount = endRegister-startRegister+1;
|
||||||
if (registerCount > 256) {
|
|
||||||
throw new SemanticException(input, "A register range can span a maximum of 256 registers");
|
|
||||||
}
|
|
||||||
if (registerCount < 1) {
|
|
||||||
throw new SemanticException(input, "A register range must have the lower register listed first");
|
|
||||||
}
|
|
||||||
|
|
||||||
$outRegisters = registerCount;
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
||||||
@ -1167,13 +1211,6 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc
|
|||||||
int endRegister = $register_range.endRegister;
|
int endRegister = $register_range.endRegister;
|
||||||
|
|
||||||
int registerCount = endRegister-startRegister+1;
|
int registerCount = endRegister-startRegister+1;
|
||||||
if (registerCount > 256) {
|
|
||||||
throw new SemanticException(input, "A register range can span a maximum of 256 registers");
|
|
||||||
}
|
|
||||||
if (registerCount < 1) {
|
|
||||||
throw new SemanticException(input, "A register range must have the lower register listed first");
|
|
||||||
}
|
|
||||||
|
|
||||||
$outRegisters = registerCount;
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||||
|
@ -30,14 +30,15 @@ package org.jf.smali;
|
|||||||
|
|
||||||
import org.antlr.runtime.IntStream;
|
import org.antlr.runtime.IntStream;
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
|
import org.antlr.runtime.tree.CommonTree;
|
||||||
|
|
||||||
public class SemanticException extends RecognitionException {
|
public class SemanticException extends RecognitionException {
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
|
|
||||||
|
|
||||||
SemanticException(IntStream input, String errorMessage) {
|
SemanticException(IntStream input, String errorMessage, Object... messageArguments) {
|
||||||
super(input);
|
super(input);
|
||||||
this.errorMessage = errorMessage;
|
this.errorMessage = String.format(errorMessage, messageArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
SemanticException(IntStream input, Exception ex) {
|
SemanticException(IntStream input, Exception ex) {
|
||||||
@ -45,6 +46,16 @@ public class SemanticException extends RecognitionException {
|
|||||||
this.errorMessage = ex.getMessage();
|
this.errorMessage = ex.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SemanticException(IntStream input, CommonTree tree, String errorMessage, Object... messageArguments) {
|
||||||
|
super();
|
||||||
|
this.input = input;
|
||||||
|
this.token = tree.getToken();
|
||||||
|
this.index = tree.getTokenStartIndex();
|
||||||
|
this.line = token.getLine();
|
||||||
|
this.charPositionInLine = token.getCharPositionInLine();
|
||||||
|
this.errorMessage = String.format(errorMessage, messageArguments);
|
||||||
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user