2016-08-28 22:37:58 +00:00
|
|
|
/*
|
2018-10-30 00:09:20 +00:00
|
|
|
* Copyright (c) 2016-2018 The University of Sheffield.
|
2016-08-28 22:37:58 +00:00
|
|
|
*
|
|
|
|
* All rights reserved. This program and the accompanying materials
|
2018-10-30 00:09:20 +00:00
|
|
|
* This program and the accompanying materials are made
|
|
|
|
* available under the terms of the Eclipse Public License 2.0
|
|
|
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
2016-08-28 22:37:58 +00:00
|
|
|
*
|
2018-10-30 00:09:20 +00:00
|
|
|
* SPDX-License-Identifier: EPL-2.0
|
2016-08-28 22:37:58 +00:00
|
|
|
*/
|
|
|
|
|
2017-05-21 14:58:16 +00:00
|
|
|
package com.logicalhacking.dasca.crosslanguage.test
|
2016-08-28 22:37:58 +00:00
|
|
|
|
|
|
|
import com.ibm.wala.classLoader.CallSiteReference
|
|
|
|
import com.ibm.wala.ipa.callgraph.CGNode
|
2017-05-21 14:58:16 +00:00
|
|
|
import com.logicalhacking.dasca.crosslanguage.util.Util
|
|
|
|
import com.logicalhacking.dasca.crosslanguage.builder.CordovaCGBuilder
|
2016-08-28 22:37:58 +00:00
|
|
|
import java.io.File
|
2017-05-21 14:58:16 +00:00
|
|
|
import com.logicalhacking.dasca.crosslanguage.util.JavaScriptSourceLocation
|
|
|
|
import com.logicalhacking.dasca.crosslanguage.util.JavaSourceLocation
|
|
|
|
import com.logicalhacking.dasca.crosslanguage.util.SourceLocation
|
2016-08-28 22:37:58 +00:00
|
|
|
import scala.collection.mutable.LinkedHashSet
|
2017-05-21 14:58:16 +00:00
|
|
|
import com.logicalhacking.dasca.crosslanguage.builder.CrossBuilderOption
|
|
|
|
import com.logicalhacking.dasca.crosslanguage.builder.MergedCallGraph
|
|
|
|
import com.logicalhacking.dasca.crosslanguage.builder._
|
2016-09-01 23:05:47 +00:00
|
|
|
import com.ibm.wala.cast.ir.ssa.AstIRFactory
|
2018-10-25 20:54:28 +00:00
|
|
|
import com.ibm.wala.cast.ir.ssa.AstIRFactory.AstIR
|
2016-09-01 23:05:47 +00:00
|
|
|
import com.ibm.wala.classLoader.IMethod
|
2016-08-28 22:37:58 +00:00
|
|
|
|
2016-08-29 21:47:33 +00:00
|
|
|
class AppTest {
|
2016-08-31 07:24:29 +00:00
|
|
|
private var cg = null:MergedCallGraph;
|
|
|
|
|
2016-08-28 22:37:58 +00:00
|
|
|
private var js2JavaHits = -1;
|
|
|
|
private var js2JavaMisses = -1;
|
|
|
|
private var js2JavaTotal = -1;
|
|
|
|
|
|
|
|
private var java2JSHits = -1;
|
|
|
|
private var java2JSMisses = -1;
|
|
|
|
private var java2JSTotal = -1;
|
|
|
|
|
|
|
|
def getJS2JavaHits() = {
|
|
|
|
js2JavaHits
|
|
|
|
}
|
|
|
|
def getJS2JavaMisses() = {
|
|
|
|
js2JavaMisses
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJS2JavaErrors() = {
|
|
|
|
js2JavaTotal - js2JavaHits
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJS2JavaRecall() = {
|
|
|
|
100.0 * js2JavaHits / (js2JavaHits + js2JavaMisses)
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJS2JavaPrecision() = {
|
|
|
|
100.0 * js2JavaHits / js2JavaTotal
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJava2JSHits() = {
|
|
|
|
java2JSHits
|
|
|
|
}
|
|
|
|
def getJava2JSMisses() = {
|
|
|
|
java2JSMisses
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJava2JSErrors() = {
|
|
|
|
java2JSTotal - java2JSHits
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJava2JSRecall() = {
|
|
|
|
100.0 * java2JSHits / (java2JSHits + java2JSMisses)
|
|
|
|
}
|
|
|
|
|
|
|
|
def getJava2JSPrecision() = {
|
|
|
|
100.0 * java2JSHits / java2JSTotal
|
|
|
|
}
|
|
|
|
|
|
|
|
private var truePositives = Set[(SourceLocation, SourceLocation)]()
|
|
|
|
private var falseNegatives = Set[(SourceLocation, SourceLocation)]()
|
|
|
|
private var falsePositives = Set[(SourceLocation, SourceLocation)]()
|
|
|
|
|
|
|
|
def getTruePositives() = {
|
|
|
|
truePositives
|
|
|
|
}
|
|
|
|
|
|
|
|
def getFalseNegatives() = {
|
|
|
|
falseNegatives
|
|
|
|
}
|
|
|
|
|
|
|
|
def getFalsePositives() = {
|
|
|
|
falsePositives
|
|
|
|
}
|
2016-08-31 07:24:29 +00:00
|
|
|
|
|
|
|
def getCallGraphSize() = cg.getNumberOfNodes
|
|
|
|
|
|
|
|
def getJSCallGraphSize() = cg.jsCG.getNumberOfNodes
|
|
|
|
|
|
|
|
def getJavaCallGraphSize() = cg.javaCG.getNumberOfNodes
|
|
|
|
|
|
|
|
|
|
|
|
private var cgSize = -1
|
2016-08-29 21:47:33 +00:00
|
|
|
|
|
|
|
def analyze(apk:String, options:List[CrossBuilderOption], expectedConnections:Set[(SourceLocation, SourceLocation)]):Boolean = {
|
2016-08-30 08:32:27 +00:00
|
|
|
val builder = CordovaCGBuilder(new File(getClass.getResource("/"+apk).getFile));
|
2016-08-29 21:47:33 +00:00
|
|
|
builder.setOptions(options:_*)
|
2016-08-31 07:24:29 +00:00
|
|
|
cg = builder.createCallGraph
|
|
|
|
val crossTargets = cg.getAllCrossTargets
|
2016-08-28 22:37:58 +00:00
|
|
|
val convertedCrossTargets = convertToSourceLocationPairs(crossTargets)
|
|
|
|
val (javaPairs, jsPairs) = convertedCrossTargets.partition({case (origin, target) => origin.isInstanceOf[JavaSourceLocation]})
|
|
|
|
java2JSTotal = javaPairs.size
|
|
|
|
js2JavaTotal = jsPairs.size
|
|
|
|
val (found, notFound) = expectedConnections.partition(p => convertedCrossTargets.contains(p))
|
|
|
|
java2JSHits = found.count(_._1.isInstanceOf[JavaSourceLocation])
|
|
|
|
js2JavaHits = found.count(_._1.isInstanceOf[JavaScriptSourceLocation])
|
|
|
|
java2JSMisses = notFound.count(_._1.isInstanceOf[JavaSourceLocation])
|
|
|
|
js2JavaMisses = notFound.count(_._1.isInstanceOf[JavaScriptSourceLocation])
|
|
|
|
|
|
|
|
truePositives = found
|
|
|
|
falseNegatives = notFound
|
|
|
|
falsePositives = convertedCrossTargets -- expectedConnections
|
2016-08-29 21:47:33 +00:00
|
|
|
true
|
2016-08-28 22:37:58 +00:00
|
|
|
}
|
2016-08-29 21:47:33 +00:00
|
|
|
|
|
|
|
def convertToSourceLocationPairs(crossTargets: Map[(CGNode, CallSiteReference), LinkedHashSet[CGNode]]): Set[(SourceLocation, SourceLocation)] = {
|
2016-08-28 22:37:58 +00:00
|
|
|
for (
|
|
|
|
origin <- crossTargets.keys;
|
|
|
|
target <- crossTargets.get(origin).get
|
|
|
|
) yield {
|
|
|
|
if (Util.isJavaNode(origin._1)) {
|
|
|
|
target.getIR match {
|
2018-10-25 20:54:28 +00:00
|
|
|
case ir: AstIR => (JavaSourceLocation(origin._1, origin._2), JavaScriptSourceLocation(ir))
|
2016-08-28 22:37:58 +00:00
|
|
|
case _ => (JavaSourceLocation(origin._1, origin._2), new JavaScriptSourceLocation(-1, -1, "unknown"))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
origin._1.getIR match {
|
2018-10-25 20:54:28 +00:00
|
|
|
case ir: AstIR => (JavaScriptSourceLocation(ir, origin._2), JavaSourceLocation(target))
|
2016-08-28 22:37:58 +00:00
|
|
|
case _ => (new JavaScriptSourceLocation(-1, -1, "unknown"), JavaSourceLocation(target))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.toSet
|
2016-08-29 21:47:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-08-28 22:37:58 +00:00
|
|
|
}
|