Convert all Java source files to use Unix line endings; no semantic change

This commit is contained in:
Manu Sridharan 2012-09-04 15:56:05 -07:00
parent fcab11e5b8
commit 256cd06460
900 changed files with 137644 additions and 137644 deletions

View File

@ -1,303 +1,303 @@
/**
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.demandpa.driver;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.core.tests.util.TestConstants;
import com.ibm.wala.demandpa.alg.ContextSensitiveStateMachine;
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo;
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo.PointsToResult;
import com.ibm.wala.demandpa.alg.refinepolicy.FieldRefinePolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.ManualFieldPolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.ManualRefinementPolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.RefinementPolicyFactory;
import com.ibm.wala.demandpa.alg.refinepolicy.TunedRefinementPolicy;
import com.ibm.wala.demandpa.alg.statemachine.StateMachineFactory;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.demandpa.util.MemoryAccessMap;
import com.ibm.wala.demandpa.util.SimpleMemoryAccessMap;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.CallGraphStats;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.properties.WalaProperties;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSACheckCastInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.Predicate;
import com.ibm.wala.util.ProgressMaster;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions;
/**
* Uses a demand-driven points-to analysis to check the safety of downcasts.
*
* @author Manu Sridharan
*
*/
public class DemandCastChecker {
// maximum number of casts to check
private static final int MAX_CASTS = Integer.MAX_VALUE;
/**
* @param args
* @throws CancelException
* @throws IllegalArgumentException
* @throws IOException
*/
public static void main(String[] args) throws IllegalArgumentException, CancelException, IOException {
try {
Properties p = new Properties();
p.putAll(WalaProperties.loadProperties());
} catch (WalaException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
runTestCase(TestConstants.JLEX_MAIN, TestConstants.JLEX, "JLex");
// runTestCase(TestConstants.HELLO_MAIN, TestConstants.HELLO, "Hello");
}
public static void runTestCase(String mainClass, String scopeFile, String benchName) throws IllegalArgumentException,
CancelException, IOException {
System.err.println("=====BENCHMARK " + benchName + "=====");
System.err.println("analyzing " + benchName);
DemandRefinementPointsTo dmp = null;
try {
dmp = makeDemandPointerAnalysis(scopeFile, mainClass, benchName);
findFailingCasts(dmp.getBaseCallGraph(), dmp);
} catch (ClassHierarchyException e) {
e.printStackTrace();
}
System.err.println("=*=*=*=*=*=*=*=*=*=*=*=*=*=*");
System.err.println("");
System.err.println("");
}
private static DemandRefinementPointsTo makeDemandPointerAnalysis(String scopeFile, String mainClass, String benchName)
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, getExclusions(benchName));
// build a type hierarchy
ClassHierarchy cha = ClassHierarchy.make(scope);
// set up call graph construction options; mainly what should be considered
// entrypoints?
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass);
AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints);
System.err.print("constructing call graph...");
final Pair<CallGraph, PointerAnalysis> cgAndPA = buildCallGraph(scope, cha, options);
CallGraph cg = cgAndPA.fst;
System.err.println("done");
System.err.println(CallGraphStats.getStats(cg));
MemoryAccessMap fam = new SimpleMemoryAccessMap(cg, cgAndPA.snd.getHeapModel(), false);
DemandRefinementPointsTo fullDemandPointsTo = DemandRefinementPointsTo.makeWithDefaultFlowGraph(cg, heapModel, fam, cha, options, makeStateMachineFactory());
fullDemandPointsTo.setRefinementPolicyFactory(chooseRefinePolicyFactory(cha));
return fullDemandPointsTo;
}
private static String getExclusions(String benchName) {
return CallGraphTestUtil.REGRESSION_EXCLUSIONS;
}
// if true, construct up-front call graph cheaply (0-CFA)
private static final boolean CHEAP_CG = true;
private static HeapModel heapModel;
/**
* builds a call graph, and sets the corresponding heap model for analysis
*
* @param scope
* @param cha
* @param options
* @return
* @throws CancelException
* @throws IllegalArgumentException
*/
private static Pair<CallGraph, PointerAnalysis> buildCallGraph(AnalysisScope scope, ClassHierarchy cha, AnalysisOptions options)
throws IllegalArgumentException, CancelException {
CallGraph retCG = null;
PointerAnalysis retPA = null;
final AnalysisCache cache = new AnalysisCache();
CallGraphBuilder builder;
if (CHEAP_CG) {
builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
// we want vanilla 0-1 CFA, which has one abstract loc per allocation
heapModel = Util.makeVanillaZeroOneCFABuilder(options, cache, cha, scope);
} else {
builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope);
heapModel = (HeapModel) builder;
}
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
master.setMillisPerWorkItem(360000);
master.beginTask("runSolver", 1);
try {
retCG = builder.makeCallGraph(options, master);
retPA = builder.getPointerAnalysis();
} catch (CallGraphBuilderCancelException e) {
System.err.println("TIMED OUT!!");
retCG = e.getPartialCallGraph();
retPA = e.getPartialPointerAnalysis();
}
return Pair.make(retCG, retPA);
}
private static RefinementPolicyFactory chooseRefinePolicyFactory(ClassHierarchy cha) {
if (true) {
return new TunedRefinementPolicy.Factory(cha);
} else {
return new ManualRefinementPolicy.Factory(cha);
}
}
private static StateMachineFactory<IFlowLabel> makeStateMachineFactory() {
return new ContextSensitiveStateMachine.Factory();
}
private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts(CallGraph cg, DemandRefinementPointsTo dmp) {
final IClassHierarchy cha = dmp.getClassHierarchy();
List<Pair<CGNode, SSACheckCastInstruction>> failing = new ArrayList<Pair<CGNode, SSACheckCastInstruction>>();
int numSafe = 0, numMightFail = 0;
outer: for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext();) {
CGNode node = nodeIter.next();
TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass();
// skip library classes
if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) {
continue;
}
IR ir = node.getIR();
if (ir == null)
continue;
SSAInstruction[] instrs = ir.getInstructions();
for (int i = 0; i < instrs.length; i++) {
if (numSafe + numMightFail > MAX_CASTS)
break outer;
SSAInstruction instruction = instrs[i];
if (instruction instanceof SSACheckCastInstruction) {
SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction;
final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes();
boolean primOnly = true;
for (TypeReference t : declaredResultTypes) {
if (! t.isPrimitiveType()) {
primOnly = false;
}
}
if (primOnly) {
continue;
}
System.err.println("CHECKING " + castInstr + " in " + node.getMethod());
PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0));
Predicate<InstanceKey> castPred = new Predicate<InstanceKey>() {
@Override
public boolean test(InstanceKey ik) {
TypeReference ikTypeRef = ik.getConcreteType().getReference();
for (TypeReference t : declaredResultTypes) {
if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) {
return true;
}
}
return false;
}
};
long startTime = System.currentTimeMillis();
Pair<PointsToResult, Collection<InstanceKey>> queryResult = dmp.getPointsTo(castedPk, castPred);
long runningTime = System.currentTimeMillis() - startTime;
System.err.println("running time: " + runningTime + "ms");
final FieldRefinePolicy fieldRefinePolicy = dmp.getRefinementPolicy().getFieldRefinePolicy();
switch (queryResult.fst) {
case SUCCESS:
System.err.println("SAFE: " + castInstr + " in " + node.getMethod());
if (fieldRefinePolicy instanceof ManualFieldPolicy) {
ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy;
System.err.println(hackedFieldPolicy.getHistory());
}
System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes");
numSafe++;
break;
case NOMOREREFINE:
if (queryResult.snd != null) {
System.err.println("MIGHT FAIL: no more refinement possible for " + castInstr + " in " + node.getMethod());
} else {
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
}
failing.add(Pair.make(node, castInstr));
numMightFail++;
break;
case BUDGETEXCEEDED:
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
failing.add(Pair.make(node, castInstr));
numMightFail++;
break;
default:
Assertions.UNREACHABLE();
}
}
}
// break outer;
}
System.err.println("TOTAL SAFE: " + numSafe);
System.err.println("TOTAL MIGHT FAIL: " + numMightFail);
return failing;
}
}
/**
* Refinement Analysis Tools is Copyright (c) 2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipient's reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents' employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.demandpa.driver;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.core.tests.util.TestConstants;
import com.ibm.wala.demandpa.alg.ContextSensitiveStateMachine;
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo;
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo.PointsToResult;
import com.ibm.wala.demandpa.alg.refinepolicy.FieldRefinePolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.ManualFieldPolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.ManualRefinementPolicy;
import com.ibm.wala.demandpa.alg.refinepolicy.RefinementPolicyFactory;
import com.ibm.wala.demandpa.alg.refinepolicy.TunedRefinementPolicy;
import com.ibm.wala.demandpa.alg.statemachine.StateMachineFactory;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.demandpa.util.MemoryAccessMap;
import com.ibm.wala.demandpa.util.SimpleMemoryAccessMap;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.CallGraphStats;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.properties.WalaProperties;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSACheckCastInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.Predicate;
import com.ibm.wala.util.ProgressMaster;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions;
/**
* Uses a demand-driven points-to analysis to check the safety of downcasts.
*
* @author Manu Sridharan
*
*/
public class DemandCastChecker {
// maximum number of casts to check
private static final int MAX_CASTS = Integer.MAX_VALUE;
/**
* @param args
* @throws CancelException
* @throws IllegalArgumentException
* @throws IOException
*/
public static void main(String[] args) throws IllegalArgumentException, CancelException, IOException {
try {
Properties p = new Properties();
p.putAll(WalaProperties.loadProperties());
} catch (WalaException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
runTestCase(TestConstants.JLEX_MAIN, TestConstants.JLEX, "JLex");
// runTestCase(TestConstants.HELLO_MAIN, TestConstants.HELLO, "Hello");
}
public static void runTestCase(String mainClass, String scopeFile, String benchName) throws IllegalArgumentException,
CancelException, IOException {
System.err.println("=====BENCHMARK " + benchName + "=====");
System.err.println("analyzing " + benchName);
DemandRefinementPointsTo dmp = null;
try {
dmp = makeDemandPointerAnalysis(scopeFile, mainClass, benchName);
findFailingCasts(dmp.getBaseCallGraph(), dmp);
} catch (ClassHierarchyException e) {
e.printStackTrace();
}
System.err.println("=*=*=*=*=*=*=*=*=*=*=*=*=*=*");
System.err.println("");
System.err.println("");
}
private static DemandRefinementPointsTo makeDemandPointerAnalysis(String scopeFile, String mainClass, String benchName)
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, getExclusions(benchName));
// build a type hierarchy
ClassHierarchy cha = ClassHierarchy.make(scope);
// set up call graph construction options; mainly what should be considered
// entrypoints?
Iterable<Entrypoint> entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass);
AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints);
System.err.print("constructing call graph...");
final Pair<CallGraph, PointerAnalysis> cgAndPA = buildCallGraph(scope, cha, options);
CallGraph cg = cgAndPA.fst;
System.err.println("done");
System.err.println(CallGraphStats.getStats(cg));
MemoryAccessMap fam = new SimpleMemoryAccessMap(cg, cgAndPA.snd.getHeapModel(), false);
DemandRefinementPointsTo fullDemandPointsTo = DemandRefinementPointsTo.makeWithDefaultFlowGraph(cg, heapModel, fam, cha, options, makeStateMachineFactory());
fullDemandPointsTo.setRefinementPolicyFactory(chooseRefinePolicyFactory(cha));
return fullDemandPointsTo;
}
private static String getExclusions(String benchName) {
return CallGraphTestUtil.REGRESSION_EXCLUSIONS;
}
// if true, construct up-front call graph cheaply (0-CFA)
private static final boolean CHEAP_CG = true;
private static HeapModel heapModel;
/**
* builds a call graph, and sets the corresponding heap model for analysis
*
* @param scope
* @param cha
* @param options
* @return
* @throws CancelException
* @throws IllegalArgumentException
*/
private static Pair<CallGraph, PointerAnalysis> buildCallGraph(AnalysisScope scope, ClassHierarchy cha, AnalysisOptions options)
throws IllegalArgumentException, CancelException {
CallGraph retCG = null;
PointerAnalysis retPA = null;
final AnalysisCache cache = new AnalysisCache();
CallGraphBuilder builder;
if (CHEAP_CG) {
builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
// we want vanilla 0-1 CFA, which has one abstract loc per allocation
heapModel = Util.makeVanillaZeroOneCFABuilder(options, cache, cha, scope);
} else {
builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope);
heapModel = (HeapModel) builder;
}
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
master.setMillisPerWorkItem(360000);
master.beginTask("runSolver", 1);
try {
retCG = builder.makeCallGraph(options, master);
retPA = builder.getPointerAnalysis();
} catch (CallGraphBuilderCancelException e) {
System.err.println("TIMED OUT!!");
retCG = e.getPartialCallGraph();
retPA = e.getPartialPointerAnalysis();
}
return Pair.make(retCG, retPA);
}
private static RefinementPolicyFactory chooseRefinePolicyFactory(ClassHierarchy cha) {
if (true) {
return new TunedRefinementPolicy.Factory(cha);
} else {
return new ManualRefinementPolicy.Factory(cha);
}
}
private static StateMachineFactory<IFlowLabel> makeStateMachineFactory() {
return new ContextSensitiveStateMachine.Factory();
}
private static List<Pair<CGNode, SSACheckCastInstruction>> findFailingCasts(CallGraph cg, DemandRefinementPointsTo dmp) {
final IClassHierarchy cha = dmp.getClassHierarchy();
List<Pair<CGNode, SSACheckCastInstruction>> failing = new ArrayList<Pair<CGNode, SSACheckCastInstruction>>();
int numSafe = 0, numMightFail = 0;
outer: for (Iterator<? extends CGNode> nodeIter = cg.iterator(); nodeIter.hasNext();) {
CGNode node = nodeIter.next();
TypeReference declaringClass = node.getMethod().getReference().getDeclaringClass();
// skip library classes
if (declaringClass.getClassLoader().equals(ClassLoaderReference.Primordial)) {
continue;
}
IR ir = node.getIR();
if (ir == null)
continue;
SSAInstruction[] instrs = ir.getInstructions();
for (int i = 0; i < instrs.length; i++) {
if (numSafe + numMightFail > MAX_CASTS)
break outer;
SSAInstruction instruction = instrs[i];
if (instruction instanceof SSACheckCastInstruction) {
SSACheckCastInstruction castInstr = (SSACheckCastInstruction) instruction;
final TypeReference[] declaredResultTypes = castInstr.getDeclaredResultTypes();
boolean primOnly = true;
for (TypeReference t : declaredResultTypes) {
if (! t.isPrimitiveType()) {
primOnly = false;
}
}
if (primOnly) {
continue;
}
System.err.println("CHECKING " + castInstr + " in " + node.getMethod());
PointerKey castedPk = heapModel.getPointerKeyForLocal(node, castInstr.getUse(0));
Predicate<InstanceKey> castPred = new Predicate<InstanceKey>() {
@Override
public boolean test(InstanceKey ik) {
TypeReference ikTypeRef = ik.getConcreteType().getReference();
for (TypeReference t : declaredResultTypes) {
if (cha.isAssignableFrom(cha.lookupClass(t), cha.lookupClass(ikTypeRef))) {
return true;
}
}
return false;
}
};
long startTime = System.currentTimeMillis();
Pair<PointsToResult, Collection<InstanceKey>> queryResult = dmp.getPointsTo(castedPk, castPred);
long runningTime = System.currentTimeMillis() - startTime;
System.err.println("running time: " + runningTime + "ms");
final FieldRefinePolicy fieldRefinePolicy = dmp.getRefinementPolicy().getFieldRefinePolicy();
switch (queryResult.fst) {
case SUCCESS:
System.err.println("SAFE: " + castInstr + " in " + node.getMethod());
if (fieldRefinePolicy instanceof ManualFieldPolicy) {
ManualFieldPolicy hackedFieldPolicy = (ManualFieldPolicy) fieldRefinePolicy;
System.err.println(hackedFieldPolicy.getHistory());
}
System.err.println("TRAVERSED " + dmp.getNumNodesTraversed() + " nodes");
numSafe++;
break;
case NOMOREREFINE:
if (queryResult.snd != null) {
System.err.println("MIGHT FAIL: no more refinement possible for " + castInstr + " in " + node.getMethod());
} else {
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
}
failing.add(Pair.make(node, castInstr));
numMightFail++;
break;
case BUDGETEXCEEDED:
System.err.println("MIGHT FAIL: exceeded budget for " + castInstr + " in " + node.getMethod());
failing.add(Pair.make(node, castInstr));
numMightFail++;
break;
default:
Assertions.UNREACHABLE();
}
}
}
// break outer;
}
System.err.println("TOTAL SAFE: " + numSafe);
System.err.println("TOTAL MIGHT FAIL: " + numMightFail);
return failing;
}
}

View File

