Implemented verification for filled-new-array/range

git-svn-id: https://smali.googlecode.com/svn/trunk@576 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2010-01-24 03:40:43 +00:00
parent 9e5dd85d83
commit ac8785e5d5

View File

@ -460,6 +460,8 @@ public class MethodAnalyzer {
return handleNewArray(analyzedInstruction); return handleNewArray(analyzedInstruction);
case FILLED_NEW_ARRAY: case FILLED_NEW_ARRAY:
return handleFilledNewArray(analyzedInstruction); return handleFilledNewArray(analyzedInstruction);
case FILLED_NEW_ARRAY_RANGE:
return handleFilledNewArrayRange(analyzedInstruction);
} }
assert false; assert false;
return false; return false;
@ -948,11 +950,17 @@ public class MethodAnalyzer {
return true; return true;
} }
private boolean handleFilledNewArray(AnalyzedInstruction analyzedInstruction) { private static interface RegisterIterator {
int getRegister();
boolean moveNext();
}
private boolean handleFilledNewArrayCommon(AnalyzedInstruction analyzedInstruction,
RegisterIterator registerIterator) {
InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
RegisterType arrayType; RegisterType arrayType;
RegisterType arrayImmediateElementType; RegisterType arrayImmediateElementType;
{
InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
Item item = instruction.getReferencedItem(); Item item = instruction.getReferencedItem();
assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
@ -973,16 +981,9 @@ public class MethodAnalyzer {
throw new ValidationException("Cannot use filled-new-array to create an array of wide values " + throw new ValidationException("Cannot use filled-new-array to create an array of wide values " +
"(long or double)"); "(long or double)");
} }
}
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction; do {
int registerCount = instruction.getRegCount(); int register = registerIterator.getRegister();
byte[] registers = new byte[]{instruction.getRegisterD(), instruction.getRegisterE(), instruction.getRegisterF(),
instruction.getRegisterG(), instruction.getRegisterA()};
for (int i=0; i<registerCount; i++) {
int register = registers[i];
RegisterType elementType = analyzedInstruction.getPreInstructionRegisterType(register); RegisterType elementType = analyzedInstruction.getPreInstructionRegisterType(register);
assert elementType != null; assert elementType != null;
@ -995,12 +996,68 @@ public class MethodAnalyzer {
elementType.toString() + " and is incompatible with the array type " + elementType.toString() + " and is incompatible with the array type " +
arrayType.type.getClassType()); arrayType.type.getClassType());
} }
} } while (registerIterator.moveNext());
setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType);
return true; return true;
} }
private boolean handleFilledNewArray(AnalyzedInstruction analyzedInstruction) {
FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction;
final int registerCount = instruction.getRegCount();
final int[] registers = new int[]{instruction.getRegisterD(), instruction.getRegisterE(),
instruction.getRegisterF(), instruction.getRegisterG(),
instruction.getRegisterA()};
return handleFilledNewArrayCommon(analyzedInstruction,
new RegisterIterator() {
private int currentRegister = 0;
public int getRegister() {
return registers[currentRegister];
}
public boolean moveNext() {
currentRegister++;
if (currentRegister >= registerCount) {
return false;
}
return true;
}
});
}
private boolean handleFilledNewArrayRange(AnalyzedInstruction analyzedInstruction) {
final RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction;
//instruction.getStartRegister() and instruction.getRegCount() both return an int value, but are actually
//unsigned 16 bit values, so we don't have to worry about overflowing an int when adding them together
if (instruction.getStartRegister() + instruction.getRegCount() >= 1<<16) {
throw new ValidationException(String.format("Invalid register range {v%d .. v%d}. The ending register " +
" is larger than the largest allowed register of v65535.",
instruction.getStartRegister(),
instruction.getStartRegister() + instruction.getRegCount() - 1));
}
return handleFilledNewArrayCommon(analyzedInstruction,
new RegisterIterator() {
private int currentRegister = 0;
private final int startRegister = instruction.getStartRegister();
private final int registerCount = instruction.getRegCount();
public int getRegister() {
return startRegister + currentRegister;
}
public boolean moveNext() {
currentRegister++;
if (currentRegister >= registerCount) {
return false;
}
return true;
}
});
}
private static void checkRegister(RegisterType registerType, EnumSet validCategories) { private static void checkRegister(RegisterType registerType, EnumSet validCategories) {
if (!validCategories.contains(registerType.category)) { if (!validCategories.contains(registerType.category)) {
//TODO: add expected categories to error message //TODO: add expected categories to error message