mirror of
https://github.com/revanced/smali.git
synced 2025-06-12 12:17:37 +02:00
Implemented verification for the literal binary operation instructions
git-svn-id: https://smali.googlecode.com/svn/trunk@619 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
@ -860,6 +860,45 @@ public class MethodAnalyzer {
|
||||
handleBinary2AddrOp(analyzedInstruction, WideLowCategories, WideLowCategories,
|
||||
RegisterType.Category.DoubleLo, false);
|
||||
return;
|
||||
case ADD_INT_LIT16:
|
||||
case RSUB_INT:
|
||||
case MUL_INT_LIT16:
|
||||
case DIV_INT_LIT16:
|
||||
case REM_INT_LIT16:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
|
||||
false);
|
||||
return;
|
||||
case AND_INT_LIT16:
|
||||
case OR_INT_LIT16:
|
||||
case XOR_INT_LIT16:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
|
||||
true);
|
||||
return;
|
||||
case ADD_INT_LIT8:
|
||||
case RSUB_INT_LIT8:
|
||||
case MUL_INT_LIT8:
|
||||
case DIV_INT_LIT8:
|
||||
case REM_INT_LIT8:
|
||||
case SHL_INT_LIT8:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
|
||||
false);
|
||||
return;
|
||||
case AND_INT_LIT8:
|
||||
case OR_INT_LIT8:
|
||||
case XOR_INT_LIT8:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
|
||||
true);
|
||||
return;
|
||||
case SHR_INT_LIT8:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories,
|
||||
getDestTypeForLiteralShiftRight(analyzedInstruction, true), false);
|
||||
return;
|
||||
case USHR_INT_LIT8:
|
||||
handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories,
|
||||
getDestTypeForLiteralShiftRight(analyzedInstruction, false), false);
|
||||
return;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2384,6 +2423,99 @@ public class MethodAnalyzer {
|
||||
RegisterType.getRegisterType(destRegisterCategory, null));
|
||||
}
|
||||
|
||||
private void handleLiteralBinaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSourceCategories,
|
||||
RegisterType.Category destRegisterCategory, boolean checkForBoolean) {
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
|
||||
|
||||
RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
|
||||
validSourceCategories);
|
||||
|
||||
if (checkForBoolean) {
|
||||
if (BooleanCategories.contains(sourceRegisterType.category)) {
|
||||
long literal = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral();
|
||||
if (literal == 0 || literal == 1) {
|
||||
destRegisterCategory = RegisterType.Category.Boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
|
||||
RegisterType.getRegisterType(destRegisterCategory, null));
|
||||
}
|
||||
|
||||
private RegisterType.Category getDestTypeForLiteralShiftRight(AnalyzedInstruction analyzedInstruction,
|
||||
boolean signedShift) {
|
||||
TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
|
||||
|
||||
RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
|
||||
Primitive32BitCategories);
|
||||
long literalShift = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral();
|
||||
|
||||
if (literalShift == 0) {
|
||||
return sourceRegisterType.category;
|
||||
}
|
||||
|
||||
RegisterType.Category destRegisterCategory;
|
||||
if (!signedShift) {
|
||||
destRegisterCategory = RegisterType.Category.Integer;
|
||||
} else {
|
||||
destRegisterCategory = sourceRegisterType.category;
|
||||
}
|
||||
|
||||
if (literalShift >= 32) {
|
||||
//TODO: add warning
|
||||
return destRegisterCategory;
|
||||
}
|
||||
|
||||
switch (sourceRegisterType.category) {
|
||||
case Integer:
|
||||
case Float:
|
||||
if (!signedShift) {
|
||||
if (literalShift > 24) {
|
||||
return RegisterType.Category.PosByte;
|
||||
}
|
||||
if (literalShift >= 16) {
|
||||
return RegisterType.Category.Char;
|
||||
}
|
||||
} else {
|
||||
if (literalShift >= 24) {
|
||||
return RegisterType.Category.Byte;
|
||||
}
|
||||
if (literalShift >= 16) {
|
||||
return RegisterType.Category.Short;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Short:
|
||||
if (signedShift && literalShift >= 8) {
|
||||
return RegisterType.Category.Byte;
|
||||
}
|
||||
break;
|
||||
case PosShort:
|
||||
if (literalShift >= 8) {
|
||||
return RegisterType.Category.PosByte;
|
||||
}
|
||||
break;
|
||||
case Char:
|
||||
if (literalShift > 8) {
|
||||
return RegisterType.Category.PosByte;
|
||||
}
|
||||
break;
|
||||
case Byte:
|
||||
break;
|
||||
case PosByte:
|
||||
return RegisterType.Category.PosByte;
|
||||
case Null:
|
||||
case One:
|
||||
case Boolean:
|
||||
return RegisterType.Category.Null;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
return destRegisterCategory;
|
||||
}
|
||||
|
||||
private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory,
|
||||
RegisterType.Category instructionCategory) {
|
||||
if (arrayFieldCategory == instructionCategory) {
|
||||
|
Reference in New Issue
Block a user