@ -1,229 +1,229 @@
/**
*
*/
package com.ibm.wala.cast.java.translator.polyglot;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import polyglot.types.ArrayType;
import polyglot.types.ClassType;
import polyglot.types.CodeInstance;
import polyglot.types.ConstructorInstance;
import polyglot.types.FieldInstance;
import polyglot.types.InitializerInstance;
import polyglot.types.MemberDef;
import polyglot.types.MethodInstance;
import polyglot.types.PrimitiveType;
import polyglot.types.ProcedureInstance;
import polyglot.types.Type;
import com.ibm.wala.cast.java.translator.polyglot.PolyglotJava2CAstTranslator.IdentityMapper;
import com.ibm.wala.cast.java.types.JavaPrimitiveTypeMap;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* Class responsible for mapping Polyglot type system objects representing types,
* methods and fields to the corresponding WALA TypeReferences, MethodReferences
* and FieldReferences. Used during translation and by clients to help correlate
* WALA analysis results to the various AST nodes.
* @author rfuhrer
*/
public class PolyglotIdentityMapper implements IdentityMapper<Type, CodeInstance, FieldInstance> {
private final Map<Type, TypeReference> fTypeMap = HashMapFactory.make();
private final Map<FieldInstance, FieldReference> fFieldMap = HashMapFactory.make();
private final Map<CodeInstance, MethodReference> fMethodMap = HashMapFactory.make();
/**
* Map from Polyglot local ClassTypes to their enclosing methods. Used by localTypeToTypeID().<br>
* Needed since Polyglot doesn't provide this information. (It doesn't need to, since it
* doesn't need to generate unambiguous names for such entities -- it hands the source
* off to javac to generate bytecode. It probably also wouldn't want to, since that would
* create back-pointers from Type objects in the TypeSystem to AST's.)
*/
protected Map<ClassType, CodeInstance> fLocalTypeMap = new LinkedHashMap<ClassType, CodeInstance>();
protected final ClassLoaderReference fClassLoaderRef;
public PolyglotIdentityMapper(ClassLoaderReference clr) {
fClassLoaderRef= clr;
}
public FieldReference getFieldRef(FieldInstance field) {
if (!fFieldMap.containsKey(field)) {
FieldReference ref= referenceForField(field);
fFieldMap.put(field, ref);
return ref;
}
return fFieldMap.get(field);
}
public TypeReference getTypeRef(Type type) {
if (!fTypeMap.containsKey(type)) {
TypeReference ref= referenceForType(type);
fTypeMap.put(type, ref);
return ref;
}
return fTypeMap.get(type);
}
public MethodReference getMethodRef(CodeInstance method) {
if (!fMethodMap.containsKey(method)) {
MethodReference sel= referenceForMethod(method);
fMethodMap.put(method, sel);
return sel;
}
return fMethodMap.get(method);
}
public void mapLocalAnonTypeToMethod(ClassType anonLocalType, CodeInstance owningProc) {
fLocalTypeMap.put(anonLocalType, owningProc);
}
/**
* Create a FieldReference for the given Polyglot FieldInstance.<br>
* N.B.: This method <b>does not canonicalize</b> the FieldReferences,
* but rather creates a new one for each call.
* You more likely want to call getFieldRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having FieldInstances collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public FieldReference referenceForField(FieldInstance field) {
Type targetType= field.container();
Type fieldType= field.type();
TypeReference targetTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(targetType));
TypeReference fieldTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(fieldType));
Atom fieldName= Atom.findOrCreateUnicodeAtom(field.name().toString());
FieldReference fieldRef= FieldReference.findOrCreate(targetTypeRef, fieldName, fieldTypeRef);
return fieldRef;
}
/**
* Create a TypeReference for the given Polyglot Type.<br>
* N.B.: This method <b>does not canonicalize</b> the TypeReferences,
* but rather creates a new one for each call.
* You more likely want to call getTypeRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having Types collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public TypeReference referenceForType(Type type) {
TypeName typeName= TypeName.string2TypeName(typeToTypeID(type));
TypeReference typeRef= TypeReference.findOrCreate(fClassLoaderRef, typeName);
return typeRef;
}
private Selector selectorForMethod(CodeInstance procInstance) {
Atom name=
(procInstance instanceof ConstructorInstance) ?
MethodReference.initAtom :
(procInstance instanceof InitializerInstance) ?
MethodReference.clinitName :
Atom.findOrCreateUnicodeAtom(((MethodInstance) procInstance).name().toString());
TypeName[] argTypeNames = null;
if (! (procInstance instanceof InitializerInstance)) {
List formalTypes = ((ProcedureInstance)procInstance).formalTypes();
int numArgs = formalTypes.size();
// Descriptor prefers null to an empty array
if (numArgs > 0) {
argTypeNames = new TypeName[numArgs];
int i = 0;
for(Iterator iter = formalTypes.iterator(); iter.hasNext(); i++) {
Type argType= (Type) iter.next();
argTypeNames[i]= TypeName.string2TypeName(typeToTypeID(argType));
}
}
}
Type retType=
(procInstance instanceof MethodInstance) ? ((MethodInstance) procInstance).returnType() : procInstance.typeSystem().Void();
TypeName retTypeName= TypeName.string2TypeName(typeToTypeID(retType));
Descriptor desc= Descriptor.findOrCreate(argTypeNames, retTypeName);
return new Selector(name, desc);
}
/**
* Create a MethodReference for the given Polyglot MethodInstance.<br>
* N.B.: This method <b>does not canonicalize</b> the MethodReferences,
* but rather creates a new one for each call.
* You more likely want to call getMethodRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having MethodInstances collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public MethodReference referenceForMethod(CodeInstance procInstance) {
// Handles both ConstructorInstance's and MethodInstance's
TypeName ownerType= TypeName.string2TypeName(typeToTypeID(((MemberDef) procInstance.def()).container().get()));
TypeReference ownerTypeRef= TypeReference.findOrCreate(fClassLoaderRef, ownerType);
MethodReference methodRef= MethodReference.findOrCreate(ownerTypeRef, selectorForMethod(procInstance));
return methodRef;
}
/**
* Translates the given Polyglot type to a name suitable for use in a WALA TypeReference
* (i.e. a bytecode-compliant type name).
*/
public String typeToTypeID(Type type) {
if (type.isPrimitive()) {
PrimitiveType ptype= (PrimitiveType) type;
return JavaPrimitiveTypeMap.getShortName(ptype.name().toString());
} else if (type.isArray()) {
ArrayType atype= (ArrayType) type;
return "[" + typeToTypeID(atype.base());
} else if (type.isNull()) {
Assertions.UNREACHABLE("typeToTypeID() encountered a null type!");
return null;
}
Assertions.productionAssertion(type.isClass(), "typeToTypeID() encountered the type " + type + " that is neither primitive, array, nor class!");
ClassType ctype= (ClassType) type;
return (ctype.isLocal() || ctype.isAnonymous()) ? anonLocalTypeToTypeID(ctype) : composeWALATypeDescriptor(ctype);
}
public String anonLocalTypeToTypeID(ClassType ctype) {
CodeInstance procInstance= (CodeInstance) fLocalTypeMap.get(ctype);
String outerTypeID= typeToTypeID(ctype.outer());
String shortName= (ctype.isAnonymous()) ? PolyglotJava2CAstTranslator.anonTypeName(ctype) : ctype.fullName().name().toString();
return outerTypeID + '/' + getMethodRef(procInstance).getSelector() + '/' + shortName;
}
public String composeWALATypeDescriptor(ClassType ctype) {
return "L" + composeWALATypeName(ctype);
}
public String composeWALATypeName(ClassType ctype) {
if (ctype.package_() != null) {
String packageName = ctype.package_().fullName().toString();
Assertions.productionAssertion(ctype.fullName().toString().startsWith(packageName));
return packageName.replace('.','/') + "/" + ctype.fullName().toString().substring( packageName.length()+1 ).replace('.','$');
} else {
return ctype.fullName().toString().replace('.', '$');
}
}
}
/**
*
*/
package com.ibm.wala.cast.java.translator.polyglot;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import polyglot.types.ArrayType;
import polyglot.types.ClassType;
import polyglot.types.CodeInstance;
import polyglot.types.ConstructorInstance;
import polyglot.types.FieldInstance;
import polyglot.types.InitializerInstance;
import polyglot.types.MemberDef;
import polyglot.types.MethodInstance;
import polyglot.types.PrimitiveType;
import polyglot.types.ProcedureInstance;
import polyglot.types.Type;
import com.ibm.wala.cast.java.translator.polyglot.PolyglotJava2CAstTranslator.IdentityMapper;
import com.ibm.wala.cast.java.types.JavaPrimitiveTypeMap;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* Class responsible for mapping Polyglot type system objects representing types,
* methods and fields to the corresponding WALA TypeReferences, MethodReferences
* and FieldReferences. Used during translation and by clients to help correlate
* WALA analysis results to the various AST nodes.
* @author rfuhrer
*/
public class PolyglotIdentityMapper implements IdentityMapper<Type, CodeInstance, FieldInstance> {
private final Map<Type, TypeReference> fTypeMap = HashMapFactory.make();
private final Map<FieldInstance, FieldReference> fFieldMap = HashMapFactory.make();
private final Map<CodeInstance, MethodReference> fMethodMap = HashMapFactory.make();
/**
* Map from Polyglot local ClassTypes to their enclosing methods. Used by localTypeToTypeID().<br>
* Needed since Polyglot doesn't provide this information. (It doesn't need to, since it
* doesn't need to generate unambiguous names for such entities -- it hands the source
* off to javac to generate bytecode. It probably also wouldn't want to, since that would
* create back-pointers from Type objects in the TypeSystem to AST's.)
*/
protected Map<ClassType, CodeInstance> fLocalTypeMap = new LinkedHashMap<ClassType, CodeInstance>();
protected final ClassLoaderReference fClassLoaderRef;
public PolyglotIdentityMapper(ClassLoaderReference clr) {
fClassLoaderRef= clr;
}
public FieldReference getFieldRef(FieldInstance field) {
if (!fFieldMap.containsKey(field)) {
FieldReference ref= referenceForField(field);
fFieldMap.put(field, ref);
return ref;
}
return fFieldMap.get(field);
}
public TypeReference getTypeRef(Type type) {
if (!fTypeMap.containsKey(type)) {
TypeReference ref= referenceForType(type);
fTypeMap.put(type, ref);
return ref;
}
return fTypeMap.get(type);
}
public MethodReference getMethodRef(CodeInstance method) {
if (!fMethodMap.containsKey(method)) {
MethodReference sel= referenceForMethod(method);
fMethodMap.put(method, sel);
return sel;
}
return fMethodMap.get(method);
}
public void mapLocalAnonTypeToMethod(ClassType anonLocalType, CodeInstance owningProc) {
fLocalTypeMap.put(anonLocalType, owningProc);
}
/**
* Create a FieldReference for the given Polyglot FieldInstance.<br>
* N.B.: This method <b>does not canonicalize</b> the FieldReferences,
* but rather creates a new one for each call.
* You more likely want to call getFieldRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having FieldInstances collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public FieldReference referenceForField(FieldInstance field) {
Type targetType= field.container();
Type fieldType= field.type();
TypeReference targetTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(targetType));
TypeReference fieldTypeRef= TypeReference.findOrCreate(fClassLoaderRef, typeToTypeID(fieldType));
Atom fieldName= Atom.findOrCreateUnicodeAtom(field.name().toString());
FieldReference fieldRef= FieldReference.findOrCreate(targetTypeRef, fieldName, fieldTypeRef);
return fieldRef;
}
/**
* Create a TypeReference for the given Polyglot Type.<br>
* N.B.: This method <b>does not canonicalize</b> the TypeReferences,
* but rather creates a new one for each call.
* You more likely want to call getTypeRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having Types collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public TypeReference referenceForType(Type type) {
TypeName typeName= TypeName.string2TypeName(typeToTypeID(type));
TypeReference typeRef= TypeReference.findOrCreate(fClassLoaderRef, typeName);
return typeRef;
}
private Selector selectorForMethod(CodeInstance procInstance) {
Atom name=
(procInstance instanceof ConstructorInstance) ?
MethodReference.initAtom :
(procInstance instanceof InitializerInstance) ?
MethodReference.clinitName :
Atom.findOrCreateUnicodeAtom(((MethodInstance) procInstance).name().toString());
TypeName[] argTypeNames = null;
if (! (procInstance instanceof InitializerInstance)) {
List formalTypes = ((ProcedureInstance)procInstance).formalTypes();
int numArgs = formalTypes.size();
// Descriptor prefers null to an empty array
if (numArgs > 0) {
argTypeNames = new TypeName[numArgs];
int i = 0;
for(Iterator iter = formalTypes.iterator(); iter.hasNext(); i++) {
Type argType= (Type) iter.next();
argTypeNames[i]= TypeName.string2TypeName(typeToTypeID(argType));
}
}
}
Type retType=
(procInstance instanceof MethodInstance) ? ((MethodInstance) procInstance).returnType() : procInstance.typeSystem().Void();
TypeName retTypeName= TypeName.string2TypeName(typeToTypeID(retType));
Descriptor desc= Descriptor.findOrCreate(argTypeNames, retTypeName);
return new Selector(name, desc);
}
/**
* Create a MethodReference for the given Polyglot MethodInstance.<br>
* N.B.: This method <b>does not canonicalize</b> the MethodReferences,
* but rather creates a new one for each call.
* You more likely want to call getMethodRef(). This method is exposed
* so that multiple Polyglot instances can use the translation services
* without having MethodInstances collide (producing the dreaded "we are
* TypeSystem_c but type Foo is from TypeSystem_c" exception).
*/
public MethodReference referenceForMethod(CodeInstance procInstance) {
// Handles both ConstructorInstance's and MethodInstance's
TypeName ownerType= TypeName.string2TypeName(typeToTypeID(((MemberDef) procInstance.def()).container().get()));
TypeReference ownerTypeRef= TypeReference.findOrCreate(fClassLoaderRef, ownerType);
MethodReference methodRef= MethodReference.findOrCreate(ownerTypeRef, selectorForMethod(procInstance));
return methodRef;
}
/**
* Translates the given Polyglot type to a name suitable for use in a WALA TypeReference
* (i.e. a bytecode-compliant type name).
*/
public String typeToTypeID(Type type) {
if (type.isPrimitive()) {
PrimitiveType ptype= (PrimitiveType) type;
return JavaPrimitiveTypeMap.getShortName(ptype.name().toString());
} else if (type.isArray()) {
ArrayType atype= (ArrayType) type;
return "[" + typeToTypeID(atype.base());
} else if (type.isNull()) {
Assertions.UNREACHABLE("typeToTypeID() encountered a null type!");
return null;
}
Assertions.productionAssertion(type.isClass(), "typeToTypeID() encountered the type " + type + " that is neither primitive, array, nor class!");
ClassType ctype= (ClassType) type;
return (ctype.isLocal() || ctype.isAnonymous()) ? anonLocalTypeToTypeID(ctype) : composeWALATypeDescriptor(ctype);
}
public String anonLocalTypeToTypeID(ClassType ctype) {
CodeInstance procInstance= (CodeInstance) fLocalTypeMap.get(ctype);
String outerTypeID= typeToTypeID(ctype.outer());
String shortName= (ctype.isAnonymous()) ? PolyglotJava2CAstTranslator.anonTypeName(ctype) : ctype.fullName().name().toString();
return outerTypeID + '/' + getMethodRef(procInstance).getSelector() + '/' + shortName;
}
public String composeWALATypeDescriptor(ClassType ctype) {
return "L" + composeWALATypeName(ctype);
}
public String composeWALATypeName(ClassType ctype) {
if (ctype.package_() != null) {
String packageName = ctype.package_().fullName().toString();
Assertions.productionAssertion(ctype.fullName().toString().startsWith(packageName));
return packageName.replace('.','/') + "/" + ctype.fullName().toString().substring( packageName.length()+1 ).replace('.','$');
} else {
return ctype.fullName().toString().replace('.', '$');
}
}
}

View File

