110 lines
4.0 KiB
Scala
110 lines
4.0 KiB
Scala
/*
|
|
* (C) Copyright 2010-2015 SAP SE.
|
|
*
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
*/
|
|
|
|
package com.logicalhacking.dasca.crosslanguage.builder.algorithms
|
|
|
|
import scala.collection.JavaConverters.asScalaIteratorConverter
|
|
import scala.collection.JavaConverters.collectionAsScalaIterableConverter
|
|
|
|
import org.slf4j.LoggerFactory
|
|
|
|
import com.ibm.wala.ipa.callgraph.CGNode
|
|
import com.ibm.wala.ipa.callgraph.CallGraph
|
|
import com.ibm.wala.ipa.cfg.BasicBlockInContext
|
|
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction
|
|
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction
|
|
import com.ibm.wala.ssa.SSAConditionalBranchInstruction
|
|
import com.ibm.wala.ssa.analysis.ExplodedControlFlowGraph
|
|
import com.ibm.wala.ssa.analysis.IExplodedBasicBlock
|
|
import com.typesafe.scalalogging.Logger
|
|
|
|
import scala.{ Option => ? }
|
|
|
|
class ExecuteActionBasedChecker(val cg: CallGraph,
|
|
val keep: CGNode => Boolean,
|
|
val action: String,
|
|
val execNode: CGNode) extends ReachabilityChecker(cg, keep) {
|
|
val symbolTable = execNode.getIR.getSymbolTable
|
|
override val logger = Logger(LoggerFactory.getLogger(getClass.toString))
|
|
|
|
override def canPassThrough(toBB: IExplodedBasicBlock,
|
|
predBB: IExplodedBasicBlock): Boolean = {
|
|
// Asuming both basic blocks are from the execNode
|
|
predBB.getLastInstruction match {
|
|
case cond: SSAConditionalBranchInstruction if cond.getOperator == IConditionalBranchInstruction.Operator.EQ => {
|
|
val vl = cond.getUse(0)
|
|
val vr = cond.getUse(1)
|
|
// The right side (vr) is apparently always either one or zero in conditional eq instructions
|
|
|
|
// We are only looking for equal calls on the second method parameter of the cordova execute method,
|
|
// which is "action"
|
|
val nonActionUseInEquals = isEqualsAndDependsOnActionParam(vl)
|
|
|
|
if (nonActionUseInEquals != -1 && symbolTable.isConstant(nonActionUseInEquals) &&
|
|
symbolTable.isStringConstant(nonActionUseInEquals)) {
|
|
val actionString = symbolTable.getStringValue(nonActionUseInEquals)
|
|
if (actionString.equals(action) && !isTrueBranch(vr, toBB, predBB)) {
|
|
return false
|
|
} else if (!actionString.equals(action) && isTrueBranch(vr, toBB, predBB)) {
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
case _ => true
|
|
}
|
|
}
|
|
|
|
def isEqualsAndDependsOnActionParam(v: Int): Int = {
|
|
for (
|
|
invoke <- ?(execNode.getDU.getDef(v)).collect({ case i: SSAAbstractInvokeInstruction => i });
|
|
if (invoke.getDeclaredTarget.toString().contains("equal"))
|
|
) {
|
|
if (invoke.getUse(0) == 2) {
|
|
return invoke.getUse(1)
|
|
} else if (invoke.getUse(1) == 2) {
|
|
return invoke.getUse(0)
|
|
}
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
def isTrueBranch(v: Int,
|
|
toBB: IExplodedBasicBlock,
|
|
predBB: IExplodedBasicBlock): Boolean = {
|
|
if (symbolTable.isOneOrTrue(v) && predBB.getLastInstructionIndex + 1 != toBB.getLastInstructionIndex) {
|
|
return true
|
|
} else if (symbolTable.isZeroOrFalse(v) && predBB.getLastInstructionIndex + 1 == toBB.getLastInstructionIndex) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
def extraPredNodes(node: CGNode): List[CGNode] = {
|
|
if (node.getMethod.getName.toString().equals("run")) {
|
|
for (
|
|
interf <- node.getMethod.getDeclaringClass.getAllImplementedInterfaces.asScala;
|
|
if (interf.getName().toString().equals("Ljava/lang/Runnable"));
|
|
n <- cg.iterator().asScala;
|
|
if (n.getMethod.getDeclaringClass == node.getMethod.getDeclaringClass);
|
|
if (n.getMethod.getName.toString() == "<init>")
|
|
) {
|
|
return List(n)
|
|
}
|
|
}
|
|
return List.empty
|
|
}
|
|
}
|