mirror of
https://github.com/revanced/smali.git
synced 2025-05-05 09:04:25 +02:00
Implemented verification for fill-array-data
git-svn-id: https://smali.googlecode.com/svn/trunk@577 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
ac8785e5d5
commit
472d3ea584
@ -2,6 +2,8 @@ package org.jf.dexlib.Code.Analysis;
|
|||||||
|
|
||||||
import org.jf.dexlib.*;
|
import org.jf.dexlib.*;
|
||||||
import org.jf.dexlib.Code.*;
|
import org.jf.dexlib.Code.*;
|
||||||
|
import org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction;
|
||||||
|
import org.jf.dexlib.Code.Format.Format;
|
||||||
import org.jf.dexlib.Util.*;
|
import org.jf.dexlib.Util.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -462,6 +464,8 @@ public class MethodAnalyzer {
|
|||||||
return handleFilledNewArray(analyzedInstruction);
|
return handleFilledNewArray(analyzedInstruction);
|
||||||
case FILLED_NEW_ARRAY_RANGE:
|
case FILLED_NEW_ARRAY_RANGE:
|
||||||
return handleFilledNewArrayRange(analyzedInstruction);
|
return handleFilledNewArrayRange(analyzedInstruction);
|
||||||
|
case FILL_ARRAY_DATA:
|
||||||
|
return handleFillArrayData(analyzedInstruction);
|
||||||
}
|
}
|
||||||
assert false;
|
assert false;
|
||||||
return false;
|
return false;
|
||||||
@ -1058,6 +1062,75 @@ public class MethodAnalyzer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean handleFillArrayData(AnalyzedInstruction analyzedInstruction) {
|
||||||
|
SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
|
||||||
|
|
||||||
|
int register = instruction.getRegisterA();
|
||||||
|
RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register);
|
||||||
|
assert registerType != null;
|
||||||
|
|
||||||
|
if (registerType.category == RegisterType.Category.Unknown ||
|
||||||
|
registerType.category == RegisterType.Category.Null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registerType.category != RegisterType.Category.Reference) {
|
||||||
|
throw new ValidationException(String.format("Cannot use fill-array-data with non-array register v%d of " +
|
||||||
|
"type %s", register, registerType.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert registerType.type instanceof ClassPath.ArrayClassDef;
|
||||||
|
ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)registerType.type;
|
||||||
|
|
||||||
|
if (arrayClassDef.getArrayDimensions() != 1) {
|
||||||
|
throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can only " +
|
||||||
|
"be used with a one-dimensional array of primitives.", arrayClassDef.getClassType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int elementWidth;
|
||||||
|
switch (arrayClassDef.getBaseElementClass().getClassType().charAt(0)) {
|
||||||
|
case 'Z':
|
||||||
|
case 'B':
|
||||||
|
elementWidth = 1;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
case 'S':
|
||||||
|
elementWidth = 2;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
case 'F':
|
||||||
|
elementWidth = 4;
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
case 'D':
|
||||||
|
elementWidth = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can " +
|
||||||
|
"only be used with a one-dimensional array of primitives.", arrayClassDef.getClassType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int arrayDataOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset();
|
||||||
|
AnalyzedInstruction arrayDataInstruction = this.instructions.get(arrayDataOffset);
|
||||||
|
if (arrayDataInstruction == null || arrayDataInstruction.instruction.getFormat() != Format.ArrayData) {
|
||||||
|
throw new ValidationException(String.format("Could not find an array data structure at code address 0x%x",
|
||||||
|
arrayDataOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDataPseudoInstruction arrayDataPseudoInstruction =
|
||||||
|
(ArrayDataPseudoInstruction)arrayDataInstruction.instruction;
|
||||||
|
|
||||||
|
if (elementWidth != arrayDataPseudoInstruction.getElementWidth()) {
|
||||||
|
throw new ValidationException(String.format("The array data at code address 0x%x does not have the " +
|
||||||
|
"correct element width for array type %s. Expecting element width %d, got element width %d.",
|
||||||
|
arrayDataOffset, arrayClassDef.getClassType(), elementWidth,
|
||||||
|
arrayDataPseudoInstruction.getElementWidth()));
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user