@ -1,447 +1,447 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
/*
* Created on Oct 3, 2005
*/
package com.ibm.wala.cast.java.test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
import org.junit.Assert;
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
import com.ibm.wala.cast.loader.AstClass;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.JarFileModule;
import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.properties.WalaProperties;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
public abstract class IRTests {
protected IRTests(String projectName) {
this.projectName = projectName;
}
protected final String projectName;
protected static String javaHomePath;
private String testSrcPath = "." + File.separator + "src";
public static List<String> rtJar;
protected static List<IRAssertion> emptyList = Collections.emptyList();
static {
boolean found = false;
try {
rtJar = new LinkedList<String>();
Properties p = WalaProperties.loadProperties();
javaHomePath = p.getProperty(WalaProperties.J2SE_DIR);
if (new File(javaHomePath).isDirectory()) {
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
/**
* todo: {@link WalaProperties#getJ2SEJarFiles()}
*/
rtJar.add(javaHomePath + "/classes.jar");
rtJar.add(javaHomePath + "/ui.jar");
} else {
rtJar.add(javaHomePath + File.separator + "classes.jar");
rtJar.add(javaHomePath + File.separator + "rt.jar");
rtJar.add(javaHomePath + File.separator + "core.jar");
rtJar.add(javaHomePath + File.separator + "vm.jar");
}
found = true;
}
} catch (Exception e) {
// no properties
}
if (!found) {
javaHomePath = System.getProperty("java.home");
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
rtJar.add(javaHomePath + "/../Classes/classes.jar");
rtJar.add(javaHomePath + "/../Classes/ui.jar");
} else {
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "rt.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "core.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "vm.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "classes.jar");
}
}
}
public interface IRAssertion {
void check(CallGraph cg);
}
protected static class EdgeAssertions implements IRAssertion {
public final String srcDescriptor;
public final List/* <String> */<String> tgtDescriptors = new ArrayList<String>();
public EdgeAssertions(String srcDescriptor) {
this.srcDescriptor = srcDescriptor;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
ea.tgtDescriptors.add(tgtDescriptor3);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3,
String tgtDescriptor4) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
ea.tgtDescriptors.add(tgtDescriptor3);
ea.tgtDescriptors.add(tgtDescriptor4);
return ea;
}
public void check(CallGraph callGraph) {
MethodReference srcMethod = descriptorToMethodRef(this.srcDescriptor, callGraph.getClassHierarchy());
Set<CGNode> srcNodes = callGraph.getNodes(srcMethod);
if (srcNodes.size() == 0) {
System.err.println(("Unreachable/non-existent method: " + srcMethod));
return;
}
if (srcNodes.size() > 1) {
System.err.println("Context-sensitive call graph?");
}
// Assume only one node for src method
CGNode srcNode = srcNodes.iterator().next();
for (String target : this.tgtDescriptors) {
MethodReference tgtMethod = descriptorToMethodRef(target, callGraph.getClassHierarchy());
// Assume only one node for target method
Set<CGNode> tgtNodes = callGraph.getNodes(tgtMethod);
if (tgtNodes.size() == 0) {
System.err.println(("Unreachable/non-existent method: " + tgtMethod));
continue;
}
CGNode tgtNode = tgtNodes.iterator().next();
boolean found = false;
for (Iterator<? extends CGNode> succIter = callGraph.getSuccNodes(srcNode); succIter.hasNext();) {
CGNode succ = succIter.next();
if (tgtNode == succ) {
found = true;
break;
}
}
if (!found) {
System.err.println(("Missing edge: " + srcMethod + " -> " + tgtMethod));
}
}
}
}
protected static class SourceMapAssertion implements IRAssertion {
private final String method;
private final String variableName;
private final int definingLineNumber;
protected SourceMapAssertion(String method, String variableName, int definingLineNumber) {
this.method = method;
this.variableName = variableName;
this.definingLineNumber = definingLineNumber;
}
public void check(CallGraph cg) {
MethodReference mref = descriptorToMethodRef(method, cg.getClassHierarchy());
for (CGNode cgNode : cg.getNodes(mref)) {
Assert.assertTrue("failed for " + this.variableName + " in " + cgNode, this.check(cgNode.getMethod(), cgNode.getIR()));
}
}
boolean check(IMethod m, IR ir) {
System.err.println(("check for " + variableName + " defined at " + definingLineNumber));
SSAInstruction[] insts = ir.getInstructions();
for (int i = 0; i < insts.length; i++) {
if (insts[i] != null) {
int ln = m.getLineNumber(i);
if (ln == definingLineNumber) {
System.err.println((" found " + insts[i] + " at " + ln));
for (int j = 0; j < insts[i].getNumberOfDefs(); j++) {
int def = insts[i].getDef(j);
System.err.println((" looking at def " + j + ": " + def));
String[] names = ir.getLocalNames(i, def);
if (names != null) {
for (String name : names) {
System.err.println((" looking at name " + name));
if (name.equals(variableName)) {
return true;
}
}
}
}
}
}
}
return false;
}
}
protected Collection<String> singleTestSrc() {
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
}
protected Collection<String> singleTestSrc(final String folder) {
return Collections.singletonList(getTestSrcPath() + File.separator + folder + File.separator + singleJavaInputForTest());
}
protected Collection<String> singlePkgTestSrc(String pkgName) {
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaPkgInputForTest(pkgName));
}
protected String getTestName() {
StackTraceElement stack[] = new Throwable().getStackTrace();
for(int i = 0; i <= stack.length; i++) {
if (stack[i].getMethodName().startsWith("test")) {
return stack[i].getMethodName();
}
}
throw new Error("test method not found");
}
protected String[] simpleTestEntryPoint() {
return new String[] { "L" + getTestName().substring(4) };
}
protected String[] simplePkgTestEntryPoint(String pkgName) {
return new String[] { "L" + pkgName + "/" + getTestName().substring(4) };
}
protected abstract AbstractAnalysisEngine getAnalysisEngine(String[] mainClassDescriptors, Collection<String> sources, List<String> libs);
public Pair runTest(Collection<String> sources, List<String> libs, String[] mainClassDescriptors, List<? extends IRAssertion> ca,
boolean assertReachable) {
AbstractAnalysisEngine engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
CallGraph callGraph;
try {
callGraph = engine.buildDefaultCallGraph();
System.err.println(callGraph.toString());
// If we've gotten this far, IR has been produced.
dumpIR(callGraph, sources, assertReachable);
// Now check any assertions as to source mapping
for (IRAssertion IRAssertion : ca) {
IRAssertion.check(callGraph);
}
return Pair.make(callGraph, engine.getPointerAnalysis());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CancelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected static void dumpIR(CallGraph cg, Collection<String> sources, boolean assertReachable) throws IOException {
Set<String> sourcePaths = HashSetFactory.make();
for(String src : sources) {
sourcePaths.add(src.substring(src.lastIndexOf(File.separator)+1));
}
Set<IMethod> unreachable = HashSetFactory.make();
IClassHierarchy cha = cg.getClassHierarchy();
IClassLoader sourceLoader = cha.getLoader(JavaSourceAnalysisScope.SOURCE);
for (Iterator iter = sourceLoader.iterateAllClasses(); iter.hasNext();) {
IClass clazz = (IClass) iter.next();
System.err.println(clazz);
if (clazz.isInterface())
continue;
for (IMethod m : clazz.getDeclaredMethods()) {
if (m.isAbstract()) {
System.err.println(m);
} else {
Iterator nodeIter = cg.getNodes(m.getReference()).iterator();
if (!nodeIter.hasNext()) {
if (m instanceof AstMethod) {
String fn = ((AstClass)m.getDeclaringClass()).getSourcePosition().getURL().getFile();
if (sourcePaths.contains(fn.substring(fn.lastIndexOf(File.separator)+1))) {
System.err.println(("Method " + m.getReference() + " not reachable?"));
unreachable.add(m);
}
}
continue;
}
CGNode node = (CGNode) nodeIter.next();
System.err.println(node.getIR());
}
}
}
if (assertReachable) {
Assert.assertTrue("unreachable methods: " + unreachable.toString(), unreachable.isEmpty());
}
}
/**
*
* @param srcMethodDescriptor a full method descriptor of the form ldr#type#methName#methSig example:
* Source#Simple1#main#([Ljava/lang/String;)V
* @param cha
* @return
*/
public static MethodReference descriptorToMethodRef(String srcMethodDescriptor, IClassHierarchy cha) {
String[] ldrTypeMeth = srcMethodDescriptor.split("\\#");
String loaderName = ldrTypeMeth[0];
String typeStr = ldrTypeMeth[1];
String methName = ldrTypeMeth[2];
String methSig = ldrTypeMeth[3];
TypeReference typeRef = findOrCreateTypeReference(loaderName, typeStr, cha);
Language l = cha.getLoader(typeRef.getClassLoader()).getLanguage();
return MethodReference.findOrCreate(l, typeRef, methName, methSig);
}
static TypeReference findOrCreateTypeReference(String loaderName, String typeStr, IClassHierarchy cha) {
ClassLoaderReference clr = findLoader(loaderName, cha);
TypeName typeName = TypeName.string2TypeName("L" + typeStr);
TypeReference typeRef = TypeReference.findOrCreate(clr, typeName);
return typeRef;
}
private static ClassLoaderReference findLoader(String loaderName, IClassHierarchy cha) {
Atom loaderAtom = Atom.findOrCreateUnicodeAtom(loaderName);
IClassLoader[] loaders = cha.getLoaders();
for (IClassLoader loader : loaders) {
if (loader.getName() == loaderAtom) {
return loader.getReference();
}
}
Assertions.UNREACHABLE();
return null;
}
protected void populateScope(JavaSourceAnalysisEngine engine, Collection<String> sources, List<String> libs) {
boolean foundLib = false;
for (String lib : libs) {
File libFile = new File(lib);
if (libFile.exists()) {
foundLib = true;
try {
engine.addSystemModule(new JarFileModule(new JarFile(libFile)));
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}
assert foundLib : "couldn't find library file from " + libs;
for (String srcFilePath : sources) {
String srcFileName = srcFilePath.substring(srcFilePath.lastIndexOf(File.separator) + 1);
File f = new File(srcFilePath);
Assert.assertTrue("couldn't find " + srcFilePath, f.exists());
if (f.isDirectory()) {
engine.addSourceModule(new SourceDirectoryTreeModule(f));
} else {
engine.addSourceModule(new SourceFileModule(f, srcFileName));
}
}
}
protected void setTestSrcPath(String testSrcPath) {
this.testSrcPath = testSrcPath;
}
protected String getTestSrcPath() {
return testSrcPath;
}
protected String singleJavaInputForTest() {
return getTestName().substring(4) + ".java";
}
protected String singleInputForTest() {
return getTestName().substring(4);
}
protected String singleJavaPkgInputForTest(String pkgName) {
return pkgName + File.separator + getTestName().substring(4) + ".java";
}
}
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
/*
* Created on Oct 3, 2005
*/
package com.ibm.wala.cast.java.test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
import org.junit.Assert;
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
import com.ibm.wala.cast.loader.AstClass;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.JarFileModule;
import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.properties.WalaProperties;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
public abstract class IRTests {
protected IRTests(String projectName) {
this.projectName = projectName;
}
protected final String projectName;
protected static String javaHomePath;
private String testSrcPath = "." + File.separator + "src";
public static List<String> rtJar;
protected static List<IRAssertion> emptyList = Collections.emptyList();
static {
boolean found = false;
try {
rtJar = new LinkedList<String>();
Properties p = WalaProperties.loadProperties();
javaHomePath = p.getProperty(WalaProperties.J2SE_DIR);
if (new File(javaHomePath).isDirectory()) {
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
/**
* todo: {@link WalaProperties#getJ2SEJarFiles()}
*/
rtJar.add(javaHomePath + "/classes.jar");
rtJar.add(javaHomePath + "/ui.jar");
} else {
rtJar.add(javaHomePath + File.separator + "classes.jar");
rtJar.add(javaHomePath + File.separator + "rt.jar");
rtJar.add(javaHomePath + File.separator + "core.jar");
rtJar.add(javaHomePath + File.separator + "vm.jar");
}
found = true;
}
} catch (Exception e) {
// no properties
}
if (!found) {
javaHomePath = System.getProperty("java.home");
if ("Mac OS X".equals(System.getProperty("os.name"))) { // nick
rtJar.add(javaHomePath + "/../Classes/classes.jar");
rtJar.add(javaHomePath + "/../Classes/ui.jar");
} else {
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "rt.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "core.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "vm.jar");
rtJar.add(javaHomePath + File.separator + "lib" + File.separator + "classes.jar");
}
}
}
public interface IRAssertion {
void check(CallGraph cg);
}
protected static class EdgeAssertions implements IRAssertion {
public final String srcDescriptor;
public final List/* <String> */<String> tgtDescriptors = new ArrayList<String>();
public EdgeAssertions(String srcDescriptor) {
this.srcDescriptor = srcDescriptor;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
ea.tgtDescriptors.add(tgtDescriptor3);
return ea;
}
public static EdgeAssertions make(String srcDescriptor, String tgtDescriptor1, String tgtDescriptor2, String tgtDescriptor3,
String tgtDescriptor4) {
EdgeAssertions ea = new EdgeAssertions(srcDescriptor);
ea.tgtDescriptors.add(tgtDescriptor1);
ea.tgtDescriptors.add(tgtDescriptor2);
ea.tgtDescriptors.add(tgtDescriptor3);
ea.tgtDescriptors.add(tgtDescriptor4);
return ea;
}
public void check(CallGraph callGraph) {
MethodReference srcMethod = descriptorToMethodRef(this.srcDescriptor, callGraph.getClassHierarchy());
Set<CGNode> srcNodes = callGraph.getNodes(srcMethod);
if (srcNodes.size() == 0) {
System.err.println(("Unreachable/non-existent method: " + srcMethod));
return;
}
if (srcNodes.size() > 1) {
System.err.println("Context-sensitive call graph?");
}
// Assume only one node for src method
CGNode srcNode = srcNodes.iterator().next();
for (String target : this.tgtDescriptors) {
MethodReference tgtMethod = descriptorToMethodRef(target, callGraph.getClassHierarchy());
// Assume only one node for target method
Set<CGNode> tgtNodes = callGraph.getNodes(tgtMethod);
if (tgtNodes.size() == 0) {
System.err.println(("Unreachable/non-existent method: " + tgtMethod));
continue;
}
CGNode tgtNode = tgtNodes.iterator().next();
boolean found = false;
for (Iterator<? extends CGNode> succIter = callGraph.getSuccNodes(srcNode); succIter.hasNext();) {
CGNode succ = succIter.next();
if (tgtNode == succ) {
found = true;
break;
}
}
if (!found) {
System.err.println(("Missing edge: " + srcMethod + " -> " + tgtMethod));
}
}
}
}
protected static class SourceMapAssertion implements IRAssertion {
private final String method;
private final String variableName;
private final int definingLineNumber;
protected SourceMapAssertion(String method, String variableName, int definingLineNumber) {
this.method = method;
this.variableName = variableName;
this.definingLineNumber = definingLineNumber;
}
public void check(CallGraph cg) {
MethodReference mref = descriptorToMethodRef(method, cg.getClassHierarchy());
for (CGNode cgNode : cg.getNodes(mref)) {
Assert.assertTrue("failed for " + this.variableName + " in " + cgNode, this.check(cgNode.getMethod(), cgNode.getIR()));
}
}
boolean check(IMethod m, IR ir) {
System.err.println(("check for " + variableName + " defined at " + definingLineNumber));
SSAInstruction[] insts = ir.getInstructions();
for (int i = 0; i < insts.length; i++) {
if (insts[i] != null) {
int ln = m.getLineNumber(i);
if (ln == definingLineNumber) {
System.err.println((" found " + insts[i] + " at " + ln));
for (int j = 0; j < insts[i].getNumberOfDefs(); j++) {
int def = insts[i].getDef(j);
System.err.println((" looking at def " + j + ": " + def));
String[] names = ir.getLocalNames(i, def);
if (names != null) {
for (String name : names) {
System.err.println((" looking at name " + name));
if (name.equals(variableName)) {
return true;
}
}
}
}
}
}
}
return false;
}
}
protected Collection<String> singleTestSrc() {
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaInputForTest());
}
protected Collection<String> singleTestSrc(final String folder) {
return Collections.singletonList(getTestSrcPath() + File.separator + folder + File.separator + singleJavaInputForTest());
}
protected Collection<String> singlePkgTestSrc(String pkgName) {
return Collections.singletonList(getTestSrcPath() + File.separator + singleJavaPkgInputForTest(pkgName));
}
protected String getTestName() {
StackTraceElement stack[] = new Throwable().getStackTrace();
for(int i = 0; i <= stack.length; i++) {
if (stack[i].getMethodName().startsWith("test")) {
return stack[i].getMethodName();
}
}
throw new Error("test method not found");
}
protected String[] simpleTestEntryPoint() {
return new String[] { "L" + getTestName().substring(4) };
}
protected String[] simplePkgTestEntryPoint(String pkgName) {
return new String[] { "L" + pkgName + "/" + getTestName().substring(4) };
}
protected abstract AbstractAnalysisEngine getAnalysisEngine(String[] mainClassDescriptors, Collection<String> sources, List<String> libs);
public Pair runTest(Collection<String> sources, List<String> libs, String[] mainClassDescriptors, List<? extends IRAssertion> ca,
boolean assertReachable) {
AbstractAnalysisEngine engine = getAnalysisEngine(mainClassDescriptors, sources, libs);
CallGraph callGraph;
try {
callGraph = engine.buildDefaultCallGraph();
System.err.println(callGraph.toString());
// If we've gotten this far, IR has been produced.
dumpIR(callGraph, sources, assertReachable);
// Now check any assertions as to source mapping
for (IRAssertion IRAssertion : ca) {
IRAssertion.check(callGraph);
}
return Pair.make(callGraph, engine.getPointerAnalysis());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CancelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected static void dumpIR(CallGraph cg, Collection<String> sources, boolean assertReachable) throws IOException {
Set<String> sourcePaths = HashSetFactory.make();
for(String src : sources) {
sourcePaths.add(src.substring(src.lastIndexOf(File.separator)+1));
}
Set<IMethod> unreachable = HashSetFactory.make();
IClassHierarchy cha = cg.getClassHierarchy();
IClassLoader sourceLoader = cha.getLoader(JavaSourceAnalysisScope.SOURCE);
for (Iterator iter = sourceLoader.iterateAllClasses(); iter.hasNext();) {
IClass clazz = (IClass) iter.next();
System.err.println(clazz);
if (clazz.isInterface())
continue;
for (IMethod m : clazz.getDeclaredMethods()) {
if (m.isAbstract()) {
System.err.println(m);
} else {
Iterator nodeIter = cg.getNodes(m.getReference()).iterator();
if (!nodeIter.hasNext()) {
if (m instanceof AstMethod) {
String fn = ((AstClass)m.getDeclaringClass()).getSourcePosition().getURL().getFile();
if (sourcePaths.contains(fn.substring(fn.lastIndexOf(File.separator)+1))) {
System.err.println(("Method " + m.getReference() + " not reachable?"));
unreachable.add(m);
}
}
continue;
}
CGNode node = (CGNode) nodeIter.next();
System.err.println(node.getIR());
}
}
}
if (assertReachable) {
Assert.assertTrue("unreachable methods: " + unreachable.toString(), unreachable.isEmpty());
}
}
/**
*
* @param srcMethodDescriptor a full method descriptor of the form ldr#type#methName#methSig example:
* Source#Simple1#main#([Ljava/lang/String;)V
* @param cha
* @return
*/
public static MethodReference descriptorToMethodRef(String srcMethodDescriptor, IClassHierarchy cha) {
String[] ldrTypeMeth = srcMethodDescriptor.split("\\#");
String loaderName = ldrTypeMeth[0];
String typeStr = ldrTypeMeth[1];
String methName = ldrTypeMeth[2];
String methSig = ldrTypeMeth[3];
TypeReference typeRef = findOrCreateTypeReference(loaderName, typeStr, cha);
Language l = cha.getLoader(typeRef.getClassLoader()).getLanguage();
return MethodReference.findOrCreate(l, typeRef, methName, methSig);
}
static TypeReference findOrCreateTypeReference(String loaderName, String typeStr, IClassHierarchy cha) {
ClassLoaderReference clr = findLoader(loaderName, cha);
TypeName typeName = TypeName.string2TypeName("L" + typeStr);
TypeReference typeRef = TypeReference.findOrCreate(clr, typeName);
return typeRef;
}
private static ClassLoaderReference findLoader(String loaderName, IClassHierarchy cha) {
Atom loaderAtom = Atom.findOrCreateUnicodeAtom(loaderName);
IClassLoader[] loaders = cha.getLoaders();
for (IClassLoader loader : loaders) {
if (loader.getName() == loaderAtom) {
return loader.getReference();
}
}
Assertions.UNREACHABLE();
return null;
}
protected void populateScope(JavaSourceAnalysisEngine engine, Collection<String> sources, List<String> libs) {
boolean foundLib = false;
for (String lib : libs) {
File libFile = new File(lib);
if (libFile.exists()) {
foundLib = true;
try {
engine.addSystemModule(new JarFileModule(new JarFile(libFile)));
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}
assert foundLib : "couldn't find library file from " + libs;
for (String srcFilePath : sources) {
String srcFileName = srcFilePath.substring(srcFilePath.lastIndexOf(File.separator) + 1);
File f = new File(srcFilePath);
Assert.assertTrue("couldn't find " + srcFilePath, f.exists());
if (f.isDirectory()) {
engine.addSourceModule(new SourceDirectoryTreeModule(f));
} else {
engine.addSourceModule(new SourceFileModule(f, srcFileName));
}
}
}
protected void setTestSrcPath(String testSrcPath) {
this.testSrcPath = testSrcPath;
}
protected String getTestSrcPath() {
return testSrcPath;
}
protected String singleJavaInputForTest() {
return getTestName().substring(4) + ".java";
}
protected String singleInputForTest() {
return getTestName().substring(4);
}
protected String singleJavaPkgInputForTest(String pkgName) {
return pkgName + File.separator + getTestName().substring(4) + ".java";
}
}

View File

@ -1,165 +1,165 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.java.client;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.config.FileOfClasses;
/**
*/
public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
/**
* Modules which are user-space code
*/
private final Set<Module> userEntries = HashSetFactory.make();
/**
* Modules which are source code
*/
private final Set<Module> sourceEntries = HashSetFactory.make();
/**
* Modules which are system or library code TODO: what about extension loader?
*/
private final Set<Module> systemEntries = HashSetFactory.make();
public JavaSourceAnalysisEngine() {
super();
}
/**
* Adds the given source module to the source loader's module list. Clients
* should/may call this method if they don't supply an IJavaProject to the
* constructor.
*/
public void addSourceModule(Module M) {
sourceEntries.add(M);
}
/**
* Adds the given compiled module to the application loader's module list.
* Clients should/may call this method if they don't supply an IJavaProject to
* the constructor.
*/
public void addCompiledModule(Module M) {
userEntries.add(M);
}
/**
* Adds the given module to the primordial loader's module list. Clients
* should/may call this method if they don't supply an IJavaProject to the
* constructor.
*/
public void addSystemModule(Module M) {
systemEntries.add(M);
}
protected void addApplicationModulesToScope() {
ClassLoaderReference app = scope.getApplicationLoader();
for (Module M : userEntries) {
scope.addToScope(app, M);
}
ClassLoaderReference src = ((JavaSourceAnalysisScope) scope).getSourceLoader();
for (Module M : sourceEntries) {
scope.addToScope(src, M);
}
}
public void buildAnalysisScope() throws IOException {
scope = makeSourceAnalysisScope();
if (getExclusionsFile() != null) {
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
}
for (Module M : this.systemEntries) {
scope.addToScope(scope.getPrimordialLoader(), M);
}
// add user stuff
addApplicationModulesToScope();
}
protected AnalysisScope makeSourceAnalysisScope() {
return new JavaSourceAnalysisScope();
}
protected abstract ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions);
public IClassHierarchy buildClassHierarchy() {
IClassHierarchy cha = null;
ClassLoaderFactory factory = getClassLoaderFactory(scope.getExclusions());
try {
cha = ClassHierarchy.make(getScope(), factory);
} catch (ClassHierarchyException e) {
System.err.println("Class Hierarchy construction failed");
System.err.println(e.toString());
e.printStackTrace();
}
return cha;
}
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE, cha);
}
@Override
public AnalysisCache makeDefaultCache() {
return new AnalysisCache(AstIRFactory.makeDefaultFactory());
}
public AnalysisOptions getDefaultOptions(Iterable<Entrypoint> entrypoints) {
AnalysisOptions options = new AnalysisOptions(getScope(), entrypoints);
SSAOptions ssaOptions = new SSAOptions();
ssaOptions.setDefaultValues(new SSAOptions.DefaultValues() {
public int getDefaultValue(SymbolTable symtab, int valueNumber) {
return symtab.getDefaultValue(valueNumber);
}
});
options.setSSAOptions(ssaOptions);
return options;
}
@Override
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
return new ZeroCFABuilderFactory().make(options, cache, cha, scope, false);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.java.client;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.config.FileOfClasses;
/**
*/
public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
/**
* Modules which are user-space code
*/
private final Set<Module> userEntries = HashSetFactory.make();
/**
* Modules which are source code
*/
private final Set<Module> sourceEntries = HashSetFactory.make();
/**
* Modules which are system or library code TODO: what about extension loader?
*/
private final Set<Module> systemEntries = HashSetFactory.make();
public JavaSourceAnalysisEngine() {
super();
}
/**
* Adds the given source module to the source loader's module list. Clients
* should/may call this method if they don't supply an IJavaProject to the
* constructor.
*/
public void addSourceModule(Module M) {
sourceEntries.add(M);
}
/**
* Adds the given compiled module to the application loader's module list.
* Clients should/may call this method if they don't supply an IJavaProject to
* the constructor.
*/
public void addCompiledModule(Module M) {
userEntries.add(M);
}
/**
* Adds the given module to the primordial loader's module list. Clients
* should/may call this method if they don't supply an IJavaProject to the
* constructor.
*/
public void addSystemModule(Module M) {
systemEntries.add(M);
}
protected void addApplicationModulesToScope() {
ClassLoaderReference app = scope.getApplicationLoader();
for (Module M : userEntries) {
scope.addToScope(app, M);
}
ClassLoaderReference src = ((JavaSourceAnalysisScope) scope).getSourceLoader();
for (Module M : sourceEntries) {
scope.addToScope(src, M);
}
}
public void buildAnalysisScope() throws IOException {
scope = makeSourceAnalysisScope();
if (getExclusionsFile() != null) {
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
}
for (Module M : this.systemEntries) {
scope.addToScope(scope.getPrimordialLoader(), M);
}
// add user stuff
addApplicationModulesToScope();
}
protected AnalysisScope makeSourceAnalysisScope() {
return new JavaSourceAnalysisScope();
}
protected abstract ClassLoaderFactory getClassLoaderFactory(SetOfClasses exclusions);
public IClassHierarchy buildClassHierarchy() {
IClassHierarchy cha = null;
ClassLoaderFactory factory = getClassLoaderFactory(scope.getExclusions());
try {
cha = ClassHierarchy.make(getScope(), factory);
} catch (ClassHierarchyException e) {
System.err.println("Class Hierarchy construction failed");
System.err.println(e.toString());
e.printStackTrace();
}
return cha;
}
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE, cha);
}
@Override
public AnalysisCache makeDefaultCache() {
return new AnalysisCache(AstIRFactory.makeDefaultFactory());
}
public AnalysisOptions getDefaultOptions(Iterable<Entrypoint> entrypoints) {
AnalysisOptions options = new AnalysisOptions(getScope(), entrypoints);
SSAOptions ssaOptions = new SSAOptions();
ssaOptions.setDefaultValues(new SSAOptions.DefaultValues() {
public int getDefaultValue(SymbolTable symtab, int valueNumber) {
return symtab.getDefaultValue(valueNumber);
}
});
options.setSSAOptions(ssaOptions);
return options;
}
@Override
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
return new ZeroCFABuilderFactory().make(options, cache, cha, scope, false);
}
}

