
soot.dexpler.DalvikThrowAnalysis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
//
// (c) 2012 University of Luxembourg - Interdisciplinary Centre for
// Security Reliability and Trust (SnT) - All rights reserved
//
// Author: Alexandre Bartel
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
//
package soot.dexpler;
import soot.FastHierarchy;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 2018 Raja Vallée-Rai and others
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import soot.G;
import soot.NullType;
import soot.PrimType;
import soot.RefLikeType;
import soot.Scene;
import soot.Singletons;
import soot.Type;
import soot.UnknownType;
import soot.baf.EnterMonitorInst;
import soot.baf.ReturnInst;
import soot.baf.ReturnVoidInst;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.ClassConstant;
import soot.jimple.EnterMonitorStmt;
import soot.jimple.StringConstant;
import soot.toolkits.exceptions.ThrowableSet;
import soot.toolkits.exceptions.UnitThrowAnalysis;
/**
*
* @author alex
*
*
* According to
* https://android.googlesource.com/platform/dalvik/+/2988c4f272f62af2e96f1e6161d4e99bc1dc1b16/opcode-gen/bytecode.txt
* the following Dalvik bytecode instructions might throw an exception:
*
* op 1a const-string 21c y string-ref continue|throw op 1b const-string/jumbo 31c y string-ref continue|throw op 1c
* const-class 21c y type-ref continue|throw op 1d monitor-enter 11x n none continue|throw op 1e monitor-exit 11x n
* none continue|throw op 1f check-cast 21c y type-ref continue|throw op 20 instance-of 22c y type-ref continue|throw
* op 21 array-length 12x y none continue|throw op 22 new-instance 21c y type-ref continue|throw op 23 new-array 22c
* y type-ref continue|throw op 24 filled-new-array 35c n type-ref continue|throw op 25 filled-new-array/range 3rc n
* type-ref continue|throw
*
* op 27 throw 11x n none throw
*
* op 44 aget 23x y none continue|throw op 45 aget-wide 23x y none continue|throw op 46 aget-object 23x y none
* continue|throw op 47 aget-boolean 23x y none continue|throw op 48 aget-byte 23x y none continue|throw op 49
* aget-char 23x y none continue|throw op 4a aget-short 23x y none continue|throw op 4b aput 23x n none
* continue|throw op 4c aput-wide 23x n none continue|throw op 4d aput-object 23x n none continue|throw op 4e
* aput-boolean 23x n none continue|throw op 4f aput-byte 23x n none continue|throw op 50 aput-char 23x n none
* continue|throw op 51 aput-short 23x n none continue|throw op 52 iget 22c y field-ref continue|throw op 53
* iget-wide 22c y field-ref continue|throw op 54 iget-object 22c y field-ref continue|throw op 55 iget-boolean 22c y
* field-ref continue|throw op 56 iget-byte 22c y field-ref continue|throw op 57 iget-char 22c y field-ref
* continue|throw op 58 iget-short 22c y field-ref continue|throw op 59 iput 22c n field-ref continue|throw op 5a
* iput-wide 22c n field-ref continue|throw op 5b iput-object 22c n field-ref continue|throw op 5c iput-boolean 22c n
* field-ref continue|throw op 5d iput-byte 22c n field-ref continue|throw op 5e iput-char 22c n field-ref
* continue|throw op 5f iput-short 22c n field-ref continue|throw op 60 sget 21c y field-ref continue|throw op 61
* sget-wide 21c y field-ref continue|throw op 62 sget-object 21c y field-ref continue|throw op 63 sget-boolean 21c y
* field-ref continue|throw op 64 sget-byte 21c y field-ref continue|throw op 65 sget-char 21c y field-ref
* continue|throw op 66 sget-short 21c y field-ref continue|throw op 67 sput 21c n field-ref continue|throw op 68
* sput-wide 21c n field-ref continue|throw op 69 sput-object 21c n field-ref continue|throw op 6a sput-boolean 21c n
* field-ref continue|throw op 6b sput-byte 21c n field-ref continue|throw op 6c sput-char 21c n field-ref
* continue|throw op 6d sput-short 21c n field-ref continue|throw op 6e invoke-virtual 35c n method-ref
* continue|throw|invoke op 6f invoke-super 35c n method-ref continue|throw|invoke op 70 invoke-direct 35c n
* method-ref continue|throw|invoke op 71 invoke-static 35c n method-ref continue|throw|invoke op 72 invoke-interface
* 35c n method-ref continue|throw|invoke # unused: op 73 op 74 invoke-virtual/range 3rc n method-ref
* continue|throw|invoke op 75 invoke-super/range 3rc n method-ref continue|throw|invoke op 76 invoke-direct/range
* 3rc n method-ref continue|throw|invoke op 77 invoke-static/range 3rc n method-ref continue|throw|invoke op 78
* invoke-interface/range 3rc n method-ref continue|throw|invoke
*
* op 93 div-int 23x y none continue|throw op 94 rem-int 23x y none continue|throw
*
* op 9e div-long 23x y none continue|throw op 9f rem-long 23x y none continue|throw
*
* op b3 div-int/2addr 12x y none continue|throw op b4 rem-int/2addr 12x y none continue|throw
*
* op be div-long/2addr 12x y none continue|throw op bf rem-long/2addr 12x y none continue|throw
*
* op d3 div-int/lit16 22s y none continue|throw op d4 rem-int/lit16 22s y none continue|throw
*
* op db div-int/lit8 22b y none continue|throw op dc rem-int/lit8 22b y none continue|throw
*
* op e3 +iget-volatile 22c y field-ref optimized|continue|throw op e4 +iput-volatile 22c n field-ref
* optimized|continue|throw op e5 +sget-volatile 21c y field-ref optimized|continue|throw op e6 +sput-volatile 21c n
* field-ref optimized|continue|throw op e7 +iget-object-volatile 22c y field-ref optimized|continue|throw op e8
* +iget-wide-volatile 22c y field-ref optimized|continue|throw op e9 +iput-wide-volatile 22c n field-ref
* optimized|continue|throw op ea +sget-wide-volatile 21c y field-ref optimized|continue|throw op eb
* +sput-wide-volatile 21c n field-ref optimized|continue|throw
*
* op ed ^throw-verification-error 20bc n varies optimized|throw op ee +execute-inline 35mi n inline-method
* optimized|continue|throw op ef +execute-inline/range 3rmi n inline-method optimized|continue|throw
*
* op f0 +invoke-object-init/range 35c n method-ref optimized|continue|throw|invoke
*
* op f2 +iget-quick 22cs y field-offset optimized|continue|throw op f3 +iget-wide-quick 22cs y field-offset
* optimized|continue|throw op f4 +iget-object-quick 22cs y field-offset optimized|continue|throw op f5 +iput-quick
* 22cs n field-offset optimized|continue|throw op f6 +iput-wide-quick 22cs n field-offset optimized|continue|throw
* op f7 +iput-object-quick 22cs n field-offset optimized|continue|throw op f8 +invoke-virtual-quick 35ms n
* vtable-offset optimized|continue|throw|invoke op f9 +invoke-virtual-quick/range 3rms n vtable-offset
* optimized|continue|throw|invoke op fa +invoke-super-quick 35ms n vtable-offset optimized|continue|throw|invoke op
* fb +invoke-super-quick/range 3rms n vtable-offset optimized|continue|throw|invoke op fc +iput-object-volatile 22c
* n field-ref optimized|continue|throw op fd +sget-object-volatile 21c y field-ref optimized|continue|throw op fe
* +sput-object-volatile 21c n field-ref optimized|continue|throw
*
* In brief: - const [string|class] - monitor [enter|exit] already handled in UnitThrowAnalysis - check cast already
* handled in UnitThrowAnalysis - instanceof already handled in UnitThrowAnalysis - array length already handled in
* UnitThrowAnalysis - new [instance|array] already handled in UnitThrowAnalysis - filled new array - throw already
* handled in UnitThrowAnalysis - invoke* already handled in UnitThrowAnalysis - [ais][get|put] already handled in
* UnitThrowAnalysis - div/rem already handled in UnitThrowAnalysis
*
* For a reference manual, look at https://code.google.com/p/android-source-browsing
*
*
*/
public class DalvikThrowAnalysis extends UnitThrowAnalysis {
/**
* Constructs a DalvikThrowAnalysis
for inclusion in Soot's global variable manager, {@link G}.
*
* @param g
* guarantees that the constructor may only be called from {@link Singletons}.
*/
public DalvikThrowAnalysis(Singletons.Global g) {
}
/**
* Returns the single instance of DalvikThrowAnalysis
.
*
* @return Soot's UnitThrowAnalysis
.
*/
public static DalvikThrowAnalysis v() {
return G.v().soot_dexpler_DalvikThrowAnalysis();
}
protected DalvikThrowAnalysis(boolean isInterproc) {
super(isInterproc);
}
public DalvikThrowAnalysis(Singletons.Global g, boolean isInterproc) {
super(isInterproc);
}
public static DalvikThrowAnalysis interproceduralAnalysis = null;
public static DalvikThrowAnalysis interproc() {
return G.v().interproceduralDalvikThrowAnalysis();
}
@Override
protected ThrowableSet defaultResult() {
return mgr.EMPTY;
}
@Override
protected UnitSwitch unitSwitch() {
return new UnitThrowAnalysis.UnitSwitch() {
// Dalvik does not throw an exception for this instruction
@Override
public void caseReturnInst(ReturnInst i) {
}
// Dalvik does not throw an exception for this instruction
@Override
public void caseReturnVoidInst(ReturnVoidInst i) {
}
@Override
public void caseEnterMonitorInst(EnterMonitorInst i) {
result = result.add(mgr.NULL_POINTER_EXCEPTION);
result = result.add(mgr.ILLEGAL_MONITOR_STATE_EXCEPTION);
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt s) {
result = result.add(mgr.NULL_POINTER_EXCEPTION);
result = result.add(mgr.ILLEGAL_MONITOR_STATE_EXCEPTION);
result = result.add(mightThrow(s.getOp()));
}
@Override
public void caseAssignStmt(AssignStmt s) {
// Dalvik only throws ArrayIndexOutOfBounds and
// NullPointerException which are both handled through the
// ArrayRef expressions. There is no ArrayStoreException in
// Dalvik.
result = result.add(mightThrow(s.getLeftOp()));
result = result.add(mightThrow(s.getRightOp()));
}
};
}
@Override
protected ValueSwitch valueSwitch() {
return new UnitThrowAnalysis.ValueSwitch() {
// from ./vm/mterp/c/OP_CONST_STRING.c
//
// HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
// {
// StringObject* strObj;
//
// vdst = INST_AA(inst);
// ref = FETCH(1);
// ILOGV("|const-string v%d string@0x%04x", vdst, ref);
// strObj = dvmDexGetResolvedString(methodClassDex, ref);
// if (strObj == NULL) {
// EXPORT_PC();
// strObj = dvmResolveString(curMethod->clazz, ref);
// if (strObj == NULL)
// GOTO_exceptionThrown(); <--- HERE
// }
// SET_REGISTER(vdst, (u4) strObj);
// }
// FINISH(2);
// OP_END
//
@Override
public void caseStringConstant(StringConstant c) {
//
// the string is already fetched when converting
// Dalvik bytecode to Jimple. A potential error
// would be detected there.
//
// result = result.add(mgr.RESOLVE_FIELD_ERRORS); // should we add another kind of exception for this?
}
//
// from ./vm/mterp/c/OP_CONST_CLASS.c
//
// HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
// {
// ClassObject* clazz;
//
// vdst = INST_AA(inst);
// ref = FETCH(1);
// ILOGV("|const-class v%d class@0x%04x", vdst, ref);
// clazz = dvmDexGetResolvedClass(methodClassDex, ref);
// if (clazz == NULL) {
// EXPORT_PC();
// clazz = dvmResolveClass(curMethod->clazz, ref, true);
// if (clazz == NULL)
// GOTO_exceptionThrown(); <--- HERE
// }
// SET_REGISTER(vdst, (u4) clazz);
// }
// FINISH(2);
// OP_END
//
@Override
public void caseClassConstant(ClassConstant c) {
//
// the string is already fetched and stored in a
// ClassConstant object when converting
// Dalvik bytecode to Jimple. A potential error
// would be detected there.
//
// result = result.add(mgr.RESOLVE_CLASS_ERRORS);
}
@Override
public void caseCastExpr(CastExpr expr) {
if (expr.getCastType() instanceof PrimType) {
// No exception are thrown for primitive casts
return;
}
Type fromType = expr.getOp().getType();
Type toType = expr.getCastType();
result = result.add(mgr.RESOLVE_CLASS_ERRORS);
if (toType instanceof RefLikeType) {
// fromType might still be unknown when we are called,
// but toType will have a value.
FastHierarchy h = Scene.v().getOrMakeFastHierarchy();
if (fromType == null || fromType instanceof UnknownType
|| ((!(fromType instanceof NullType)) && (!h.canStoreType(fromType, toType)))) {
result = result.add(mgr.CLASS_CAST_EXCEPTION);
}
}
result = result.add(mightThrow(expr.getOp()));
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy