mirror of
https://github.com/revanced/smali.git
synced 2025-06-13 04:27:38 +02:00
Implemented verification for aput/aput-boolean/aput-byte/aput-char/aput-short
git-svn-id: https://smali.googlecode.com/svn/trunk@590 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
@ -514,6 +514,16 @@ public class MethodAnalyzer {
|
|||||||
return handleAgetWide(analyzedInstruction);
|
return handleAgetWide(analyzedInstruction);
|
||||||
case AGET_OBJECT:
|
case AGET_OBJECT:
|
||||||
return handleAgetObject(analyzedInstruction);
|
return handleAgetObject(analyzedInstruction);
|
||||||
|
case APUT:
|
||||||
|
return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Integer);
|
||||||
|
case APUT_BOOLEAN:
|
||||||
|
return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Boolean);
|
||||||
|
case APUT_BYTE:
|
||||||
|
return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Byte);
|
||||||
|
case APUT_CHAR:
|
||||||
|
return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Char);
|
||||||
|
case APUT_SHORT:
|
||||||
|
return handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Short);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert false;
|
assert false;
|
||||||
@ -1519,6 +1529,68 @@ public class MethodAnalyzer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean handle32BitPrimitiveAput(AnalyzedInstruction analyzedInstruction,
|
||||||
|
RegisterType.Category instructionCategory) {
|
||||||
|
ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
|
||||||
|
|
||||||
|
RegisterType indexRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterC());
|
||||||
|
assert indexRegisterType != null;
|
||||||
|
if (indexRegisterType.category == RegisterType.Category.Unknown) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
checkRegister(indexRegisterType, Primitive32BitCategories);
|
||||||
|
|
||||||
|
|
||||||
|
RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
|
||||||
|
assert sourceRegisterType != null;
|
||||||
|
if (sourceRegisterType.category == RegisterType.Category.Unknown) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null);
|
||||||
|
if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) {
|
||||||
|
throw new ValidationException(String.format("Cannot use %s with source register type %s.",
|
||||||
|
analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
|
||||||
|
assert arrayRegisterType != null;
|
||||||
|
if (indexRegisterType.category == RegisterType.Category.Unknown) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrayRegisterType.category != RegisterType.Category.Null) {
|
||||||
|
if (arrayRegisterType.category != RegisterType.Category.Reference) {
|
||||||
|
throw new ValidationException(String.format("Cannot use %s with non-array type %s",
|
||||||
|
analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert arrayRegisterType.type != null;
|
||||||
|
if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
|
||||||
|
throw new ValidationException(String.format("Cannot use %s with non-array type %s",
|
||||||
|
analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
|
||||||
|
ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
|
||||||
|
|
||||||
|
if (arrayClassDef.getArrayDimensions() != 1) {
|
||||||
|
throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s",
|
||||||
|
analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterType arrayBaseType =
|
||||||
|
RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType());
|
||||||
|
if (checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) {
|
||||||
|
throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " +
|
||||||
|
"for the instruction.", analyzedInstruction.instruction.opcode.name,
|
||||||
|
arrayRegisterType.type.getClassType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory,
|
private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory,
|
||||||
RegisterType.Category instructionCategory) {
|
RegisterType.Category instructionCategory) {
|
||||||
if (arrayFieldCategory == instructionCategory) {
|
if (arrayFieldCategory == instructionCategory) {
|
||||||
|
Reference in New Issue
Block a user