View File

@ -1,75 +1,75 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.cast.java.ipa.callgraph;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector;
import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContainerContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.IClassHierarchy;
/**
*
* 0-1-CFA Call graph builder which analyzes calls to "container methods" in a context which is defined by the receiver
* instance.
*
* @author sfink
*/
public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder {
/**
* @param cha governing class hierarchy
* @param warnings object to track analysis warnings
* @param options call graph construction options
* @param appContextSelector application-specific logic to choose contexts
* @param appContextInterpreter application-specific logic to interpret a method in context
* @param reflect reflection specification
*/
public AstJavaZeroOneContainerCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter) {
super(cha, options, cache);
ContextSelector def = new DefaultContextSelector(options, cha);
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
setContextInterpreter(contextInterpreter);
ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter);
setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik));
ContextSelector CCS = makeContainerContextSelector(cha, zik);
DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector);
setContextSelector(DCS);
}
protected ZeroXInstanceKeys makeInstanceKeys(IClassHierarchy cha, AnalysisOptions options,
SSAContextInterpreter contextInterpreter) {
ZeroXInstanceKeys zik = new ZeroXInstanceKeys(options, cha, contextInterpreter, ZeroXInstanceKeys.ALLOCATIONS
| ZeroXInstanceKeys.SMUSH_PRIMITIVE_HOLDERS | ZeroXInstanceKeys.SMUSH_STRINGS | ZeroXInstanceKeys.SMUSH_MANY
| ZeroXInstanceKeys.SMUSH_THROWABLES);
return zik;
}
/**
* @param cha
* @param keys
* @return an object which creates contexts for call graph nodes based on the container disambiguation policy
*/
protected ContextSelector makeContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys keys) {
return new ContainerContextSelector(cha, keys);
}
}
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.cast.java.ipa.callgraph;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector;
import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContainerContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.IClassHierarchy;
/**
*
* 0-1-CFA Call graph builder which analyzes calls to "container methods" in a context which is defined by the receiver
* instance.
*
* @author sfink
*/
public class AstJavaZeroOneContainerCFABuilder extends AstJavaCFABuilder {
/**
* @param cha governing class hierarchy
* @param warnings object to track analysis warnings
* @param options call graph construction options
* @param appContextSelector application-specific logic to choose contexts
* @param appContextInterpreter application-specific logic to interpret a method in context
* @param reflect reflection specification
*/
public AstJavaZeroOneContainerCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter) {
super(cha, options, cache);
ContextSelector def = new DefaultContextSelector(options, cha);
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
setContextInterpreter(contextInterpreter);
ZeroXInstanceKeys zik = makeInstanceKeys(cha, options, contextInterpreter);
setInstanceKeys(new JavaScopeMappingInstanceKeys(cha, this, zik));
ContextSelector CCS = makeContainerContextSelector(cha, zik);
DelegatingContextSelector DCS = new DelegatingContextSelector(CCS, contextSelector);
setContextSelector(DCS);
}
protected ZeroXInstanceKeys makeInstanceKeys(IClassHierarchy cha, AnalysisOptions options,
SSAContextInterpreter contextInterpreter) {
ZeroXInstanceKeys zik = new ZeroXInstanceKeys(options, cha, contextInterpreter, ZeroXInstanceKeys.ALLOCATIONS
| ZeroXInstanceKeys.SMUSH_PRIMITIVE_HOLDERS | ZeroXInstanceKeys.SMUSH_STRINGS | ZeroXInstanceKeys.SMUSH_MANY
| ZeroXInstanceKeys.SMUSH_THROWABLES);
return zik;
}
/**
* @param cha
* @param keys
* @return an object which creates contexts for call graph nodes based on the container disambiguation policy
*/
protected ContextSelector makeContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys keys) {
return new ContainerContextSelector(cha, keys);
}
}

View File

@ -1,115 +1,115 @@
package com.ibm.wala.cast.java.ipa.slicer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
import com.ibm.wala.cast.java.ipa.modref.AstJavaModRef;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.impl.PartialCallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.slicer.NormalStatement;
import com.ibm.wala.ipa.slicer.SDG;
import com.ibm.wala.ipa.slicer.Slicer;
import com.ibm.wala.ipa.slicer.Statement;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAMonitorInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.graph.traverse.DFS;
@SuppressWarnings("deprecation")
public class AstJavaSlicer extends Slicer {
/*
* Use the passed-in SDG
*/
public static Collection<Statement> computeBackwardSlice(SDG sdg, Collection<Statement> ss) throws IllegalArgumentException,
CancelException {
return computeSlice(sdg, ss, true);
}
/**
* @param ss a collection of statements of interest
* @throws CancelException
*/
public static Collection<Statement> computeSlice(SDG sdg, Collection<Statement> ss, boolean backward) throws CancelException {
return new AstJavaSlicer().slice(sdg, ss, backward);
}
public static Set<Statement> gatherStatements(CallGraph CG, Collection<CGNode> partialRoots, Filter<SSAInstruction> filter) {
Set<Statement> result = new HashSet<Statement>();
for (Iterator<CGNode> ns = DFS.getReachableNodes(CG, partialRoots).iterator(); ns.hasNext();) {
CGNode n = ns.next();
IR nir = n.getIR();
if (nir != null) {
SSAInstruction insts[] = nir.getInstructions();
for (int i = 0; i < insts.length; i++) {
if (filter.accepts(insts[i])) {
result.add(new NormalStatement(n, i));
}
}
}
}
return result;
}
public static Set<Statement> gatherAssertions(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return o instanceof AstAssertInstruction;
}
});
}
public static Set<Statement> gatherMonitors(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return o instanceof SSAMonitorInstruction;
}
});
}
public static Set<Statement> gatherWrites(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return (o instanceof SSAPutInstruction) || (o instanceof SSAArrayStoreInstruction);
}
});
}
public static Set<Statement> gatherReads(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return (o instanceof SSAGetInstruction) || (o instanceof SSAArrayLoadInstruction);
}
});
}
public static Pair<Collection<Statement>, SDG> computeAssertionSlice(CallGraph CG, PointerAnalysis pa,
Collection<CGNode> partialRoots, boolean multiThreadedCode) throws IllegalArgumentException, CancelException {
CallGraph pcg = PartialCallGraph.make(CG, new LinkedHashSet<CGNode>(partialRoots));
SDG sdg = new SDG(pcg, pa, new AstJavaModRef(), DataDependenceOptions.FULL, ControlDependenceOptions.FULL);
System.err.println(("SDG:\n" + sdg));
Set<Statement> stmts = gatherAssertions(CG, partialRoots);
if (multiThreadedCode) {
// Grab anything that has "side effects" under JMM
stmts.addAll(gatherReads(CG, partialRoots));
stmts.addAll(gatherWrites(CG, partialRoots));
stmts.addAll(gatherMonitors(CG, partialRoots));
}
return Pair.make(AstJavaSlicer.computeBackwardSlice(sdg, stmts), sdg);
}
}
package com.ibm.wala.cast.java.ipa.slicer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
import com.ibm.wala.cast.java.ipa.modref.AstJavaModRef;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.impl.PartialCallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.slicer.NormalStatement;
import com.ibm.wala.ipa.slicer.SDG;
import com.ibm.wala.ipa.slicer.Slicer;
import com.ibm.wala.ipa.slicer.Statement;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAMonitorInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.graph.traverse.DFS;
@SuppressWarnings("deprecation")
public class AstJavaSlicer extends Slicer {
/*
* Use the passed-in SDG
*/
public static Collection<Statement> computeBackwardSlice(SDG sdg, Collection<Statement> ss) throws IllegalArgumentException,
CancelException {
return computeSlice(sdg, ss, true);
}
/**
* @param ss a collection of statements of interest
* @throws CancelException
*/
public static Collection<Statement> computeSlice(SDG sdg, Collection<Statement> ss, boolean backward) throws CancelException {
return new AstJavaSlicer().slice(sdg, ss, backward);
}
public static Set<Statement> gatherStatements(CallGraph CG, Collection<CGNode> partialRoots, Filter<SSAInstruction> filter) {
Set<Statement> result = new HashSet<Statement>();
for (Iterator<CGNode> ns = DFS.getReachableNodes(CG, partialRoots).iterator(); ns.hasNext();) {
CGNode n = ns.next();
IR nir = n.getIR();
if (nir != null) {
SSAInstruction insts[] = nir.getInstructions();
for (int i = 0; i < insts.length; i++) {
if (filter.accepts(insts[i])) {
result.add(new NormalStatement(n, i));
}
}
}
}
return result;
}
public static Set<Statement> gatherAssertions(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return o instanceof AstAssertInstruction;
}
});
}
public static Set<Statement> gatherMonitors(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return o instanceof SSAMonitorInstruction;
}
});
}
public static Set<Statement> gatherWrites(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return (o instanceof SSAPutInstruction) || (o instanceof SSAArrayStoreInstruction);
}
});
}
public static Set<Statement> gatherReads(CallGraph CG, Collection<CGNode> partialRoots) {
return gatherStatements(CG, partialRoots, new Filter<SSAInstruction>() {
public boolean accepts(SSAInstruction o) {
return (o instanceof SSAGetInstruction) || (o instanceof SSAArrayLoadInstruction);
}
});
}
public static Pair<Collection<Statement>, SDG> computeAssertionSlice(CallGraph CG, PointerAnalysis pa,
Collection<CGNode> partialRoots, boolean multiThreadedCode) throws IllegalArgumentException, CancelException {
CallGraph pcg = PartialCallGraph.make(CG, new LinkedHashSet<CGNode>(partialRoots));
SDG sdg = new SDG(pcg, pa, new AstJavaModRef(), DataDependenceOptions.FULL, ControlDependenceOptions.FULL);
System.err.println(("SDG:\n" + sdg));
Set<Statement> stmts = gatherAssertions(CG, partialRoots);
if (multiThreadedCode) {
// Grab anything that has "side effects" under JMM
stmts.addAll(gatherReads(CG, partialRoots));
stmts.addAll(gatherWrites(CG, partialRoots));
stmts.addAll(gatherMonitors(CG, partialRoots));
}
return Pair.make(AstJavaSlicer.computeBackwardSlice(sdg, stmts), sdg);
}
}

View File

@ -1,74 +1,74 @@
package com.ibm.wala.cast.java.ssa;
import java.util.Collection;
import java.util.Collections;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
/**
* The CAst source language front end for Java has explicit support for lexically-enclosing objects, rather than compiling them
* away into extra fields and access-control thwarting accessor methods as is done in bytecode. This instruction represents a read
* of the object of the given type that lexically encloses its use value.
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public class EnclosingObjectReference extends SSAInstruction {
private final TypeReference type;
private final int lval;
public EnclosingObjectReference(int lval, TypeReference type) {
this.lval = lval;
this.type = type;
}
public boolean hasDef() {
return true;
}
public int getDef() {
return lval;
}
public int getDef(int i) {
assert i == 0;
return lval;
}
public int getNumberOfDefs() {
return 1;
}
public TypeReference getEnclosingType() {
return type;
}
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
return ((AstJavaInstructionFactory) insts).EnclosingObjectReference(defs == null ? lval : defs[0], type);
}
public String toString(SymbolTable symbolTable) {
return getValueString(symbolTable, lval) + " = enclosing " + type.getName();
}
public void visit(IVisitor v) {
((AstJavaInstructionVisitor) v).visitEnclosingObjectReference(this);
}
public int hashCode() {
return lval * type.hashCode();
}
public Collection<TypeReference> getExceptionTypes() {
return Collections.emptySet();
}
public boolean isFallThrough() {
return true;
}
}
package com.ibm.wala.cast.java.ssa;
import java.util.Collection;
import java.util.Collections;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
/**
* The CAst source language front end for Java has explicit support for lexically-enclosing objects, rather than compiling them
* away into extra fields and access-control thwarting accessor methods as is done in bytecode. This instruction represents a read
* of the object of the given type that lexically encloses its use value.
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public class EnclosingObjectReference extends SSAInstruction {
private final TypeReference type;
private final int lval;
public EnclosingObjectReference(int lval, TypeReference type) {
this.lval = lval;
this.type = type;
}
public boolean hasDef() {
return true;
}
public int getDef() {
return lval;
}
public int getDef(int i) {
assert i == 0;
return lval;
}
public int getNumberOfDefs() {
return 1;
}
public TypeReference getEnclosingType() {
return type;
}
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
return ((AstJavaInstructionFactory) insts).EnclosingObjectReference(defs == null ? lval : defs[0], type);
}
public String toString(SymbolTable symbolTable) {
return getValueString(symbolTable, lval) + " = enclosing " + type.getName();
}
public void visit(IVisitor v) {
((AstJavaInstructionVisitor) v).visitEnclosingObjectReference(this);
}
public int hashCode() {
return lval * type.hashCode();
}
public Collection<TypeReference> getExceptionTypes() {
return Collections.emptySet();
}
public boolean isFallThrough() {
return true;
}
}

View File

@ -1,71 +1,71 @@
package com.ibm.wala.cast.js.vis;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
import com.ibm.wala.cast.js.html.IdentityUrlResolver;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException;
public class JsViewerDriver extends JSCallGraphBuilderUtil {
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
if (args.length != 1){
System.out.println("Usage: <URL of html page to analyze>");
System.exit(1);
}
boolean domless = false;
URL url = new URL(args[0]);
// computing CG + PA
JSCallGraphBuilderUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
SourceModule[] sources = getSources(domless, url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, CGBuilderType.ZERO_ONE_CFA, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url);
CallGraph cg = builder.makeCallGraph(builder.getOptions());
PointerAnalysis pa = builder.getPointerAnalysis();
new JsViewer(cg, pa);
}
private static SourceModule[] getSources(boolean domless, URL url)
throws IOException {
JSSourceExtractor sourceExtractor;
if (domless ){
sourceExtractor = new DomLessSourceExtractor();
} else {
sourceExtractor = new DefaultSourceExtractor();
}
Set<MappedSourceModule> sourcesMap = sourceExtractor.extractSources(url, new JerichoHtmlParser(), new IdentityUrlResolver());
SourceModule[] sources = new SourceFileModule[sourcesMap.size()];
int i = 0;
for (SourceModule m : sourcesMap){
sources[i++] = m;
}
return sources;
}
}
package com.ibm.wala.cast.js.vis;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
import com.ibm.wala.cast.js.html.IdentityUrlResolver;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException;
public class JsViewerDriver extends JSCallGraphBuilderUtil {
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
if (args.length != 1){
System.out.println("Usage: <URL of html page to analyze>");
System.exit(1);
}
boolean domless = false;
URL url = new URL(args[0]);
// computing CG + PA
JSCallGraphBuilderUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
SourceModule[] sources = getSources(domless, url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, CGBuilderType.ZERO_ONE_CFA, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url);
CallGraph cg = builder.makeCallGraph(builder.getOptions());
PointerAnalysis pa = builder.getPointerAnalysis();
new JsViewer(cg, pa);
}
private static SourceModule[] getSources(boolean domless, URL url)
throws IOException {
JSSourceExtractor sourceExtractor;
if (domless ){
sourceExtractor = new DomLessSourceExtractor();
} else {
sourceExtractor = new DefaultSourceExtractor();
}
Set<MappedSourceModule> sourcesMap = sourceExtractor.extractSources(url, new JerichoHtmlParser(), new IdentityUrlResolver());
SourceModule[] sources = new SourceFileModule[sourcesMap.size()];
int i = 0;
for (SourceModule m : sourcesMap){
sources[i++] = m;
}
return sources;
}
}

View File

@ -1,185 +1,185 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
public class DefaultSourceExtractor extends DomLessSourceExtractor{
protected static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{
private final HashMap<String, String> constructors = HashMapFactory.make();
private final Stack<String> stack = new Stack<String>();
private final Stack<ITag> forms = new Stack<ITag>();
private final Set<Pair<ITag,String>> sets = new HashSet<Pair<ITag,String>>();
public HtmlCallBack(URL entrypointUrl, IUrlResolver urlResolver) {
super(entrypointUrl, urlResolver);
constructors.put("FORM", "DOMHTMLFormElement");
constructors.put("TABLE", "DOMHTMLTableElement");
}
@Override
public void handleEndTag(ITag tag) {
super.handleEndTag(tag);
endElement(stack.pop());
if (tag.getName().equalsIgnoreCase("FORM")) {
forms.pop();
}
for(Entry<String,Pair<String, Position>> e : tag.getAllAttributes().entrySet()) {
String a = e.getKey();
String v = e.getValue().fst;
if (v != null && v.startsWith("javascript:")) {
try {
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a));
} catch (MalformedURLException ex) {
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
}
}
}
}
@Override
protected void handleDOM(ITag tag, String funcName) {
String cons = constructors.get(tag.getName().toUpperCase());
if(cons == null) cons = "DOMHTMLElement";
writeElement(tag, cons, funcName);
newLine();
}
private void printlnIndented(String line, ITag relatedTag){
printlnIndented(line, relatedTag==null? null: relatedTag.getElementPosition());
}
private void printlnIndented(String line, Position pos){
StringBuilder indentedLine = new StringBuilder();
for (int i = 0 ; i < stack.size() ; i++){
indentedLine.append(" ");
}
indentedLine.append(line);
if (pos == null){
domRegion.println(indentedLine.toString());
} else {
domRegion.println(indentedLine.toString(), pos, entrypointUrl);
}
}
private void newLine(){
domRegion.println("");
}
protected void writeElement(ITag tag, String cons, String varName){
Map<String, Pair<String, Position>> attrs = tag.getAllAttributes();
printlnIndented("function make_" + varName + "(parent) {", tag);
stack.push(varName);
printlnIndented("this.temp = " + cons + ";", tag);
printlnIndented("this.temp(\"" + tag.getName() + "\");", tag);
for (Map.Entry<String, Pair<String, Position>> e : attrs.entrySet()){
String attr = e.getKey();
String value = e.getValue().fst;
writeAttribute(tag, e.getValue().snd, attr, value, "this", varName);
}
if (tag.getName().equalsIgnoreCase("FORM")) {
forms.push(tag);
printlnIndented(" document.forms[document.formCount++] = this;", tag);
printlnIndented(" var currentForm = this;", tag);
} if (tag.getName().equalsIgnoreCase("INPUT")) {
String prop = attrs.containsKey("name") ? attrs.get("name").fst : null;
String type = attrs.containsKey("type") ? attrs.get("type").fst : null;
if (type != null && prop != null) {
if (type.equalsIgnoreCase("RADIO")) {
if (! sets.contains(Pair.make(forms.peek(), prop))) {
sets.add(Pair.make(forms.peek(), prop));
printlnIndented(" currentForm." + prop + " = new Array();", tag);
printlnIndented(" currentForm." + prop + "Counter = 0;", tag);
}
printlnIndented(" currentForm." + prop + "[currentForm." + prop + "Counter++] = this;", tag);
} else {
printlnIndented(" currentForm." + prop + " = this;", tag);
}
}
}
printlnIndented(varName + " = this;", tag);
printlnIndented("document." + varName + " = this;", tag);
printlnIndented("parent.appendChild(this);", tag);
}
protected void writeAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2) {
writePortletAttribute(tag, attr, value, varName);
writeEventAttribute(tag, pos, attr, value, varName, varName2);
}
protected void writeEventAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2){
if(attr.substring(0,2).equals("on")) {
printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag);
entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl);
} else if (value != null) {
if (value.indexOf('\'') > 0) {
value = value.replaceAll("\\'", "\\\\'");
}
if (value.indexOf('\n') > 0) {
value = value.replaceAll("\\n", "\\\\n");
}
if (attr.equals(attr.toUpperCase())) {
attr = attr.toLowerCase();
}
printlnIndented(varName + "['" + attr + "'] = '" + value + "';", tag);
}
}
protected void writePortletAttribute(ITag tag, String attr, String value, String varName){
if(attr.equals("portletid")) {
if(value.substring(value.length()-4).equals("vice")) {
newLine(); newLine();
printlnIndented("function cVice() { var contextVice = " + varName + "; }\ncVice();\n", tag);
} else if(value.substring(value.length()-4).equals("root")) {
newLine(); newLine();
printlnIndented("function cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n", tag);
}
}
}
protected void endElement(String name) {
printlnIndented("};", (Position)null);
if (stack.isEmpty()) {
printlnIndented("new make_" + name + "(document);\n\n", (Position)null);
} else {
printlnIndented("new make_" + name + "(this);\n", (Position)null);
}
}
}
@Override
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
return new HtmlCallBack(entrypointUrl, urlResolver);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
public class DefaultSourceExtractor extends DomLessSourceExtractor{
protected static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{
private final HashMap<String, String> constructors = HashMapFactory.make();
private final Stack<String> stack = new Stack<String>();
private final Stack<ITag> forms = new Stack<ITag>();
private final Set<Pair<ITag,String>> sets = new HashSet<Pair<ITag,String>>();
public HtmlCallBack(URL entrypointUrl, IUrlResolver urlResolver) {
super(entrypointUrl, urlResolver);
constructors.put("FORM", "DOMHTMLFormElement");
constructors.put("TABLE", "DOMHTMLTableElement");
}
@Override
public void handleEndTag(ITag tag) {
super.handleEndTag(tag);
endElement(stack.pop());
if (tag.getName().equalsIgnoreCase("FORM")) {
forms.pop();
}
for(Entry<String,Pair<String, Position>> e : tag.getAllAttributes().entrySet()) {
String a = e.getKey();
String v = e.getValue().fst;
if (v != null && v.startsWith("javascript:")) {
try {
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a));
} catch (MalformedURLException ex) {
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
}
}
}
}
@Override
protected void handleDOM(ITag tag, String funcName) {
String cons = constructors.get(tag.getName().toUpperCase());
if(cons == null) cons = "DOMHTMLElement";
writeElement(tag, cons, funcName);
newLine();
}
private void printlnIndented(String line, ITag relatedTag){
printlnIndented(line, relatedTag==null? null: relatedTag.getElementPosition());
}
private void printlnIndented(String line, Position pos){
StringBuilder indentedLine = new StringBuilder();
for (int i = 0 ; i < stack.size() ; i++){
indentedLine.append(" ");
}
indentedLine.append(line);
if (pos == null){
domRegion.println(indentedLine.toString());
} else {
domRegion.println(indentedLine.toString(), pos, entrypointUrl);
}
}
private void newLine(){
domRegion.println("");
}
protected void writeElement(ITag tag, String cons, String varName){
Map<String, Pair<String, Position>> attrs = tag.getAllAttributes();
printlnIndented("function make_" + varName + "(parent) {", tag);
stack.push(varName);
printlnIndented("this.temp = " + cons + ";", tag);
printlnIndented("this.temp(\"" + tag.getName() + "\");", tag);
for (Map.Entry<String, Pair<String, Position>> e : attrs.entrySet()){
String attr = e.getKey();
String value = e.getValue().fst;
writeAttribute(tag, e.getValue().snd, attr, value, "this", varName);
}
if (tag.getName().equalsIgnoreCase("FORM")) {
forms.push(tag);
printlnIndented(" document.forms[document.formCount++] = this;", tag);
printlnIndented(" var currentForm = this;", tag);
} if (tag.getName().equalsIgnoreCase("INPUT")) {
String prop = attrs.containsKey("name") ? attrs.get("name").fst : null;
String type = attrs.containsKey("type") ? attrs.get("type").fst : null;
if (type != null && prop != null) {
if (type.equalsIgnoreCase("RADIO")) {
if (! sets.contains(Pair.make(forms.peek(), prop))) {
sets.add(Pair.make(forms.peek(), prop));
printlnIndented(" currentForm." + prop + " = new Array();", tag);
printlnIndented(" currentForm." + prop + "Counter = 0;", tag);
}
printlnIndented(" currentForm." + prop + "[currentForm." + prop + "Counter++] = this;", tag);
} else {
printlnIndented(" currentForm." + prop + " = this;", tag);
}
}
}
printlnIndented(varName + " = this;", tag);
printlnIndented("document." + varName + " = this;", tag);
printlnIndented("parent.appendChild(this);", tag);
}
protected void writeAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2) {
writePortletAttribute(tag, attr, value, varName);
writeEventAttribute(tag, pos, attr, value, varName, varName2);
}
protected void writeEventAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2){
if(attr.substring(0,2).equals("on")) {
printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag);
entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl);
} else if (value != null) {
if (value.indexOf('\'') > 0) {
value = value.replaceAll("\\'", "\\\\'");
}
if (value.indexOf('\n') > 0) {
value = value.replaceAll("\\n", "\\\\n");
}
if (attr.equals(attr.toUpperCase())) {
attr = attr.toLowerCase();
}
printlnIndented(varName + "['" + attr + "'] = '" + value + "';", tag);
}
}
protected void writePortletAttribute(ITag tag, String attr, String value, String varName){
if(attr.equals("portletid")) {
if(value.substring(value.length()-4).equals("vice")) {
newLine(); newLine();
printlnIndented("function cVice() { var contextVice = " + varName + "; }\ncVice();\n", tag);
} else if(value.substring(value.length()-4).equals("root")) {
newLine(); newLine();
printlnIndented("function cRoot() { var contextRoot = " + varName + "; }\ncRoot();\n", tag);
}
}
}
protected void endElement(String name) {
printlnIndented("};", (Position)null);
if (stack.isEmpty()) {
printlnIndented("new make_" + name + "(document);\n\n", (Position)null);
} else {
printlnIndented("new make_" + name + "(this);\n", (Position)null);
}
}
}
@Override
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
return new HtmlCallBack(entrypointUrl, urlResolver);
}
}

View File

@ -1,279 +1,279 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
public class DomLessSourceExtractor extends JSSourceExtractor {
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
protected interface IGeneratorCallback extends IHtmlCallback {
void writeToFinalRegion(SourceRegion finalRegion);
}
protected static class HtmlCallback implements IGeneratorCallback{
protected final URL entrypointUrl;
protected final IUrlResolver urlResolver;
protected final SourceRegion scriptRegion;
protected final SourceRegion domRegion;
protected final SourceRegion entrypointRegion;
private ITag currentScriptTag;
private int nodeCounter = 0;
private int scriptNodeCounter = 0;
public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
this.entrypointUrl = entrypointUrl;
this.urlResolver = urlResolver;
this.scriptRegion = new SourceRegion();
this.domRegion = new SourceRegion();
this.entrypointRegion = new SourceRegion();
}
protected Position makePos(int lineNumber, ITag governingTag) {
return makePos(entrypointUrl, lineNumber, governingTag);
}
protected Position makePos(final URL url, final int lineNumber, ITag governingTag) {
return governingTag.getElementPosition();
}
public void handleEndTag(ITag tag) {
if (tag.getName().equalsIgnoreCase("script")) {
assert currentScriptTag != null;
currentScriptTag = null;
}
}
public void handleText(Position p, String text) {
if (currentScriptTag != null) {
if (text.startsWith("<![CDATA[")) {
assert text.endsWith("]]>");
text = text.substring(9, text.length()-11);
}
URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + scriptNodeCounter);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
}
}
public void handleStartTag(ITag tag) {
if (tag.getName().equalsIgnoreCase("script")) {
handleScript(tag);
assert currentScriptTag == null;
currentScriptTag = tag;
scriptNodeCounter++;
}
handleDOM(tag);
}
/**
* Model the HTML DOM
*
* @param tag
* - the HTML tag to module
*/
protected void handleDOM(ITag tag) {
// Get the name of the modeling function either from the id attribute or a
// running counter
Pair<String,Position> idAttribute = tag.getAttributeByName("id");
String funcName;
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
funcName = idAttribute.fst;
} else {
funcName = "node" + (nodeCounter++);
}
handleDOM(tag, funcName);
}
protected void handleDOM(ITag tag, String funcName) {
Map<String, Pair<String,Position>> attributeSet = tag.getAllAttributes();
for (Entry<String, Pair<String, Position>> a : attributeSet.entrySet()) {
handleAttribute(a, funcName, tag);
}
}
private void handleAttribute(Entry<String, Pair<String,Position>> a, String funcName, ITag tag) {
URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + tag.getElementPosition().getFirstOffset());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Position pos = a.getValue().snd;
String attName = a.getKey();
String attValue = a.getValue().fst;
if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) {
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
String signatureLine = "function " + fName + "(event) {";
// Defines the function
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
// Run it
entrypointRegion.println("\t" + fName + "(null);", pos, url);
}
}
private String extructJS(String attValue) {
if (attValue == null){
return "";
}
String content;
if (attValue.toLowerCase().equals("javascript:")) {
content = attValue.substring("javascript:".length());
} else {
content = attValue;
}
return content;
}
protected void handleScript(ITag tag) {
Pair<String,Position> value = tag.getAttributeByName("src");
try {
if (value != null) {
// script is out-of-line
getScriptFromUrl(value.fst, tag);
}
} catch (IOException e) {
System.err.println("Error reading script file: " + e.getMessage());
}
}
private void getScriptFromUrl(String urlAsString, ITag scriptTag) throws IOException, MalformedURLException {
URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
URL scriptSrc = urlResolver.resolve(absoluteUrl);
if (scriptSrc == null) { //Error resolving URL
return;
}
InputStream scriptInputStream = scriptSrc.openConnection().getInputStream();
try{
String line;
BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
StringBuffer x = new StringBuffer();
while ((line = scriptReader.readLine()) != null) {
x.append(line).append("\n");
}
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
} finally {
scriptInputStream.close();
}
}
protected String getScriptName(URL url) throws MalformedURLException {
String file = url.getFile();
int lastIdxOfSlash = file.lastIndexOf('/');
file = (lastIdxOfSlash == (-1)) ? file : file.substring(lastIdxOfSlash + 1);
return file;
}
public void writeToFinalRegion(SourceRegion finalRegion) {
// wrapping the embedded scripts with a fake method of the window. Required for making this == window.
finalRegion.println("window.__MAIN__ = function __WINDOW_MAIN__(){");
finalRegion.write(scriptRegion);
finalRegion.write(domRegion);
finalRegion.println(" document.URL = new String(\"" + entrypointUrl + "\");");
finalRegion.println("while (true){ ");
finalRegion.write(entrypointRegion);
finalRegion.println("} // while (true)");
finalRegion.println("} // end of window.__MAIN__");
finalRegion.println("window.__MAIN__();");
}
}
public Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver)
throws IOException {
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
SourceRegion finalRegion = new SourceRegion();
htmlCallback.writeToFinalRegion(finalRegion);
// writing the final region into one SourceFileModule.
File outputFile = createOutputFile(entrypointUrl, DELETE_UPON_EXIT, USE_TEMP_NAME);
FileMapping fileMapping = finalRegion.writeToFile(new PrintStream(outputFile));
MappedSourceModule singleFileModule = new MappedSourceFileModule(outputFile, outputFile.getName(), fileMapping);
return Collections.singleton(singleFileModule);
}
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
return new HtmlCallback(entrypointUrl, urlResolver);
}
private File createOutputFile(URL url, boolean delete, boolean useTempName) throws IOException {
File outputFile;
if (useTempName) {
outputFile = File.createTempFile(new File(url.getFile()).getName(), ".js");
} else {
outputFile = new File(new File(url.getFile()).getName());
}
if (outputFile.exists()){
outputFile.delete();
}
if(delete){
outputFile.deleteOnExit();
}
return outputFile;
}
public static void main(String[] args) throws IOException {
// DomLessSourceExtractor domLessScopeGenerator = new DomLessSourceExtractor();
JSSourceExtractor domLessScopeGenerator = new DefaultSourceExtractor();
JSSourceExtractor.DELETE_UPON_EXIT = false;
URL entrypointUrl = new URL(args[0]);
IHtmlParser htmlParser = new JerichoHtmlParser();
IUrlResolver urlResolver = new IdentityUrlResolver();
Set<MappedSourceModule> res = domLessScopeGenerator.extractSources(entrypointUrl , htmlParser , urlResolver);
MappedSourceModule entry = res.iterator().next();
System.out.println(entry);
entry.getMapping().dump(System.out);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
public class DomLessSourceExtractor extends JSSourceExtractor {
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
protected interface IGeneratorCallback extends IHtmlCallback {
void writeToFinalRegion(SourceRegion finalRegion);
}
protected static class HtmlCallback implements IGeneratorCallback{
protected final URL entrypointUrl;
protected final IUrlResolver urlResolver;
protected final SourceRegion scriptRegion;
protected final SourceRegion domRegion;
protected final SourceRegion entrypointRegion;
private ITag currentScriptTag;
private int nodeCounter = 0;
private int scriptNodeCounter = 0;
public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
this.entrypointUrl = entrypointUrl;
this.urlResolver = urlResolver;
this.scriptRegion = new SourceRegion();
this.domRegion = new SourceRegion();
this.entrypointRegion = new SourceRegion();
}
protected Position makePos(int lineNumber, ITag governingTag) {
return makePos(entrypointUrl, lineNumber, governingTag);
}
protected Position makePos(final URL url, final int lineNumber, ITag governingTag) {
return governingTag.getElementPosition();
}
public void handleEndTag(ITag tag) {
if (tag.getName().equalsIgnoreCase("script")) {
assert currentScriptTag != null;
currentScriptTag = null;
}
}
public void handleText(Position p, String text) {
if (currentScriptTag != null) {
if (text.startsWith("<![CDATA[")) {
assert text.endsWith("]]>");
text = text.substring(9, text.length()-11);
}
URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + scriptNodeCounter);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
}
}
public void handleStartTag(ITag tag) {
if (tag.getName().equalsIgnoreCase("script")) {
handleScript(tag);
assert currentScriptTag == null;
currentScriptTag = tag;
scriptNodeCounter++;
}
handleDOM(tag);
}
/**
* Model the HTML DOM
*
* @param tag
* - the HTML tag to module
*/
protected void handleDOM(ITag tag) {
// Get the name of the modeling function either from the id attribute or a
// running counter
Pair<String,Position> idAttribute = tag.getAttributeByName("id");
String funcName;
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
funcName = idAttribute.fst;
} else {
funcName = "node" + (nodeCounter++);
}
handleDOM(tag, funcName);
}
protected void handleDOM(ITag tag, String funcName) {
Map<String, Pair<String,Position>> attributeSet = tag.getAllAttributes();
for (Entry<String, Pair<String, Position>> a : attributeSet.entrySet()) {
handleAttribute(a, funcName, tag);
}
}
private void handleAttribute(Entry<String, Pair<String,Position>> a, String funcName, ITag tag) {
URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + tag.getElementPosition().getFirstOffset());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Position pos = a.getValue().snd;
String attName = a.getKey();
String attValue = a.getValue().fst;
if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) {
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
String signatureLine = "function " + fName + "(event) {";
// Defines the function
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
// Run it
entrypointRegion.println("\t" + fName + "(null);", pos, url);
}
}
private String extructJS(String attValue) {
if (attValue == null){
return "";
}
String content;
if (attValue.toLowerCase().equals("javascript:")) {
content = attValue.substring("javascript:".length());
} else {
content = attValue;
}
return content;
}
protected void handleScript(ITag tag) {
Pair<String,Position> value = tag.getAttributeByName("src");
try {
if (value != null) {
// script is out-of-line
getScriptFromUrl(value.fst, tag);
}
} catch (IOException e) {
System.err.println("Error reading script file: " + e.getMessage());
}
}
private void getScriptFromUrl(String urlAsString, ITag scriptTag) throws IOException, MalformedURLException {
URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
URL scriptSrc = urlResolver.resolve(absoluteUrl);
if (scriptSrc == null) { //Error resolving URL
return;
}
InputStream scriptInputStream = scriptSrc.openConnection().getInputStream();
try{
String line;
BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
StringBuffer x = new StringBuffer();
while ((line = scriptReader.readLine()) != null) {
x.append(line).append("\n");
}
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
} finally {
scriptInputStream.close();
}
}
protected String getScriptName(URL url) throws MalformedURLException {
String file = url.getFile();
int lastIdxOfSlash = file.lastIndexOf('/');
file = (lastIdxOfSlash == (-1)) ? file : file.substring(lastIdxOfSlash + 1);
return file;
}
public void writeToFinalRegion(SourceRegion finalRegion) {
// wrapping the embedded scripts with a fake method of the window. Required for making this == window.
finalRegion.println("window.__MAIN__ = function __WINDOW_MAIN__(){");
finalRegion.write(scriptRegion);
finalRegion.write(domRegion);
finalRegion.println(" document.URL = new String(\"" + entrypointUrl + "\");");
finalRegion.println("while (true){ ");
finalRegion.write(entrypointRegion);
finalRegion.println("} // while (true)");
finalRegion.println("} // end of window.__MAIN__");
finalRegion.println("window.__MAIN__();");
}
}
public Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver)
throws IOException {
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
SourceRegion finalRegion = new SourceRegion();
htmlCallback.writeToFinalRegion(finalRegion);
// writing the final region into one SourceFileModule.
File outputFile = createOutputFile(entrypointUrl, DELETE_UPON_EXIT, USE_TEMP_NAME);
FileMapping fileMapping = finalRegion.writeToFile(new PrintStream(outputFile));
MappedSourceModule singleFileModule = new MappedSourceFileModule(outputFile, outputFile.getName(), fileMapping);
return Collections.singleton(singleFileModule);
}
protected IGeneratorCallback createHtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
return new HtmlCallback(entrypointUrl, urlResolver);
}
private File createOutputFile(URL url, boolean delete, boolean useTempName) throws IOException {
File outputFile;
if (useTempName) {
outputFile = File.createTempFile(new File(url.getFile()).getName(), ".js");
} else {
outputFile = new File(new File(url.getFile()).getName());
}
if (outputFile.exists()){
outputFile.delete();
}
if(delete){
outputFile.deleteOnExit();
}
return outputFile;
}
public static void main(String[] args) throws IOException {
// DomLessSourceExtractor domLessScopeGenerator = new DomLessSourceExtractor();
JSSourceExtractor domLessScopeGenerator = new DefaultSourceExtractor();
JSSourceExtractor.DELETE_UPON_EXIT = false;
URL entrypointUrl = new URL(args[0]);
IHtmlParser htmlParser = new JerichoHtmlParser();
IUrlResolver urlResolver = new IdentityUrlResolver();
Set<MappedSourceModule> res = domLessScopeGenerator.extractSources(entrypointUrl , htmlParser , urlResolver);
MappedSourceModule entry = res.iterator().next();
System.out.println(entry);
entry.getMapping().dump(System.out);
}
}

View File

@ -1,31 +1,31 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
/**
* Callback which is implemented by users of the IHtmlParser. The parser traverses the dom-nodes in an in-order.
* @author danielk
* @author yinnonh
*
*/
public interface IHtmlCallback {
void handleStartTag(ITag tag);
void handleText(Position pos, String text);
void handleEndTag(ITag tag);
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
/**
* Callback which is implemented by users of the IHtmlParser. The parser traverses the dom-nodes in an in-order.
* @author danielk
* @author yinnonh
*
*/
public interface IHtmlCallback {
void handleStartTag(ITag tag);
void handleText(Position pos, String text);
void handleEndTag(ITag tag);
}

View File

@ -1,31 +1,31 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.InputStream;
import java.net.URL;
/**
* @author danielk
* @author yinnonh
* Parses an HTML file using call backs
*/
public interface IHtmlParser {
/**
* Parses a given HTML, calling the given callback.
* @param reader
* @param callback
* @param fileName
*/
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName);
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.InputStream;
import java.net.URL;
/**
* @author danielk
* @author yinnonh
* Parses an HTML file using call backs
*/
public interface IHtmlParser {
/**
* Parses a given HTML, calling the given callback.
* @param reader
* @param callback
* @param fileName
*/
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName);
}

View File

@ -1,45 +1,45 @@
package com.ibm.wala.cast.js.html;
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
import java.util.Map;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
/**
* @author danielk
* Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback.
*/
public interface ITag {
/**
* @return tag's name (e.g., "HEAD" / "HTML" / "FORM")
*/
public String getName();
/**
* Retrieves a specific attribute
* @param name
* @return null if there is no such attribute
*/
public Pair<String, Position> getAttributeByName(String name);
public Map<String, Pair<String, Position>> getAllAttributes();
/**
* Returns the starting line number of the tag.
* @return null if no known
*/
public Position getElementPosition();
public Position getContentPosition();
}
package com.ibm.wala.cast.js.html;
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
import java.util.Map;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
/**
* @author danielk
* Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback.
*/
public interface ITag {
/**
* @return tag's name (e.g., "HEAD" / "HTML" / "FORM")
*/
public String getName();
/**
* Retrieves a specific attribute
* @param name
* @return null if there is no such attribute
*/
public Pair<String, Position> getAttributeByName(String name);
public Map<String, Pair<String, Position>> getAllAttributes();
/**
* Returns the starting line number of the tag.
* @return null if no known
*/
public Position getElementPosition();
public Position getContentPosition();
}

View File

@ -1,36 +1,36 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.URL;
/**
* Used for handling resources that were copied from the web to local files (and still contain references to the web)
* @author yinnonh
* @author danielk
*
*/
public interface IUrlResolver {
/**
* From Internet to local
* @param input
* @return
*/
public URL resolve(URL input);
/**
* From local to Internet
* @param input
* @return
*/
public URL deResolve(URL input);
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.URL;
/**
* Used for handling resources that were copied from the web to local files (and still contain references to the web)
* @author yinnonh
* @author danielk
*
*/
public interface IUrlResolver {
/**
* From Internet to local
* @param input
* @return
*/
public URL resolve(URL input);
/**
* From local to Internet
* @param input
* @return
*/
public URL deResolve(URL input);
}

View File

@ -1,25 +1,25 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.URL;
public class IdentityUrlResolver implements IUrlResolver{
public URL resolve(URL input) {
return input;
}
public URL deResolve(URL input) {
return input;
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.URL;
public class IdentityUrlResolver implements IUrlResolver{
public URL resolve(URL input) {
return input;
}
public URL deResolve(URL input) {
return input;
}
}

View File

@ -1,32 +1,32 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
/**
* Extracts scripts from a given URL of an HTML. Retrieves also attached js files.
* Provides file and line mapping for each extracted SourceFileModule back to the original file and line number.
*
* @author yinnonh
* @author danielk
*/
public abstract class JSSourceExtractor {
public static boolean DELETE_UPON_EXIT = false;
public static boolean USE_TEMP_NAME = false;
public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException;
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
/**
* Extracts scripts from a given URL of an HTML. Retrieves also attached js files.
* Provides file and line mapping for each extracted SourceFileModule back to the original file and line number.
*
* @author yinnonh
* @author danielk
*/
public abstract class JSSourceExtractor {
public static boolean DELETE_UPON_EXIT = false;
public static boolean USE_TEMP_NAME = false;
public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException;
}

View File

@ -1,100 +1,100 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.PrintStream;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
public class SourceRegion {
private final StringBuilder source = new StringBuilder();
private FileMapping fileMapping;
private int currentLine = 1;
public SourceRegion() {
}
public void print(String text, Position originalPos, URL url){
int startOffset = source.length();
source.append(text);
int endOffset = source.length();
int numberOfLineDrops = getNumberOfLineDrops(text);
if (originalPos != null) {
RangeFileMapping map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
if (fileMapping == null) {
fileMapping = map;
} else {
fileMapping = new CompositeFileMapping(map, fileMapping);
}
}
currentLine += numberOfLineDrops;
}
public void println(String text, Position originalPos, URL url){
print(text + "\n", originalPos, url);
}
public void print(String text){
print(text, null, null);
}
public void println(String text){
print(text + "\n");
}
public FileMapping writeToFile(PrintStream ps){
ps.print(source.toString());
return fileMapping;
}
public void write(SourceRegion otherRegion){
int rangeStart = source.length();
String text = otherRegion.source.toString();
source.append(text);
int rangeEnd = source.length();
int numberOfLineDrops = getNumberOfLineDrops(text);
if (otherRegion.fileMapping != null) {
FileMapping map = new NestedRangeMapping(rangeStart, rangeEnd, currentLine, currentLine+numberOfLineDrops, otherRegion.fileMapping);
if (fileMapping == null) {
fileMapping = map;
} else {
fileMapping = new CompositeFileMapping(map, fileMapping);
}
}
currentLine += numberOfLineDrops;
}
public void dump(PrintStream ps){
ps.println(source.toString());
}
private static int getNumberOfLineDrops(String text) {
int ret = 0;
int i = text.indexOf('\n');
while (i != -1){
ret++;
if (i < text.length()-1){
i = text.indexOf('\n', i + 1);
} else {
break; // CR was the the last character.
}
}
return ret;
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.PrintStream;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
public class SourceRegion {
private final StringBuilder source = new StringBuilder();
private FileMapping fileMapping;
private int currentLine = 1;
public SourceRegion() {
}
public void print(String text, Position originalPos, URL url){
int startOffset = source.length();
source.append(text);
int endOffset = source.length();
int numberOfLineDrops = getNumberOfLineDrops(text);
if (originalPos != null) {
RangeFileMapping map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
if (fileMapping == null) {
fileMapping = map;
} else {
fileMapping = new CompositeFileMapping(map, fileMapping);
}
}
currentLine += numberOfLineDrops;
}
public void println(String text, Position originalPos, URL url){
print(text + "\n", originalPos, url);
}
public void print(String text){
print(text, null, null);
}
public void println(String text){
print(text + "\n");
}
public FileMapping writeToFile(PrintStream ps){
ps.print(source.toString());
return fileMapping;
}
public void write(SourceRegion otherRegion){
int rangeStart = source.length();
String text = otherRegion.source.toString();
source.append(text);
int rangeEnd = source.length();
int numberOfLineDrops = getNumberOfLineDrops(text);
if (otherRegion.fileMapping != null) {
FileMapping map = new NestedRangeMapping(rangeStart, rangeEnd, currentLine, currentLine+numberOfLineDrops, otherRegion.fileMapping);
if (fileMapping == null) {
fileMapping = map;
} else {
fileMapping = new CompositeFileMapping(map, fileMapping);
}
}
currentLine += numberOfLineDrops;
}
public void dump(PrintStream ps){
ps.println(source.toString());
}
private static int getNumberOfLineDrops(String text) {
int ret = 0;
int i = text.indexOf('\n');
while (i != -1){
ret++;
if (i < text.length()-1){
i = text.indexOf('\n', i + 1);
} else {
break; // CR was the the last character.
}
}
return ret;
}
}

View File

@ -1,122 +1,122 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
/**
http://www.unicode.org/unicode/faq/utf_bom.html
BOMs:
00 00 FE FF = UTF-32, big-endian
FF FE 00 00 = UTF-32, little-endian
FE FF = UTF-16, big-endian
FF FE = UTF-16, little-endian
EF BB BF = UTF-8
Win2k Notepad:
Unicode format = UTF-16LE
***/
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
/**
* Generic unicode textreader, which will use BOM mark to identify the encoding to be used.
*/
public class UnicodeReader extends Reader {
PushbackInputStream internalIn;
InputStreamReader internalIn2 = null;
String defaultEnc;
private static final int BOM_SIZE = 6;
/*
* Default encoding is used only if BOM is not found. If defaultEncoding is NULL then systemdefault is used.
*/
public UnicodeReader(InputStream in, String defaultEnc) {
internalIn = new PushbackInputStream(in, BOM_SIZE);
this.defaultEnc = defaultEnc;
}
public String getDefaultEncoding() {
return defaultEnc;
}
public String getEncoding() {
if (internalIn2 == null)
return null;
return internalIn2.getEncoding();
}
/**
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread back to the stream, only BOM bytes are skipped.
*/
protected void init() throws IOException {
if (internalIn2 != null)
return;
String encoding;
byte bom[] = new byte[BOM_SIZE];
int n, unread;
n = internalIn.read(bom, 0, bom.length);
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF) && (bom[3] == (byte) 0xEF) && (bom[4] == (byte) 0xBB) && (bom[5] == (byte) 0xBF)) {
encoding = "UTF-8";
unread = n - 6;
} else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
encoding = "UTF-8";
unread = n - 3;
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
encoding = "UTF-16BE";
unread = n - 2;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
encoding = "UTF-16LE";
unread = n - 2;
} else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
encoding = "UTF-32BE";
unread = n - 4;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
encoding = "UTF-32LE";
unread = n - 4;
} else {
// Unicode BOM mark not found, unread all bytes
encoding = defaultEnc;
unread = n;
}
// System.out.println("read=" + n + ", unread=" + unread);
if (unread > 0)
internalIn.unread(bom, (n - unread), unread);
else if (unread < -1)
internalIn.unread(bom, 0, 0);
// Use given encoding
if (encoding == null) {
internalIn2 = new InputStreamReader(internalIn);
} else {
internalIn2 = new InputStreamReader(internalIn, encoding);
}
}
public void close() throws IOException {
init();
internalIn2.close();
}
public int read(char[] cbuf, int off, int len) throws IOException {
init();
return internalIn2.read(cbuf, off, len);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
/**
http://www.unicode.org/unicode/faq/utf_bom.html
BOMs:
00 00 FE FF = UTF-32, big-endian
FF FE 00 00 = UTF-32, little-endian
FE FF = UTF-16, big-endian
FF FE = UTF-16, little-endian
EF BB BF = UTF-8
Win2k Notepad:
Unicode format = UTF-16LE
***/
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
/**
* Generic unicode textreader, which will use BOM mark to identify the encoding to be used.
*/
public class UnicodeReader extends Reader {
PushbackInputStream internalIn;
InputStreamReader internalIn2 = null;
String defaultEnc;
private static final int BOM_SIZE = 6;
/*
* Default encoding is used only if BOM is not found. If defaultEncoding is NULL then systemdefault is used.
*/
public UnicodeReader(InputStream in, String defaultEnc) {
internalIn = new PushbackInputStream(in, BOM_SIZE);
this.defaultEnc = defaultEnc;
}
public String getDefaultEncoding() {
return defaultEnc;
}
public String getEncoding() {
if (internalIn2 == null)
return null;
return internalIn2.getEncoding();
}
/**
* Read-ahead four bytes and check for BOM marks. Extra bytes are unread back to the stream, only BOM bytes are skipped.
*/
protected void init() throws IOException {
if (internalIn2 != null)
return;
String encoding;
byte bom[] = new byte[BOM_SIZE];
int n, unread;
n = internalIn.read(bom, 0, bom.length);
if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF) && (bom[3] == (byte) 0xEF) && (bom[4] == (byte) 0xBB) && (bom[5] == (byte) 0xBF)) {
encoding = "UTF-8";
unread = n - 6;
} else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
encoding = "UTF-8";
unread = n - 3;
} else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
encoding = "UTF-16BE";
unread = n - 2;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
encoding = "UTF-16LE";
unread = n - 2;
} else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
encoding = "UTF-32BE";
unread = n - 4;
} else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
encoding = "UTF-32LE";
unread = n - 4;
} else {
// Unicode BOM mark not found, unread all bytes
encoding = defaultEnc;
unread = n;
}
// System.out.println("read=" + n + ", unread=" + unread);
if (unread > 0)
internalIn.unread(bom, (n - unread), unread);
else if (unread < -1)
internalIn.unread(bom, 0, 0);
// Use given encoding
if (encoding == null) {
internalIn2 = new InputStreamReader(internalIn);
} else {
internalIn2 = new InputStreamReader(internalIn, encoding);
}
}
public void close() throws IOException {
init();
internalIn2.close();
}
public int read(char[] cbuf, int off, int len) throws IOException {
init();
return internalIn2.read(cbuf, off, len);
}
}

View File

@ -1,78 +1,78 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.MalformedURLException;
import java.net.URL;
public class UrlManipulator {
/**
* @param urlFound the link as appear
* @param context the URL in which the link appeared
* @return
* @throws MalformedURLException
*/
public static URL relativeToAbsoluteUrl(String urlFound, URL context) throws MalformedURLException {
urlFound = urlFound.replace("\\", "/").toLowerCase();
URL absoluteUrl;
if (!isAbsoluteUrl(urlFound)) {
if (urlFound.startsWith("//")) {
//create URL taking only the protocol from the context
String origHostAndPath = urlFound.substring(2);// removing "//"
String host;
String path;
int indexOf = origHostAndPath.indexOf("/");
if (indexOf > 0) {
host = origHostAndPath.substring(0, indexOf);
path = origHostAndPath.substring(indexOf);
} else {
host = origHostAndPath;
path = "";
}
absoluteUrl = new URL(context.getProtocol(), host, path);
} else if (urlFound.startsWith("/")) {
//create URL taking the protocol and the host from the context
absoluteUrl = new URL(context.getProtocol(), context.getHost(), urlFound);
} else {
//"concat" URL to context
int backDir = 0; // removing directories due to "../"
while(urlFound.startsWith("../")){
urlFound = urlFound.substring(3);
backDir++;
}
StringBuilder contextPath = new StringBuilder();
String path = context.getPath().replace("\\", "/");
boolean isContextDirectory = path.endsWith("/");
String[] split = path.split("/");
// we are also removing last element in case of a directory
int rightTrimFromPath = (isContextDirectory ? 0 : 1) + backDir;
for (int i = 0; i < split.length - rightTrimFromPath; i++) {
contextPath.append(split[i]);
contextPath.append("/");
}
absoluteUrl = new URL(context.getProtocol(), context.getHost(), contextPath.toString() + urlFound);
}
} else{
absoluteUrl = new URL(urlFound);
}
return absoluteUrl;
}
private static boolean isAbsoluteUrl(String orig) {
return orig.startsWith("http");
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.MalformedURLException;
import java.net.URL;
public class UrlManipulator {
/**
* @param urlFound the link as appear
* @param context the URL in which the link appeared
* @return
* @throws MalformedURLException
*/
public static URL relativeToAbsoluteUrl(String urlFound, URL context) throws MalformedURLException {
urlFound = urlFound.replace("\\", "/").toLowerCase();
URL absoluteUrl;
if (!isAbsoluteUrl(urlFound)) {
if (urlFound.startsWith("//")) {
//create URL taking only the protocol from the context
String origHostAndPath = urlFound.substring(2);// removing "//"
String host;
String path;
int indexOf = origHostAndPath.indexOf("/");
if (indexOf > 0) {
host = origHostAndPath.substring(0, indexOf);
path = origHostAndPath.substring(indexOf);
} else {
host = origHostAndPath;
path = "";
}
absoluteUrl = new URL(context.getProtocol(), host, path);
} else if (urlFound.startsWith("/")) {
//create URL taking the protocol and the host from the context
absoluteUrl = new URL(context.getProtocol(), context.getHost(), urlFound);
} else {
//"concat" URL to context
int backDir = 0; // removing directories due to "../"
while(urlFound.startsWith("../")){
urlFound = urlFound.substring(3);
backDir++;
}
StringBuilder contextPath = new StringBuilder();
String path = context.getPath().replace("\\", "/");
boolean isContextDirectory = path.endsWith("/");
String[] split = path.split("/");
// we are also removing last element in case of a directory
int rightTrimFromPath = (isContextDirectory ? 0 : 1) + backDir;
for (int i = 0; i < split.length - rightTrimFromPath; i++) {
contextPath.append(split[i]);
contextPath.append("/");
}
absoluteUrl = new URL(context.getProtocol(), context.getHost(), contextPath.toString() + urlFound);
}
} else{
absoluteUrl = new URL(urlFound);
}
return absoluteUrl;
}
private static boolean isAbsoluteUrl(String orig) {
return orig.startsWith("http");
}
}

View File

@ -1,78 +1,78 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html.jericho;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import net.htmlparser.jericho.Config;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.LoggerProvider;
import net.htmlparser.jericho.Source;
import com.ibm.wala.cast.js.html.IHtmlCallback;
import com.ibm.wala.cast.js.html.IHtmlParser;
/**
* @author danielk
* Uses the Jericho parser to go over the HTML
*/
public class JerichoHtmlParser implements IHtmlParser{
static{
Config.LoggerProvider = LoggerProvider.STDERR;
}
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) {
Parser parser = new Parser(callback, fileName);
Source src;
try {
src = new Source(reader);
List<Element> childElements = src.getChildElements();
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
Element e = nodeIterator.next();
parser.parse(e);
}
} catch (IOException e) {
System.err.println("Error parsing file: " + e.getMessage());
}
}
/**
* @author danielk
* Inner class does the actual traversal of the HTML using recursion
*/
private static class Parser {
private final IHtmlCallback handler;
private final String fileName;
public Parser(IHtmlCallback handler, String fileName) {
this.handler = handler;
this.fileName = fileName;
}
private void parse(Element root) {
JerichoTag tag = new JerichoTag(root, fileName);
handler.handleStartTag(tag);
handler.handleText(tag.getElementPosition(), tag.getBodyText().snd);
List<Element> childElements = root.getChildElements();
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
Element child = nodeIterator.next();
parse(child);
}
handler.handleEndTag(tag);
}
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html.jericho;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import net.htmlparser.jericho.Config;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.LoggerProvider;
import net.htmlparser.jericho.Source;
import com.ibm.wala.cast.js.html.IHtmlCallback;
import com.ibm.wala.cast.js.html.IHtmlParser;
/**
* @author danielk
* Uses the Jericho parser to go over the HTML
*/
public class JerichoHtmlParser implements IHtmlParser{
static{
Config.LoggerProvider = LoggerProvider.STDERR;
}
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) {
Parser parser = new Parser(callback, fileName);
Source src;
try {
src = new Source(reader);
List<Element> childElements = src.getChildElements();
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
Element e = nodeIterator.next();
parser.parse(e);
}
} catch (IOException e) {
System.err.println("Error parsing file: " + e.getMessage());
}
}
/**
* @author danielk
* Inner class does the actual traversal of the HTML using recursion
*/
private static class Parser {
private final IHtmlCallback handler;
private final String fileName;
public Parser(IHtmlCallback handler, String fileName) {
this.handler = handler;
this.fileName = fileName;
}
private void parse(Element root) {
JerichoTag tag = new JerichoTag(root, fileName);
handler.handleStartTag(tag);
handler.handleText(tag.getElementPosition(), tag.getBodyText().snd);
List<Element> childElements = root.getChildElements();
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
Element child = nodeIterator.next();
parse(child);
}
handler.handleEndTag(tag);
}
}
}

View File

@ -1,147 +1,147 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html.jericho;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import net.htmlparser.jericho.Attribute;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Segment;
import com.ibm.wala.cast.js.html.ITag;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
/**
* ITag impel for Jericho generated tags
* @author danielk
*/
public class JerichoTag implements ITag {
private final Element innerElement;
private final String sourceFile;
private Map<String, Pair<String, Position>> allAttributes = null;
public JerichoTag(Element root, String sourceFile) {
this.innerElement = root;
this.sourceFile = sourceFile;
}
private Position getPosition(final Segment e) {
return new AbstractSourcePosition() {
@Override
public int getFirstLine() {
return e.getSource().getRowColumnVector(e.getBegin()).getRow();
}
@Override
public int getLastLine() {
return e.getSource().getRowColumnVector(e.getEnd()).getRow();
}
@Override
public int getFirstCol() {
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
}
@Override
public int getLastCol() {
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
}
@Override
public int getFirstOffset() {
return e.getBegin();
}
@Override
public int getLastOffset() {
return e.getEnd();
}
@Override
public URL getURL() {
try {
return new URL("file://" + sourceFile);
} catch (MalformedURLException e) {
return null;
}
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(sourceFile);
}
};
}
private Map<String, Pair<String, Position>> makeAllAttributes() {
Map<String, Pair<String, Position>> result = HashMapFactory.make();
if (innerElement.getStartTag().getAttributes() != null) {
for (Attribute a : innerElement.getStartTag().getAttributes()) {
result.put(
a.getName().toLowerCase(),
Pair.make(a.getValue(), getPosition(a.getValueSegment())));
}
}
return result;
}
public Map<String, Pair<String, Position>> getAllAttributes() {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes;
}
public Pair<String, Position> getAttributeByName(String name) {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes.get(name.toLowerCase());
}
public Pair<Integer, String> getBodyText() {
Segment content = innerElement.getContent();
Integer lineNum = innerElement.getSource().getRow(content.getBegin());
String body = content.toString();
return Pair.make(lineNum, body);
}
public String getFilePath() {
return sourceFile;
}
public String getName() {
return innerElement.getName();
}
@Override
public String toString() {
return innerElement.toString();
}
public Position getElementPosition() {
return getPosition(innerElement);
}
public Position getContentPosition() {
return getPosition(innerElement.getContent());
}
}
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html.jericho;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import net.htmlparser.jericho.Attribute;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Segment;
import com.ibm.wala.cast.js.html.ITag;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
/**
* ITag impel for Jericho generated tags
* @author danielk
*/
public class JerichoTag implements ITag {
private final Element innerElement;
private final String sourceFile;
private Map<String, Pair<String, Position>> allAttributes = null;
public JerichoTag(Element root, String sourceFile) {
this.innerElement = root;
this.sourceFile = sourceFile;
}
private Position getPosition(final Segment e) {
return new AbstractSourcePosition() {
@Override
public int getFirstLine() {
return e.getSource().getRowColumnVector(e.getBegin()).getRow();
}
@Override
public int getLastLine() {
return e.getSource().getRowColumnVector(e.getEnd()).getRow();
}
@Override
public int getFirstCol() {
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
}
@Override
public int getLastCol() {
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
}
@Override
public int getFirstOffset() {
return e.getBegin();
}
@Override
public int getLastOffset() {
return e.getEnd();
}
@Override
public URL getURL() {
try {
return new URL("file://" + sourceFile);
} catch (MalformedURLException e) {
return null;
}
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(sourceFile);
}
};
}
private Map<String, Pair<String, Position>> makeAllAttributes() {
Map<String, Pair<String, Position>> result = HashMapFactory.make();
if (innerElement.getStartTag().getAttributes() != null) {
for (Attribute a : innerElement.getStartTag().getAttributes()) {
result.put(
a.getName().toLowerCase(),
Pair.make(a.getValue(), getPosition(a.getValueSegment())));
}
}
return result;
}
public Map<String, Pair<String, Position>> getAllAttributes() {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes;
}
public Pair<String, Position> getAttributeByName(String name) {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes.get(name.toLowerCase());
}
public Pair<Integer, String> getBodyText() {
Segment content = innerElement.getContent();
Integer lineNum = innerElement.getSource().getRow(content.getBegin());
String body = content.toString();
return Pair.make(lineNum, body);
}
public String getFilePath() {
return sourceFile;
}
public String getName() {
return innerElement.getName();
}
@Override
public String toString() {
return innerElement.toString();
}
public Position getElementPosition() {
return getPosition(innerElement);
}
public Position getContentPosition() {
return getPosition(innerElement.getContent());
}
}

View File

@ -1,198 +1,198 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cfg.InducedCFG;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.functions.Function;
public class AstCallGraph extends ExplicitCallGraph {
public AstCallGraph(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(cha, options, cache);
}
public static class AstFakeRoot extends AbstractRootMethod {
public AstFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, declaringClass, cha, options, cache);
}
public AstFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, cha, options, cache);
}
public InducedCFG makeControlFlowGraph(SSAInstruction[] statements) {
return new AstInducedCFG(statements, this, Everywhere.EVERYWHERE);
}
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
AstLexicalRead s = new AstLexicalRead(nextLocal++, null, name);
statements.add(s);
return s;
}
}
public static abstract class ScriptFakeRoot extends AstFakeRoot {
public ScriptFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, declaringClass, cha, options, cache);
}
public ScriptFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, cha, options, cache);
}
public abstract SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite);
}
public class AstCGNode extends ExplicitNode {
private Set<Function<Object, Object>> callbacks;
private boolean lexicalScopingChanges = false;
private IR cachedIR;
private DefUse cachedDU;
private AstCGNode(IMethod method, Context context) {
super(method, context);
}
private void fireCallbacks() {
if (callbacks != null) {
boolean done = false;
while (!done) {
try {
for (Iterator<Function<Object, Object>> x = callbacks.iterator(); x.hasNext();) {
x.next().apply(null);
}
} catch (ConcurrentModificationException e) {
done = false;
continue;
}
done = true;
}
}
}
private boolean hasCallback(Function<Object, Object> callback) {
return callbacks != null && callbacks.contains(callback);
}
private boolean hasAllCallbacks(Set<Function<Object, Object>> callbacks) {
return callbacks != null && callbacks.containsAll(callbacks);
}
public void addCallback(Function<Object, Object> callback) {
if (!hasCallback(callback)) {
if (callbacks == null) {
callbacks = HashSetFactory.make(1);
}
callbacks.add(callback);
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
((AstCGNode) ps.next()).addCallback(callback);
}
}
}
public void addAllCallbacks(Set<Function<Object, Object>> callback) {
if (!hasAllCallbacks(callbacks)) {
if (callbacks == null) {
callbacks = HashSetFactory.make(1);
}
callbacks.addAll(callback);
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
((AstCGNode) ps.next()).addAllCallbacks(callback);
}
}
}
public void setLexicallyMutatedIR(IR ir) {
lexicalScopingChanges = true;
cachedIR = ir;
cachedDU = null;
}
public void clearMutatedCache(CallSiteReference cs) {
targets.remove(cs.getProgramCounter());
}
public IR getLexicallyMutatedIR() {
if (lexicalScopingChanges) {
return cachedIR;
} else {
return null;
}
}
public DefUse getLexicallyMutatedDU() {
if (lexicalScopingChanges) {
if (cachedDU == null) {
cachedDU = new DefUse(cachedIR);
}
return cachedDU;
} else {
return null;
}
}
public boolean addTarget(CallSiteReference site, CGNode node) {
if (super.addTarget(site, node)) {
if (((AstCGNode) node).callbacks != null) {
((AstCGNode) node).fireCallbacks();
addAllCallbacks(((AstCGNode) node).callbacks);
}
return true;
} else {
return false;
}
}
}
protected ExplicitNode makeNode(IMethod method, Context context) {
return new AstCGNode(method, context);
}
protected CGNode makeFakeRootNode() throws CancelException {
return findOrCreateNode(new AstFakeRoot(FakeRootMethod.rootMethod, cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cfg.InducedCFG;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.functions.Function;
public class AstCallGraph extends ExplicitCallGraph {
public AstCallGraph(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(cha, options, cache);
}
public static class AstFakeRoot extends AbstractRootMethod {
public AstFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, declaringClass, cha, options, cache);
}
public AstFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, cha, options, cache);
}
public InducedCFG makeControlFlowGraph(SSAInstruction[] statements) {
return new AstInducedCFG(statements, this, Everywhere.EVERYWHERE);
}
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
AstLexicalRead s = new AstLexicalRead(nextLocal++, null, name);
statements.add(s);
return s;
}
}
public static abstract class ScriptFakeRoot extends AstFakeRoot {
public ScriptFakeRoot(MethodReference rootMethod, IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, declaringClass, cha, options, cache);
}
public ScriptFakeRoot(MethodReference rootMethod, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(rootMethod, cha, options, cache);
}
public abstract SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite);
}
public class AstCGNode extends ExplicitNode {
private Set<Function<Object, Object>> callbacks;
private boolean lexicalScopingChanges = false;
private IR cachedIR;
private DefUse cachedDU;
private AstCGNode(IMethod method, Context context) {
super(method, context);
}
private void fireCallbacks() {
if (callbacks != null) {
boolean done = false;
while (!done) {
try {
for (Iterator<Function<Object, Object>> x = callbacks.iterator(); x.hasNext();) {
x.next().apply(null);
}
} catch (ConcurrentModificationException e) {
done = false;
continue;
}
done = true;
}
}
}
private boolean hasCallback(Function<Object, Object> callback) {
return callbacks != null && callbacks.contains(callback);
}
private boolean hasAllCallbacks(Set<Function<Object, Object>> callbacks) {
return callbacks != null && callbacks.containsAll(callbacks);
}
public void addCallback(Function<Object, Object> callback) {
if (!hasCallback(callback)) {
if (callbacks == null) {
callbacks = HashSetFactory.make(1);
}
callbacks.add(callback);
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
((AstCGNode) ps.next()).addCallback(callback);
}
}
}
public void addAllCallbacks(Set<Function<Object, Object>> callback) {
if (!hasAllCallbacks(callbacks)) {
if (callbacks == null) {
callbacks = HashSetFactory.make(1);
}
callbacks.addAll(callback);
for (Iterator ps = getCallGraph().getPredNodes(this); ps.hasNext();) {
((AstCGNode) ps.next()).addAllCallbacks(callback);
}
}
}
public void setLexicallyMutatedIR(IR ir) {
lexicalScopingChanges = true;
cachedIR = ir;
cachedDU = null;
}
public void clearMutatedCache(CallSiteReference cs) {
targets.remove(cs.getProgramCounter());
}
public IR getLexicallyMutatedIR() {
if (lexicalScopingChanges) {
return cachedIR;
} else {
return null;
}
}
public DefUse getLexicallyMutatedDU() {
if (lexicalScopingChanges) {
if (cachedDU == null) {
cachedDU = new DefUse(cachedIR);
}
return cachedDU;
} else {
return null;
}
}
public boolean addTarget(CallSiteReference site, CGNode node) {
if (super.addTarget(site, node)) {
if (((AstCGNode) node).callbacks != null) {
((AstCGNode) node).fireCallbacks();
addAllCallbacks(((AstCGNode) node).callbacks);
}
return true;
} else {
return false;
}
}
}
protected ExplicitNode makeNode(IMethod method, Context context) {
return new AstCGNode(method, context);
}
protected CGNode makeFakeRootNode() throws CancelException {
return findOrCreateNode(new AstFakeRoot(FakeRootMethod.rootMethod, cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
}
}

View File

@ -1,168 +1,168 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cast.util.TargetLanguageSelector;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* A CallGraph implementation adapted to work for graphs that contain code
* entities from multiple languages, and hence multiple specialized forms of IR.
* The root node delegates to one of several language-specific root nodes,
* allowing each language to use its own specialized IR constructs for entry
* points.
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public class CrossLanguageCallGraph extends AstCallGraph {
public CrossLanguageCallGraph(TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots, IClassHierarchy cha,
AnalysisOptions options, AnalysisCache cache) {
super(cha, options, cache);
this.roots = roots;
}
private final TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots;
private final Set<CGNode> languageRootNodes = HashSetFactory.make();
private final Map<Atom,IMethod> languageRoots = HashMapFactory.make();
@SuppressWarnings("deprecation")
public AbstractRootMethod getLanguageRoot(Atom language){
if (!languageRoots.containsKey(language)) {
AbstractRootMethod languageRoot = roots.get(language, this);
CGNode languageRootNode = null;
try {
languageRootNode = findOrCreateNode(languageRoot, Everywhere.EVERYWHERE);
} catch (CancelException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
languageRootNodes.add(languageRootNode);
CallSiteReference site = CallSiteReference.make(1, languageRoot.getReference(), IInvokeInstruction.Dispatch.STATIC);
CGNode fakeRootNode = getFakeRootNode();
CrossLanguageFakeRoot fakeRootMethod = (CrossLanguageFakeRoot) fakeRootNode.getMethod();
site = fakeRootMethod.addInvocationInternal(new int[0], site).getCallSite();
fakeRootNode.addTarget(site, languageRootNode);
languageRoots.put(language, languageRoot);
}
return (AbstractRootMethod) languageRoots.get(language);
}
public class CrossLanguageFakeRoot extends ScriptFakeRoot {
public CrossLanguageFakeRoot(IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(FakeRootMethod.rootMethod, declaringClass, cha, options, cache);
}
public CrossLanguageFakeRoot(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(FakeRootMethod.rootMethod, cha, options, cache);
}
public int addPhi(TypeReference type, int[] values) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addPhi(values);
}
public int addGetInstance(FieldReference ref, int object) {
TypeReference type = ref.getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addGetInstance(ref, object);
}
public int addGetStatic(FieldReference ref) {
TypeReference type = ref.getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addGetStatic(ref);
}
public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) {
Atom language = type[0].getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addCheckcast(type, rv, isPEI);
}
public SSANewInstruction addAllocation(TypeReference type) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addAllocation(type);
}
public SSAInvokeInstruction addInvocation(int[] params, CallSiteReference site) {
TypeReference type = site.getDeclaredTarget().getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addInvocation(params, site);
}
public SSAInvokeInstruction addInvocationInternal(int[] params, CallSiteReference site) {
return super.addInvocation(params, site);
}
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return ((AstFakeRoot) root).addGlobalRead(type, name);
}
public SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite) {
TypeReference type = callSite.getDeclaredTarget().getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return ((ScriptFakeRoot) root).addDirectCall(functionVn, argVns, callSite);
}
}
Iterator getLanguageRoots() {
return languageRootNodes.iterator();
}
protected CGNode makeFakeRootNode() throws CancelException {
return findOrCreateNode(new CrossLanguageFakeRoot(cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
}
}
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cast.util.TargetLanguageSelector;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* A CallGraph implementation adapted to work for graphs that contain code
* entities from multiple languages, and hence multiple specialized forms of IR.
* The root node delegates to one of several language-specific root nodes,
* allowing each language to use its own specialized IR constructs for entry
* points.
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public class CrossLanguageCallGraph extends AstCallGraph {
public CrossLanguageCallGraph(TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots, IClassHierarchy cha,
AnalysisOptions options, AnalysisCache cache) {
super(cha, options, cache);
this.roots = roots;
}
private final TargetLanguageSelector<AbstractRootMethod, CrossLanguageCallGraph> roots;
private final Set<CGNode> languageRootNodes = HashSetFactory.make();
private final Map<Atom,IMethod> languageRoots = HashMapFactory.make();
@SuppressWarnings("deprecation")
public AbstractRootMethod getLanguageRoot(Atom language){
if (!languageRoots.containsKey(language)) {
AbstractRootMethod languageRoot = roots.get(language, this);
CGNode languageRootNode = null;
try {
languageRootNode = findOrCreateNode(languageRoot, Everywhere.EVERYWHERE);
} catch (CancelException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
languageRootNodes.add(languageRootNode);
CallSiteReference site = CallSiteReference.make(1, languageRoot.getReference(), IInvokeInstruction.Dispatch.STATIC);
CGNode fakeRootNode = getFakeRootNode();
CrossLanguageFakeRoot fakeRootMethod = (CrossLanguageFakeRoot) fakeRootNode.getMethod();
site = fakeRootMethod.addInvocationInternal(new int[0], site).getCallSite();
fakeRootNode.addTarget(site, languageRootNode);
languageRoots.put(language, languageRoot);
}
return (AbstractRootMethod) languageRoots.get(language);
}
public class CrossLanguageFakeRoot extends ScriptFakeRoot {
public CrossLanguageFakeRoot(IClass declaringClass, IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(FakeRootMethod.rootMethod, declaringClass, cha, options, cache);
}
public CrossLanguageFakeRoot(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) {
super(FakeRootMethod.rootMethod, cha, options, cache);
}
public int addPhi(TypeReference type, int[] values) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addPhi(values);
}
public int addGetInstance(FieldReference ref, int object) {
TypeReference type = ref.getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addGetInstance(ref, object);
}
public int addGetStatic(FieldReference ref) {
TypeReference type = ref.getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addGetStatic(ref);
}
public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) {
Atom language = type[0].getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addCheckcast(type, rv, isPEI);
}
public SSANewInstruction addAllocation(TypeReference type) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addAllocation(type);
}
public SSAInvokeInstruction addInvocation(int[] params, CallSiteReference site) {
TypeReference type = site.getDeclaredTarget().getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return root.addInvocation(params, site);
}
public SSAInvokeInstruction addInvocationInternal(int[] params, CallSiteReference site) {
return super.addInvocation(params, site);
}
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return ((AstFakeRoot) root).addGlobalRead(type, name);
}
public SSAAbstractInvokeInstruction addDirectCall(int functionVn, int[] argVns, CallSiteReference callSite) {
TypeReference type = callSite.getDeclaredTarget().getDeclaringClass();
Atom language = type.getClassLoader().getLanguage();
AbstractRootMethod root = getLanguageRoot(language);
return ((ScriptFakeRoot) root).addDirectCall(functionVn, argVns, callSite);
}
}
Iterator getLanguageRoots() {
return languageRootNodes.iterator();
}
protected CGNode makeFakeRootNode() throws CancelException {
return findOrCreateNode(new CrossLanguageFakeRoot(cha, options, getAnalysisCache()), Everywhere.EVERYWHERE);
}
}

View File

@ -1,162 +1,162 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ssa.SymbolTable;
/**
* This abstract class adds to invoke instructions the ability to handle lexical uses and definitions during call graph
* construction. The lexical uses and definitions of these objects are initially empty, and get filled in by the
* AstSSAPropagationCallGraphBuilder, particularly its LexicalOperator objects. This class is still abstract since the
* lexical scoping functionality is used by multiple languages, each of which has further specializations of invoke
* instructions.
*
* @author Julian Dolby (dolby@us.ibm.com)
*
*/
public abstract class AbstractLexicalInvoke extends MultiReturnValueInvokeInstruction {
protected Access[] lexicalReads = null;
protected Access[] lexicalWrites = null;
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site) {
super(results, exception, site);
}
protected AbstractLexicalInvoke(int result, int exception, CallSiteReference site) {
this(new int[] { result }, exception, site);
}
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site, Access[] lexicalReads,
Access[] lexicalWrites) {
this(results, exception, site);
this.lexicalReads = lexicalReads;
this.lexicalWrites = lexicalWrites;
}
public int getNumberOfUses() {
if (lexicalReads == null)
return getNumberOfParameters();
else
return getNumberOfParameters() + lexicalReads.length;
}
public int getNumberOfLexicalWrites(){
if(lexicalWrites == null){
return 0;
} else {
return lexicalWrites.length;
}
}
public int getNumberOfLexicalReads() {
if(lexicalReads == null){
return 0;
} else {
return lexicalReads.length;
}
}
public final int getLastLexicalUse() {
if (lexicalReads == null) {
return -1;
} else {
return getNumberOfParameters() + lexicalReads.length - 1;
}
}
public int getUse(int j) {
assert j >= getNumberOfParameters();
assert lexicalReads != null;
assert lexicalReads[j - getNumberOfParameters()] != null;
return lexicalReads[j - getNumberOfParameters()].valueNumber;
}
public int getNumberOfDefs() {
if (lexicalWrites == null)
return super.getNumberOfDefs();
else
return super.getNumberOfDefs() + lexicalWrites.length;
}
public int getDef(int j) {
if (j < super.getNumberOfDefs())
return super.getDef(j);
else
return lexicalWrites[j - super.getNumberOfDefs()].valueNumber;
}
private Access[] addAccess(Access[] array, Access access) {
if (array == null)
return new Access[] { access };
else {
Access[] result = new Access[array.length + 1];
System.arraycopy(array, 0, result, 0, array.length);
result[array.length] = access;
return result;
}
}
public boolean isLexicalUse(int use) {
return use >= getNumberOfParameters();
}
public void addLexicalUse(Access use) {
lexicalReads = addAccess(lexicalReads, use);
}
public Access getLexicalUse(int i) {
return lexicalReads[i - getNumberOfParameters()];
}
public boolean isLexicalDef(int def) {
return def >= super.getNumberOfDefs();
}
public void addLexicalDef(Access def) {
lexicalWrites = addAccess(lexicalWrites, def);
}
public Access getLexicalDef(int i) {
return lexicalWrites[i - super.getNumberOfDefs()];
}
public int hashCode() {
return site.hashCode() * 7529;
}
public String toString(SymbolTable symbolTable) {
StringBuffer s = new StringBuffer(super.toString(symbolTable));
if (lexicalReads != null) {
s.append(" (reads:");
for (int i = 0; i < lexicalReads.length; i++) {
s.append(" ").append(lexicalReads[i].variableName).append(":").append(
getValueString(symbolTable, lexicalReads[i].valueNumber));
}
s.append(")");
}
if (lexicalWrites != null) {
s.append(" (writes:");
for (int i = 0; i < lexicalWrites.length; i++) {
s.append(" ").append(lexicalWrites[i].variableName).append(":").append(
getValueString(symbolTable, lexicalWrites[i].valueNumber));
}
s.append(")");
}
return s.toString();
}
}
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ssa.SymbolTable;
/**
* This abstract class adds to invoke instructions the ability to handle lexical uses and definitions during call graph
* construction. The lexical uses and definitions of these objects are initially empty, and get filled in by the
* AstSSAPropagationCallGraphBuilder, particularly its LexicalOperator objects. This class is still abstract since the
* lexical scoping functionality is used by multiple languages, each of which has further specializations of invoke
* instructions.
*
* @author Julian Dolby (dolby@us.ibm.com)
*
*/
public abstract class AbstractLexicalInvoke extends MultiReturnValueInvokeInstruction {
protected Access[] lexicalReads = null;
protected Access[] lexicalWrites = null;
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site) {
super(results, exception, site);
}
protected AbstractLexicalInvoke(int result, int exception, CallSiteReference site) {
this(new int[] { result }, exception, site);
}
protected AbstractLexicalInvoke(int results[], int exception, CallSiteReference site, Access[] lexicalReads,
Access[] lexicalWrites) {
this(results, exception, site);
this.lexicalReads = lexicalReads;
this.lexicalWrites = lexicalWrites;
}
public int getNumberOfUses() {
if (lexicalReads == null)
return getNumberOfParameters();
else
return getNumberOfParameters() + lexicalReads.length;
}
public int getNumberOfLexicalWrites(){
if(lexicalWrites == null){
return 0;
} else {
return lexicalWrites.length;
}
}
public int getNumberOfLexicalReads() {
if(lexicalReads == null){
return 0;
} else {
return lexicalReads.length;
}
}
public final int getLastLexicalUse() {
if (lexicalReads == null) {
return -1;
} else {
return getNumberOfParameters() + lexicalReads.length - 1;
}
}
public int getUse(int j) {
assert j >= getNumberOfParameters();
assert lexicalReads != null;
assert lexicalReads[j - getNumberOfParameters()] != null;
return lexicalReads[j - getNumberOfParameters()].valueNumber;
}
public int getNumberOfDefs() {
if (lexicalWrites == null)
return super.getNumberOfDefs();
else
return super.getNumberOfDefs() + lexicalWrites.length;
}
public int getDef(int j) {
if (j < super.getNumberOfDefs())
return super.getDef(j);
else
return lexicalWrites[j - super.getNumberOfDefs()].valueNumber;
}
private Access[] addAccess(Access[] array, Access access) {
if (array == null)
return new Access[] { access };
else {
Access[] result = new Access[array.length + 1];
System.arraycopy(array, 0, result, 0, array.length);
result[array.length] = access;
return result;
}
}
public boolean isLexicalUse(int use) {
return use >= getNumberOfParameters();
}
public void addLexicalUse(Access use) {
lexicalReads = addAccess(lexicalReads, use);
}
public Access getLexicalUse(int i) {
return lexicalReads[i - getNumberOfParameters()];
}
public boolean isLexicalDef(int def) {
return def >= super.getNumberOfDefs();
}
public void addLexicalDef(Access def) {
lexicalWrites = addAccess(lexicalWrites, def);
}
public Access getLexicalDef(int i) {
return lexicalWrites[i - super.getNumberOfDefs()];
}
public int hashCode() {
return site.hashCode() * 7529;
}
public String toString(SymbolTable symbolTable) {
StringBuffer s = new StringBuffer(super.toString(symbolTable));
if (lexicalReads != null) {
s.append(" (reads:");
for (int i = 0; i < lexicalReads.length; i++) {
s.append(" ").append(lexicalReads[i].variableName).append(":").append(
getValueString(symbolTable, lexicalReads[i].valueNumber));
}
s.append(")");
}
if (lexicalWrites != null) {
s.append(" (writes:");
for (int i = 0; i < lexicalWrites.length; i++) {
s.append(" ").append(lexicalWrites[i].variableName).append(":").append(
getValueString(symbolTable, lexicalWrites[i].valueNumber));
}
s.append(")");
}
return s.toString();
}
}

View File

@ -1,317 +1,317 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.ir.ssa.analysis;
import java.util.Iterator;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
import com.ibm.wala.dataflow.graph.BitVectorSolver;
import com.ibm.wala.dataflow.graph.BitVectorUnion;
import com.ibm.wala.dataflow.graph.IKilldallFramework;
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
import com.ibm.wala.fixpoint.BitVectorVariable;
import com.ibm.wala.fixpoint.UnaryOperator;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.ISSABasicBlock;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAPhiInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.CancelRuntimeException;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.impl.GraphInverter;
import com.ibm.wala.util.intset.BitVector;
import com.ibm.wala.util.intset.BitVectorIntSet;
import com.ibm.wala.util.intset.IntSet;
/**
* @author Julian Dolby
*
* Live-value analysis for a method's IR (or {@link ControlFlowGraph} and {@link SymbolTable}) using a {@link IKilldallFramework}
* based implementation.
*
* Pre-requisites
* - Knowledge of SSA form: control flow graphs, basic blocks, Phi instructions
* - Knowledge of data flow analysis theory: see http://en.wikipedia.org/wiki/Data_flow_analysis
*
* Implementation notes:
*
* - The solver uses node transfer functions only.
* - Performance: inverts the CFG to traverse backwards (backward analysis).
*/
public class LiveAnalysis {
public interface Result {
boolean isLiveEntry(ISSABasicBlock bb, int valueNumber);
boolean isLiveExit(ISSABasicBlock bb, int valueNumber);
BitVector getLiveBefore(int instr);
}
/**
*
*/
public static Result perform(IR ir) {
return perform(ir.getControlFlowGraph(), ir.getSymbolTable());
}