Merge branch 'wala' into master

Conflicts:
	com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/loader/JavaSourceLoaderImpl.java
	com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaInstructionFactory.java
	com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/ssa/AstJavaInvokeInstruction.java
	com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java
	com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java
	com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java
	com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ssa/JSInstructionFactory.java
	com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ssa/JavaScriptInvoke.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstCallGraph.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/AbstractLexicalInvoke.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/AstInstructionFactory.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/AstLexicalRead.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/AstLexicalWrite.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/FixedParametersInvokeInstruction.java
	com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java
	com.ibm.wala.core/.classpath
	com.ibm.wala.core/.settings/org.eclipse.jdt.core.prefs
	com.ibm.wala.ide/src/com/ibm/wala/ide/util/ProgressMonitorDelegate.java
	com.ibm.wala.util/src/com/ibm/wala/util/NullProgressMonitor.java
	com.ibm.wala.util/src/com/ibm/wala/util/ProgressMaster.java
This commit is contained in:
Juergen Graf 2014-05-20 17:59:16 +02:00
commit 428a3975ed
262 changed files with 4996 additions and 2670 deletions

View File

@ -1,3 +1,6 @@
language: java
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
install: mvn clean verify -DskipTests=true -B -q
script: mvn clean verify -B -q

View File

@ -5,14 +5,6 @@
version="1.3.4.qualifier"
provider-name="%providerName">
<copyright url="%copyrightURL">
%copyright
</copyright>
<license url="%licenseURL">
%license
</license>
<plugin
id="com.ibm.wala.core"
download-size="0"

View File

@ -3,6 +3,9 @@
<feature id="com.ibm.wala-feature">
<category name="main"/>
</feature>
<feature id="com.ibm.wala-feature.source">
<category name="main"/>
</feature>
<feature id="com.ibm.wala.ide-feature">
<category name="main"/>
</feature>

View File

@ -22,9 +22,9 @@ import com.ibm.wala.classLoader.ClassLoaderFactoryImpl;
import com.ibm.wala.classLoader.ClassLoaderImpl;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.config.SetOfClasses;
public class PolyglotClassLoaderFactory extends ClassLoaderFactoryImpl {

View File

@ -14,7 +14,8 @@
package com.ibm.wala.cast.java.translator.polyglot;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@ -869,7 +870,7 @@ public class PolyglotJava2CAstTranslator {
handleThrowsFromCall(ctorInst, n, wc);
return makeNode(wc, fFactory, n, CAstNode.LOCAL_SCOPE, makeNode(wc, fFactory, n, CAstNode.BLOCK_EXPR, makeNode(wc, fFactory,
n, CAstNode.DECL_STMT, fFactory.makeConstant(new InternalCAstSymbol(tmpName, true)), newNode), callNode, makeNode(wc,
n, CAstNode.DECL_STMT, fFactory.makeConstant(new InternalCAstSymbol(tmpName, getTypeDict().getCAstTypeFor(n.type()), true)), newNode), callNode, makeNode(wc,
fFactory, n, CAstNode.VAR, fFactory.makeConstant(tmpName))));
}
@ -1280,7 +1281,7 @@ public class PolyglotJava2CAstTranslator {
public CAstNode visit(Synchronized s, WalkContext wc) {
CAstNode exprNode = walkNodes(s.expr(), wc);
String exprName = fFactory.makeUnique();
CAstNode declStmt = makeNode(wc, fFactory, s, CAstNode.DECL_STMT, fFactory.makeConstant(new CAstSymbolImpl(exprName, true)),
CAstNode declStmt = makeNode(wc, fFactory, s, CAstNode.DECL_STMT, fFactory.makeConstant(new CAstSymbolImpl(exprName, getTypeDict().getCAstTypeFor(s.expr().type()), true)),
exprNode);
CAstNode monitorEnterNode = makeNode(wc, fFactory, s, CAstNode.MONITOR_ENTER, makeNode(wc, fFactory, s, CAstNode.VAR,
fFactory.makeConstant(exprName)));
@ -1362,7 +1363,7 @@ public class PolyglotJava2CAstTranslator {
boolean isFinal = ld.flags().flags().isFinal();
return makeNode(wc, fFactory, ld, CAstNode.DECL_STMT, fFactory.makeConstant(new CAstSymbolImpl(ld.name().id().toString(), isFinal,
return makeNode(wc, fFactory, ld, CAstNode.DECL_STMT, fFactory.makeConstant(new CAstSymbolImpl(ld.name().id().toString(), getTypeDict().getCAstTypeFor(type), isFinal,
defaultValue)), initNode);
}
@ -2515,8 +2516,8 @@ public class PolyglotJava2CAstTranslator {
}
@Override
public InputStream getInputStream() throws IOException {
return getURL().openConnection().getInputStream();
public Reader getReader() throws IOException {
return new InputStreamReader(getURL().openConnection().getInputStream());
}
}

View File

@ -12,7 +12,7 @@ package com.ibm.wala.cast.java.translator.polyglot;
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.util.config.SetOfClasses;
public class PolyglotJavaSourceAnalysisEngine extends JavaSourceAnalysisEngine {

View File

@ -19,9 +19,9 @@ import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.java.translator.SourceModuleTranslator;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.config.SetOfClasses;
public class PolyglotSourceLoaderImpl extends JavaSourceLoaderImpl {
protected final IRTranslatorExtension fExtInfo;

View File

@ -351,10 +351,10 @@ public abstract class IRTests {
CallGraph callGraph;
try {
callGraph = engine.buildDefaultCallGraph();
System.err.println(callGraph.toString());
//System.err.println(callGraph.toString());
// If we've gotten this far, IR has been produced.
dumpIR(callGraph, sources, assertReachable);
//dumpIR(callGraph, sources, assertReachable);
// Now check any assertions as to source mapping
for (IRAssertion IRAssertion : ca) {

View File

@ -604,7 +604,7 @@ public abstract class JavaIRTests extends IRTests {
Set<CGNode> roots = cg.getNodes(sliceRootRef);
Pair<Collection<Statement>, SDG> y = AstJavaSlicer.computeAssertionSlice(cg, pa, roots, false);
Collection<Statement> slice = y.fst;
SlicerTest.dumpSlice(slice);
//SlicerTest.dumpSlice(slice);
Assert.assertEquals(0, SlicerTest.countAllocations(slice));
Assert.assertEquals(1, SlicerTest.countPutfields(slice));
@ -613,7 +613,7 @@ public abstract class JavaIRTests extends IRTests {
roots = cg.getNodes(sliceRootRef);
y = AstJavaSlicer.computeAssertionSlice(cg, pa, roots, false);
slice = y.fst;
SlicerTest.dumpSlice(slice);
// SlicerTest.dumpSlice(slice);
Assert.assertEquals(2, SlicerTest.countAllocations(slice));
Assert.assertEquals(2, SlicerTest.countPutfields(slice));
}

View File

@ -11,7 +11,9 @@
package com.ibm.wala.cast.java.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
@ -25,7 +27,6 @@ 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;
@ -35,6 +36,8 @@ 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;
import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.io.FileProvider;
/**
*/
@ -105,7 +108,8 @@ public abstract class JavaSourceAnalysisEngine extends AbstractAnalysisEngine {
scope = makeSourceAnalysisScope();
if (getExclusionsFile() != null) {
scope.setExclusions(FileOfClasses.createFileOfClasses(new File(getExclusionsFile())));
InputStream is = new File(getExclusionsFile()).exists()? new FileInputStream(getExclusionsFile()): FileProvider.class.getClassLoader().getResourceAsStream(getExclusionsFile());
scope.setExclusions(new FileOfClasses(is));
}
for (Module M : this.systemEntries) {

View File

@ -12,11 +12,13 @@ package com.ibm.wala.cast.java.examples.ast;
import java.util.Map;
import com.ibm.wala.cast.java.types.JavaPrimitiveTypeMap;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
import com.ibm.wala.cast.tree.CAstType;
import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.rewrite.CAstRewriter;
import com.ibm.wala.classLoader.CallSiteReference;
@ -219,7 +221,7 @@ public class SynchronizedBlockDuplicator extends
// the conditional test
CAstNode test = Ast.makeNode(CAstNode.CALL, Ast.makeNode(CAstNode.VOID), Ast.makeConstant(f),
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName)));
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName), Ast.makeConstant(JavaPrimitiveTypeMap.lookupType("boolean"))));
// the new if conditional
return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, cfg, new SyncContext(true, n, c), nodeMap),

View File

@ -115,7 +115,7 @@ public class AstJavaSlicer extends Slicer {
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));
//System.err.println(("SDG:\n" + sdg));
Set<Statement> stmts = gatherAssertions(CG, partialRoots);
if (multiThreadedCode) {
// Grab anything that has "side effects" under JMM

View File

@ -61,10 +61,9 @@ import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.ModuleEntry;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeCT.AnnotationsReader.ElementValue;
import com.ibm.wala.shrikeCT.AnnotationsReader.ConstantElementValue;
import com.ibm.wala.shrikeCT.AnnotationsReader.ElementValue;
import com.ibm.wala.shrikeCT.ClassConstants;
import com.ibm.wala.ssa.SSAThrowInstruction;
import com.ibm.wala.ssa.SymbolTable;
@ -78,6 +77,7 @@ import com.ibm.wala.types.TypeReference;
import com.ibm.wala.types.annotations.Annotation;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
@ -574,19 +574,9 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
}
@Override
public AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site) {
return new AstJavaInvokeInstruction(iindex, result, params, exception, site);
}
@Override
public AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site) {
return new AstJavaInvokeInstruction(iindex, params, exception, site);
}
@Override
public AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int[] results, int[] params, int exception, CallSiteReference site,
Access[] lexicalReads, Access[] lexicalWrites) {
return new AstJavaInvokeInstruction(iindex, results, params, exception, site, lexicalReads, lexicalWrites);
public AstJavaInvokeInstruction JavaInvokeInstruction(final int iindex, int result[], int[] params, int exception, CallSiteReference site) {
return result == null ? new AstJavaInvokeInstruction(iindex, params, exception, site) : new AstJavaInvokeInstruction(iindex, result[0],
params, exception, site);
}
@Override
@ -655,8 +645,8 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
}
@Override
public AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName) {
return new AstLexicalRead(iindex, lhs, definer, globalName);
public AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName, TypeReference type) {
return new AstLexicalRead(iindex, lhs, definer, globalName, type);
}
@Override
@ -670,8 +660,8 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
}
@Override
public AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, int rhs) {
return new AstLexicalWrite(iindex, definer, globalName, rhs);
public AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, TypeReference type, int rhs) {
return new AstLexicalWrite(iindex, definer, globalName, type, rhs);
}
public SSAThrowInstruction NonExceptingThrowInstruction(int iindex, int exception) {

View File

@ -11,20 +11,15 @@
package com.ibm.wala.cast.java.ssa;
import com.ibm.wala.cast.ir.ssa.AstInstructionFactory;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.types.TypeReference;
public interface AstJavaInstructionFactory extends AstInstructionFactory {
AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site);
AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int result[], int[] params, int exception, CallSiteReference site);
AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site);
AstJavaInvokeInstruction JavaInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site, Access[] lexicalReads, Access[] lexicalWrites);
EnclosingObjectReference EnclosingObjectReference(int iidnex, int lval, TypeReference type);
EnclosingObjectReference EnclosingObjectReference(int iindex, int lval, TypeReference type);
AstJavaNewEnclosingInstruction JavaNewEnclosingInstruction(int iindex, int result, NewSiteReference site, int enclosing);

View File

@ -12,8 +12,7 @@ package com.ibm.wala.cast.java.ssa;
import java.util.Collection;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.ir.ssa.FixedParametersLexicalInvokeInstruction;
import com.ibm.wala.cast.ir.ssa.FixedParametersInvokeInstruction;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.JavaLanguage;
import com.ibm.wala.ssa.SSAInstruction;
@ -21,14 +20,7 @@ import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.types.TypeReference;
/**
* This is a normal Java invoke instruction as generated by the CAst source language front end; its only difference from the normal
* SSAInvokeInstruction is that it is subclassed from invoke instructions that support explicit handling of lexical scoping. So it
* behaves exactly like an invoke from bytecode, except that it has extra state for managing lexical uses and definitions.
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public class AstJavaInvokeInstruction extends FixedParametersLexicalInvokeInstruction {
public class AstJavaInvokeInstruction extends FixedParametersInvokeInstruction {
protected AstJavaInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site) {
super(iindex, results, params, exception, site);
@ -46,34 +38,24 @@ public class AstJavaInvokeInstruction extends FixedParametersLexicalInvokeInstru
this(iindex, null, params, exception, site);
}
public AstJavaInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site, Access[] lexicalReads,
Access[] lexicalWrites) {
super(iindex, results, params, exception, site, lexicalReads, lexicalWrites);
}
@Override
protected SSAInstruction copyInstruction(SSAInstructionFactory insts, int results[], int[] params, int exception,
Access[] lexicalReads, Access[] lexicalWrites) {
return ((AstJavaInstructionFactory) insts).JavaInvokeInstruction(iindex, results, params, exception, getCallSite(), lexicalReads,
lexicalWrites);
protected SSAInstruction copyInstruction(SSAInstructionFactory insts, int results[], int[] params, int exception) {
return ((AstJavaInstructionFactory) insts).JavaInvokeInstruction(iindex, results, params, exception, getCallSite());
}
/**
* @see com.ibm.domo.ssa.SSAInstruction#visit(IVisitor)
*/
@Override
public void visit(IVisitor v) {
((AstJavaInstructionVisitor) v).visitJavaInvoke(this);
}
/*
* (non-Javadoc)
*
* @see com.ibm.domo.ssa.Instruction#getExceptionTypes()
*/
@Override
public Collection<TypeReference> getExceptionTypes() {
return JavaLanguage.getNullPointerException();
}
@Override
public int hashCode() {
return (site.hashCode() * 7529) + (exception * 9823);
}
}

View File

@ -14,6 +14,7 @@
package com.ibm.wala.cast.java.translator;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
@ -207,7 +208,7 @@ public class JavaCAst2IRTranslator extends AstTranslator {
}
@Override
protected void doGlobalWrite(WalkContext context, String name, int rval) {
protected void doGlobalWrite(WalkContext context, String name, TypeReference type, int rval) {
Assertions.UNREACHABLE("doGlobalWrite() called for Java code???");
}
@ -410,6 +411,40 @@ public class JavaCAst2IRTranslator extends AstTranslator {
}
}
private CAstType getType(final String name) {
return new CAstType.Class() {
@Override
public Collection getSupertypes() {
return Collections.emptySet();
}
@Override
public String getName() {
return name;
}
@Override
public boolean isInterface() {
return false;
}
@Override
public Collection<CAstQualifier> getQualifiers() {
return Collections.emptySet();
}
};
}
@Override
protected CAstType topType() {
return getType("java.lang.Object");
}
@Override
protected CAstType exceptionType() {
return getType("java.lang.Exception");
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.ibm.wala.cast.java.polyglot" default="getJars" basedir=".">
<project name="com.ibm.wala.cast.js.html.nu_validator" default="getJars" basedir=".">
<property name="basews" value="${ws}"/>
<property name="baseos" value="${os}"/>

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.js.html.nu_validator;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
@ -41,7 +42,7 @@ import com.ibm.wala.util.collections.Pair;
public class NuValidatorHtmlParser implements IHtmlParser {
@Override
public void parse(final URL url, final InputStream reader, final IHtmlCallback handler, final String fileName) {
public void parse(final URL url, final Reader reader, final IHtmlCallback handler, final String fileName) {
URL xx = null;
try {
xx = new URL("file://" + fileName);

View File

@ -11,9 +11,10 @@ Require-Bundle: com.ibm.wala.cast.js.rhino;bundle-version="1.0.0",
com.ibm.wala.cast.js.test;bundle-version="1.0.0",
com.ibm.wala.cast.test;bundle-version="1.0.0",
com.ibm.wala.core.tests;bundle-version="1.1.3",
org.junit4;bundle-version="4.3.1",
com.ibm.wala.cast.js.test.data;bundle-version="1.3.4"
com.ibm.wala.cast.js.test.data;bundle-version="1.3.4",
org.junit;bundle-version="4.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.ibm.wala.cast.js.rhino.test,
Export-Package: com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test,
com.ibm.wala.cast.js.rhino.test,
com.ibm.wala.cast.js.test

View File

@ -0,0 +1,64 @@
package com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import junit.framework.AssertionFailedError;
import org.junit.Before;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraph;
import com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test.CGUtil.BuilderType;
import com.ibm.wala.cast.js.test.TestJSCallGraphShape;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.util.CallGraph2JSON;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.ProgressMaster;
import com.ibm.wala.util.WalaException;
public abstract class AbstractFieldBasedTest extends TestJSCallGraphShape {
protected CGUtil util;
public AbstractFieldBasedTest() {
super();
}
@Override
@Before
public void setUp() throws Exception {
util = new CGUtil(new CAstRhinoTranslatorFactory());
}
protected JSCallGraph runTest(String script, Object[][] assertions, BuilderType... builderTypes) throws IOException, WalaException, Error, CancelException {
return runTest(TestFieldBasedCG.class.getClassLoader().getResource(script), assertions, builderTypes);
}
protected JSCallGraph runTest(URL url, Object[][] assertions, BuilderType... builderTypes) throws IOException, WalaException, Error, CancelException {
JSCallGraph cg = null;
for(BuilderType builderType : builderTypes) {
ProgressMaster monitor = ProgressMaster.make(new NullProgressMonitor(), 30000, true);
try {
cg = util.buildCG(url, builderType, monitor);
verifyGraphAssertions(cg, assertions);
} catch(AssertionFailedError afe) {
throw new AssertionFailedError(builderType + ": " + afe.getMessage());
}
}
return cg;
}
@SuppressWarnings("unused")
private void dumpCG(JSCallGraph cg) {
CallGraph2JSON.IGNORE_HARNESS = false;
Map<String, Set<String>> edges = CallGraph2JSON.extractEdges(cg);
for(String callsite : edges.keySet())
for(String callee : edges.get(callsite))
System.out.println(callsite + " -> " + callee);
}
}

View File

@ -26,11 +26,11 @@ import com.ibm.wala.cast.js.callgraph.fieldbased.PessimisticCallGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.WorklistBasedOptimisticCallgraphBuilder;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraph;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
import com.ibm.wala.cast.js.util.CallGraph2JSON;
@ -42,6 +42,7 @@ import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.WalaException;
@ -60,10 +61,22 @@ public class CGUtil {
this.translatorFactory = translatorFactory;
}
public JSCallGraph buildCG(URL url, BuilderType builderType) throws IOException, WalaException, Error {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
SourceModule[] scripts = extractScript(url).toArray(new SourceModule[]{});
JavaScriptLoaderFactory loaders = makeLoaderFactory(url);
public JSCallGraph buildCG(URL url, BuilderType builderType) throws IOException, WalaException, CancelException {
return buildCG(url, builderType, new NullProgressMonitor());
}
public JSCallGraph buildCG(URL url, BuilderType builderType, IProgressMonitor monitor) throws IOException, WalaException, CancelException {
JavaScriptLoaderFactory loaders = makeLoaderFactory(url);
SourceModule[] scripts;
if (url.getFile().endsWith(".js")) {
scripts = new SourceModule[]{
new SourceURLModule(url),
JSCallGraphBuilderUtil.getPrologueFile("prologue.js")
};
} else {
scripts = JSCallGraphBuilderUtil.makeHtmlScope(url, loaders);
}
CAstAnalysisScope scope = new CAstAnalysisScope(scripts, loaders, Collections.singleton(JavaScriptLoader.JS));
IClassHierarchy cha = ClassHierarchy.make(scope, loaders, JavaScriptLoader.JS);
Util.checkForFrontEndErrors(cha);
@ -83,26 +96,14 @@ public class CGUtil {
break;
}
try {
return builder.buildCallGraph(new NullProgressMonitor());
} catch (CancelException e) {
return null;
}
return builder.buildCallGraph(roots, monitor).fst;
}
private JavaScriptLoaderFactory makeLoaderFactory(URL url) {
return url.getFile().endsWith(".js") ? new JavaScriptLoaderFactory(translatorFactory) : new WebPageLoaderFactory(translatorFactory);
}
private Set<? extends SourceModule> extractScript(URL url) throws Error {
if(url.getFile().endsWith(".js")) {
return Collections.singleton(new SourceURLModule(url));
} else {
return WebUtil.extractScriptFromHTML(url).fst;
}
}
public static void main(String[] args) throws IOException, WalaException, Error {
public static void main(String[] args) throws IOException, WalaException, Error, CancelException {
JSSourceExtractor.DELETE_UPON_EXIT = true;
URL url = new File(args[0]).toURI().toURL();
System.err.println("Analysing " + url);

View File

@ -0,0 +1,67 @@
package com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test;
import java.io.IOException;
import java.net.URL;
import org.junit.Test;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test.CGUtil.BuilderType;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.WalaException;
public class FieldBasedCGGamesTest extends AbstractFieldBasedTest {
@Test
public void testBunnyHunt() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.themaninblue.com/experiment/BunnyHunt/"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testBomberman() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.e-forum.ro/bomberman/dynagame.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testBeslimed() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.markus-inger.de/test/game.php"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testDiggAttack() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.pixastic.com/labs/digg_attack/"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testRiverRaider() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://playstar.mobi/games/riverraider/index.html?playerId=&gameId=8&highscore=102425"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testSolitaire() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.inmensia.com/files/solitaire1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test(expected = CancelException.class)
public void testWorldOfSolitaire() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://worldofsolitaire.com/"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testMinesweeper() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.inmensia.com/files/minesweeper1.0.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testProtoRPG() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.protorpg.com/games/protorpg/?game=prologue"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
@Test
public void testBattleship() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest(new URL("http://www.sinkmyship.com/battleship/single.html"), new Object[][]{}, BuilderType.OPTIMISTIC_WORKLIST));
}
}

View File

@ -11,53 +11,16 @@
package com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import junit.framework.AssertionFailedError;
import org.junit.Before;
import org.junit.Test;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraph;
import com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test.CGUtil.BuilderType;
import com.ibm.wala.cast.js.test.TestJSCallGraphShape;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.util.CallGraph2JSON;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.WalaException;
public class TestFieldBasedCG extends TestJSCallGraphShape {
protected CGUtil util;
@Override
@Before
public void setUp() throws Exception {
util = new CGUtil(new CAstRhinoTranslatorFactory());
}
private void runTest(String script, Object[][] assertions, BuilderType... builderTypes) throws IOException, WalaException, Error {
for(BuilderType builderType : builderTypes) {
URL url = TestFieldBasedCG.class.getClassLoader().getResource(script);
JSCallGraph cg = util.buildCG(url, builderType);
try {
verifyGraphAssertions(cg, assertions);
} catch(AssertionFailedError afe) {
throw new AssertionFailedError(builderType + ": " + afe.getMessage());
}
}
}
@SuppressWarnings("unused")
private void dumpCG(JSCallGraph cg) {
CallGraph2JSON.IGNORE_HARNESS = false;
Map<String, Set<String>> edges = CallGraph2JSON.extractEdges(cg);
for(String callsite : edges.keySet())
for(String callee : edges.get(callsite))
System.out.println(callsite + " -> " + callee);
}
public class TestFieldBasedCG extends AbstractFieldBasedTest {
private static final Object[][] assertionsForSimpleJS = new Object[][] {
new Object[] { ROOT, new String[] { "suffix:simple.js" } },
new Object[] { "suffix:simple.js", new String[] { "suffix:foo", "suffix:bar", "suffix:A", "suffix:Function" } },
@ -66,7 +29,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testSimpleJS() throws IOException, WalaException, Error {
public void testSimpleJS() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/simple.js", assertionsForSimpleJS, BuilderType.PESSIMISTIC, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -77,7 +40,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testOneshot() throws IOException, WalaException, Error {
public void testOneshot() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/oneshot.js", assertionsForOneShot, BuilderType.PESSIMISTIC, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -89,7 +52,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testCallbacks() throws IOException, WalaException, Error {
public void testCallbacks() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/callbacks.js", assertionsForCallbacks, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -98,7 +61,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testLexical() throws IOException, WalaException, Error {
public void testLexical() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/lexical.js", assertionsForLexical, BuilderType.PESSIMISTIC, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -108,7 +71,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testReflectiveCall() throws IOException, WalaException, Error {
public void testReflectiveCall() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/reflective_calls.js", assertionsForReflectiveCall, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -118,7 +81,7 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testNew() throws IOException, WalaException, Error {
public void testNew() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/new.js", assertionsForNew, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
@ -128,7 +91,13 @@ public class TestFieldBasedCG extends TestJSCallGraphShape {
};
@Test
public void testCallbacks2() throws IOException, WalaException, Error {
public void testCallbacks2() throws IOException, WalaException, Error, CancelException {
runTest("tests/fieldbased/callbacks2.js", assertionsForCallbacks2, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST);
}
// @Test
public void testBug2979() throws IOException, WalaException, Error, CancelException {
System.err.println(runTest("pages/2979.html", new Object[][]{}, BuilderType.PESSIMISTIC, BuilderType.OPTIMISTIC, BuilderType.OPTIMISTIC_WORKLIST));
}
}

View File

@ -92,9 +92,8 @@ public class HTMLCGBuilder {
// the code below belongs somewhere else!!!
// the bound of 4 is what is needed to pass our current framework tests
builder.setContextSelector(new RecursionCheckContextSelector(builder.getContextSelector()));
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor(), timeout * 1000, false);
if (timeout > 0) {
master.setMillisPerWorkItem(timeout * 1000);
master.beginTask("runSolver", 1);
}
long start = System.currentTimeMillis();

View File

@ -95,7 +95,7 @@ public class PrintIRs {
// add model for DOM APIs
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
URL url = (new File(filename)).toURI().toURL();
Pair<Set<MappedSourceModule>, File> p = WebUtil.extractScriptFromHTML(url);
Pair<Set<MappedSourceModule>, File> p = WebUtil.extractScriptFromHTML(url, true);
SourceModule[] scripts = p.fst.toArray(new SourceModule[] {});
JavaScriptLoaderFactory loaders = new WebPageLoaderFactory(JSCallGraphUtil.getTranslatorFactory());
CAstAnalysisScope scope = new CAstAnalysisScope(scripts, loaders, Collections.singleton(JavaScriptLoader.JS));

View File

@ -41,7 +41,6 @@ public class TestSimpleCallGraphShapeRhino extends TestSimpleCallGraphShape {
b.makeCallGraph(b.getOptions());
PointerAnalysis PA = b.getPointerAnalysis();
// just make sure this does not crash
computeIkIdToVns(PA);
}
@Test
@ -74,7 +73,12 @@ public class TestSimpleCallGraphShapeRhino extends TestSimpleCallGraphShape {
public void testNonLoopBreakLabel() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "non_loop_break.js");
}
@Test
public void testForInName() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "for_in_name.js");
}
@Test(expected = WalaException.class)
public void testParseError() throws IllegalArgumentException, IOException, CancelException, WalaException {
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "portal-example-simple.html");

View File

@ -8,6 +8,7 @@
</listAttribute>
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
<mapEntry key="[debug]" value="org.eclipse.jdt.junit.launchconfig"/>
<mapEntry key="[run]" value="org.eclipse.jdt.junit.launchconfig"/>
</mapAttribute>
<stringAttribute key="org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE" value="/tmp/console.txt"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.ibm.wala.cast.java.polyglot" default="getJars" basedir=".">
<project name="com.ibm.wala.cast.js.rhino" default="getJars" basedir=".">
<property name="basews" value="${ws}"/>
<property name="baseos" value="${os}"/>

View File

@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.ErrorReporter;
@ -108,6 +109,7 @@ import com.ibm.wala.cast.tree.impl.CAstSymbolImpl;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.util.collections.EmptyIterator;
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.warnings.Warning;
@ -294,7 +296,7 @@ public class RhinoToAstTranslator {
}
private CAstNode handleNew(WalkContext context, String globalName, CAstNode arguments[]) {
return handleNew(context, readName(context, globalName), arguments);
return handleNew(context, readName(context, null, globalName), arguments);
}
private CAstNode handleNew(WalkContext context, CAstNode value, CAstNode arguments[]) {
@ -497,8 +499,7 @@ public class RhinoToAstTranslator {
@Override
public CAstType getType() {
Assertions.UNREACHABLE("JuliansUnnamedCAstEntity$2.getType()");
return null;
return JSAstTranslator.Any;
}
}
@ -557,9 +558,13 @@ public class RhinoToAstTranslator {
return n;
}
private CAstNode readName(WalkContext context, String name) {
private CAstNode readName(WalkContext context, AstNode node, String name) {
CAstNode cn = makeVarRef(name);
context.cfg().map(cn, cn);
if (node != null) {
context.cfg().map(node, cn);
} else {
context.cfg().map(cn, cn);
}
CAstNode target = context.getCatchTarget();
if (target != null) {
context.cfg().add(cn, target, JavaScriptTypes.ReferenceError);
@ -729,14 +734,16 @@ public class RhinoToAstTranslator {
public CAstNode visitContinueStatement(ContinueStatement node,
WalkContext arg) {
CAstNode continueStmt;
Node target;
if (node.getLabel() != null) {
continueStmt = Ast.makeNode(CAstNode.GOTO, Ast.makeConstant(node.getLabel().getIdentifier()));
target = arg.getContinueFor(node.getLabel().getIdentifier());
} else {
continueStmt = Ast.makeNode(CAstNode.GOTO);
target = arg.getContinueFor(null);
}
arg.cfg().map(node, continueStmt);
Node target = node.getTarget();
arg.cfg().add(node, target, null);
return continueStmt;
@ -805,15 +812,15 @@ public class RhinoToAstTranslator {
}
@Override
public CAstNode visitForInLoop(ForInLoop node, WalkContext arg) {
String tempName = "for in loop temp";
public CAstNode visitForInLoop(ForInLoop node, WalkContext arg) {
// set up
AstNode object = node.getIteratedObject();
CAstNode loopTemp =
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(tempName)),
visit(object, arg));
CAstNode object = visit(node.getIteratedObject(), arg);
String tempName = "for in loop temp";
CAstNode[] loopHeader = new CAstNode[]{
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(tempName, JSAstTranslator.Any))),
Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(tempName)), object)
};
CAstNode initNode;
AstNode var = node.getIterator();
assert var instanceof Name || var instanceof VariableDeclaration || var instanceof LetNode : var.getClass() + " " + var;
@ -838,13 +845,13 @@ public class RhinoToAstTranslator {
if (isLet) {
initNode =
Ast.makeNode(CAstNode.DECL_STMT,
Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString(), JSAstTranslator.Any)),
Ast.makeNode(CAstNode.EACH_ELEMENT_GET, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(tempName))));
} else {
arg.addNameDecl(
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
readName(arg, "$$undefined")));
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString(), JSAstTranslator.Any)),
readName(arg, null, "$$undefined")));
initNode =
Ast.makeNode(CAstNode.ASSIGN,
@ -858,15 +865,21 @@ public class RhinoToAstTranslator {
CAstNode breakLabel = visit(breakStmt, arg);
AstNode contStmt = makeEmptyLabelStmt("contLabel");
CAstNode contLabel = visit(contStmt, arg);
// TODO: Figure out why this is needed to make the correlation extraction tests pass
// TODO: remove this silly label
AstNode garbageStmt = makeEmptyLabelStmt("garbageLabel");
CAstNode garbageLabel = visit(garbageStmt, arg);
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode body = Ast.makeNode(CAstNode.BLOCK_STMT,
initNode,
visit(node.getBody(), loopContext),
contLabel);
garbageLabel);
CAstNode loop = Ast.makeNode(CAstNode.LOCAL_SCOPE,
Ast.makeNode(CAstNode.BLOCK_STMT,
loopTemp,
loopHeader[0],
loopHeader[1],
contLabel,
Ast.makeNode(CAstNode.LOOP,
Ast.makeNode(CAstNode.EACH_ELEMENT_HAS_NEXT,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(tempName))),
@ -885,9 +898,10 @@ public class RhinoToAstTranslator {
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode loop = Ast.makeNode(CAstNode.BLOCK_STMT,
CAstNode loop;
CAstNode top = Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getInitializer(), arg),
Ast.makeNode(CAstNode.LOOP,
loop = Ast.makeNode(CAstNode.LOOP,
visit(node.getCondition(), arg),
Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getBody(), loopContext),
@ -895,7 +909,7 @@ public class RhinoToAstTranslator {
visit(node.getIncrement(), arg))),
breakLabel);
arg.cfg().map(node, loop);
return loop;
return top;
}
private CAstNode[] gatherCallArguments(Node call, WalkContext context) {
@ -912,7 +926,7 @@ public class RhinoToAstTranslator {
public CAstNode visitFunctionCall(FunctionCall n, WalkContext context) {
if (!isPrimitiveCall(context, n)) {
AstNode callee = n.getTarget();
int thisBaseVarNum = ++baseVarNum;
int thisBaseVarNum = ++tempVarNum;
WalkContext child = new MemberDestructuringContext(context, callee, thisBaseVarNum);
CAstNode fun = visit(callee, child);
@ -924,10 +938,10 @@ public class RhinoToAstTranslator {
Ast.makeNode(CAstNode.LOCAL_SCOPE,
Ast.makeNode(CAstNode.BLOCK_EXPR,
Ast.makeNode(CAstNode.DECL_STMT,
Ast.makeConstant(new CAstSymbolImpl(operationReceiverName(thisBaseVarNum))),
Ast.makeConstant(new CAstSymbolImpl(operationReceiverName(thisBaseVarNum), JSAstTranslator.Any)),
Ast.makeConstant(null)),
Ast.makeNode(CAstNode.DECL_STMT,
Ast.makeConstant(new CAstSymbolImpl(operationElementName(thisBaseVarNum))),
Ast.makeConstant(new CAstSymbolImpl(operationElementName(thisBaseVarNum), JSAstTranslator.Any)),
Ast.makeConstant(null)),
fun,
makeCall(operationElementVar(thisBaseVarNum), operationReceiverVar(thisBaseVarNum), args, context, "dispatch")));
@ -995,7 +1009,7 @@ public class RhinoToAstTranslator {
CAstNode r = visit(node.getRight(), arg);
return Ast.makeNode(CAstNode.LOCAL_SCOPE,
Ast.makeNode(CAstNode.BLOCK_EXPR,
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("or temp")), l),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("or temp", JSAstTranslator.Any)), l),
Ast.makeNode(CAstNode.IF_EXPR,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant("or temp")),
Ast.makeNode(CAstNode.VAR, Ast.makeConstant("or temp")),
@ -1005,7 +1019,7 @@ public class RhinoToAstTranslator {
CAstNode r = visit(node.getRight(), arg);
return Ast.makeNode(CAstNode.LOCAL_SCOPE,
Ast.makeNode(CAstNode.BLOCK_EXPR,
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("and temp")), l),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("and temp", JSAstTranslator.Any)), l),
Ast.makeNode(CAstNode.IF_EXPR,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant("and temp")),
r,
@ -1059,6 +1073,9 @@ public class RhinoToAstTranslator {
case Token.NULL: {
return Ast.makeConstant(null);
}
case Token.DEBUGGER: {
return Ast.makeConstant(null);
}
}
throw new RuntimeException("unexpected keyword literal " + node + " (" + node.getType() +")");
}
@ -1098,7 +1115,7 @@ public class RhinoToAstTranslator {
for(VariableInitializer init : decl.getVariables()) {
stmts[i++] =
Ast.makeNode(CAstNode.DECL_STMT,
Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString(), JSAstTranslator.Any)),
visit(init, arg));
}
stmts[i++] = visit(node.getBody(), arg);
@ -1107,7 +1124,7 @@ public class RhinoToAstTranslator {
@Override
public CAstNode visitName(Name n, WalkContext context) {
return readName(context, n.getString());
return readName(context, n, n.getString());
}
@Override
@ -1344,8 +1361,8 @@ public class RhinoToAstTranslator {
arg.addNameDecl(
noteSourcePosition(
arg,
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
readName(arg, "$$undefined")),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString(), JSAstTranslator.Any)),
readName(arg, null, "$$undefined")),
node));
if (init.getInitializer() == null) {
@ -1380,11 +1397,10 @@ public class RhinoToAstTranslator {
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode loop = Ast.makeNode(CAstNode.BLOCK_STMT,
contLabel,
Ast.makeNode(CAstNode.LOOP,
visit(node.getCondition(), arg),
Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getBody(), loopContext),
contLabel)),
visit(node.getBody(), loopContext)),
breakLabel);
arg.cfg().map(node, loop);
@ -2277,16 +2293,16 @@ private CAstNode[] walkChildren(final Node n, WalkContext context) {
*/
public CAstEntity translateToCAst() throws Error, IOException, com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error {
class CAstErrorReporter implements ErrorReporter {
private Warning w = null;
private Set<Warning> w = HashSetFactory.make();
@Override
public void error(final String arg0, final String arg1, final int arg2, final String arg3, int arg4) {
w = new Warning(Warning.SEVERE) {
w.add(new Warning(Warning.SEVERE) {
@Override
public String getMsg() {
return arg0 + ": " + arg1 + "@" + arg2 + ": " + arg3;
}
};
});
}
@Override
@ -2315,7 +2331,7 @@ private CAstNode[] walkChildren(final Node n, WalkContext context) {
AstRoot top = P.parse(sourceReader, scriptName, 1);
if (reporter.w != null) {
if (! reporter.w.isEmpty()) {
throw new TranslatorToCAst.Error(reporter.w);
}
@ -2337,7 +2353,7 @@ private CAstNode[] walkChildren(final Node n, WalkContext context) {
final private Reader sourceReader;
private int baseVarNum = 0;
private int tempVarNum = 0;
private final DoLoopTranslator doLoopTranslator;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.ibm.wala.cast.java.polyglot" default="getJars" basedir=".">
<project name="com.ibm.wala.cast.js.test.data" default="getJars" basedir=".">
<property name="basews" value="${ws}"/>
<property name="baseos" value="${os}"/>

View File

@ -0,0 +1,17 @@
<HTML>
<TITLE>Welcome!</TITLE>
Hi
<SCRIPT>
function onload_handler() {}
window.onload = onload_handler;
</SCRIPT>
<BR>
Welcome to our system
</HTML>

View File

@ -0,0 +1,10 @@
var f = function for_in_with_assign(b) {
var a,d,n,e;
n=1;
for(e=arguments.length;n<e;n+=1)
for(a in d=arguments[n],d)
Object.prototype.hasOwnProperty.call(d,a)&&(b[a]=d[a]);
return b;
}
f(new Object());

View File

@ -0,0 +1,74 @@
var f = function(arrangedSSIDs,accessPointSpecs,exactLocation)
{
for (var i=0; i < accessPointSpecs.length; i++)
{
var definedSSID = accessPointSpecs[i].SSID;
var definedMAC = accessPointSpecs[i].MAC;
if (arrangedSSIDs[definedSSID])
{
if (definedMAC)
{
if (arrangedSSIDs[definedSSID][definedMAC])
{
arrangedSSIDs[definedSSID][definedMAC].checked = true;
continue;
}
return false;
}
arrangedSSIDs[definedSSID].checked = true;
continue;
}
return false;
}
if (exactLocation)
{
for (var key in arrangedSSIDs)
{
var SSID = arrangedSSIDs[key];
if (!SSID.checked)
{
var checkedMACs = false;
for (var MAC in SSID)
{
checkedMACs = true;
var obj = SSID[MAC];
if (!obj.checked) return false;
}
if (!checkedMACs) return false;
}
}
}
return true;
};
var g = function(transactionId) {
var obj,http,i;
try
{
http = new XMLHttpRequest();
obj = { conn:http, tId:transactionId, xhr: true };
}
catch(e)
{
for(i=0; i<this._msxml_progid.length; ++i){
try
{
http = new ActiveXObject(this._msxml_progid[i]);
obj = { conn:http, tId:transactionId, xhr: true };
break;
}
catch(e1){}
}
}
finally
{
return obj;
}
}
f();
g();

File diff suppressed because one or more lines are too long

View File

@ -4,16 +4,15 @@ Bundle-Name: WALA JavaScript Test Plug-in
Bundle-SymbolicName: com.ibm.wala.cast.js.test;singleton:=true
Bundle-Version: 1.3.4.qualifier
Bundle-ClassPath: test.jar
Bundle-Activator: com.ibm.wala.cast.js.test.JavaScriptTestPlugin
Bundle-Vendor: IBM
Require-Bundle: com.ibm.wala.cast.js,
com.ibm.wala.cast,
com.ibm.wala.core,
org.eclipse.core.runtime,
com.ibm.wala.core.tests,
org.junit4;bundle-version="4.3.1",
com.ibm.wala.cast.test;bundle-version="1.0.0",
com.ibm.wala.cast.js.test.data;bundle-version="1.3.4"
com.ibm.wala.cast.js.test.data;bundle-version="1.3.4",
org.junit;bundle-version="4.0.0"
Bundle-ActivationPolicy: lazy
Export-Package: com.ibm.wala.cast.js.test
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

View File

@ -11,16 +11,16 @@
package com.ibm.wala.cast.js.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Assert;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
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.ipa.callgraph.JSAnalysisOptions;
@ -34,7 +34,6 @@ import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.loader.CAstAbstractLoader;
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.classLoader.SourceURLModule;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
@ -48,6 +47,8 @@ import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.IRFactory;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.io.FileProvider;
/**
* TODO this class is a mess. rewrite.
@ -97,28 +98,39 @@ public class JSCallGraphBuilderUtil extends com.ibm.wala.cast.js.ipa.callgraph.J
return makeCG(loaders, scope, builderType, AstIRFactory.makeDefaultFactory());
}
public static URL getURLforFile(String dir, String name) {
URL script = JSCallGraphBuilderUtil.class.getClassLoader().getResource(dir + File.separator + name);
if (script == null) {
script = JSCallGraphBuilderUtil.class.getClassLoader().getResource(dir + "/" + name);
public static URL getURLforFile(String dir, String name) throws IOException {
File f = null;
FileProvider provider = new FileProvider();
try {
f = provider.getFile(dir + File.separator + name, JSCallGraphBuilderUtil.class.getClassLoader());
} catch (FileNotFoundException e) {
// I guess we need to do this on Windows sometimes? --MS
// if this fails, we won't catch the exception
f = provider.getFile(dir + "/" + name, JSCallGraphBuilderUtil.class.getClassLoader());
}
assert script != null : "cannot find " + dir + " and " + name;
return script;
return f.toURI().toURL();
}
static AnalysisScope makeScriptScope(String dir, String name, JavaScriptLoaderFactory loaders) throws IOException {
return makeScriptScope(getURLforFile(dir, name), dir, name, loaders);
}
public static SourceModule getPrologueFile(final String name) {
return new SourceURLModule(JSCallGraphBuilderUtil.class.getClassLoader().getResource(name)) {
@Override
public String getName() {
return name;
}
};
}
static AnalysisScope makeScriptScope(URL script, String dir, String name, JavaScriptLoaderFactory loaders) throws IOException {
AnalysisScope scope;
if (script.openConnection() instanceof JarURLConnection) {
scope = makeScope(new URL[] { script }, loaders, JavaScriptLoader.JS);
} else {
scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS);
}
return scope;
return makeScope(
new SourceModule[] {
(script.openConnection() instanceof JarURLConnection)? new SourceURLModule(script): makeSourceModule(script, dir, name),
getPrologueFile("prologue.js")
}, loaders, JavaScriptLoader.JS);
}
public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException, WalaException {
@ -151,26 +163,37 @@ public class JSCallGraphBuilderUtil extends com.ibm.wala.cast.js.ipa.callgraph.J
}
public static JSCFABuilder makeHTMLCGBuilder(URL url, CGBuilderType builderType) throws IOException, WalaException {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
SourceModule[] scripts;
IRFactory<IMethod> irFactory = AstIRFactory.makeDefaultFactory();
CAstRewriterFactory preprocessor = builderType.extractCorrelatedPairs ? new CorrelatedPairExtractorFactory(translatorFactory, url) : null;
JavaScriptLoaderFactory loaders = new WebPageLoaderFactory(translatorFactory, preprocessor);
try {
Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url).fst;
scripts = script.toArray(new SourceModule[script.size()]);
} catch (Error e) {
SourceModule dummy = new SourceURLModule(url);
scripts = new SourceModule[]{ dummy };
((CAstAbstractLoader)loaders.getTheLoader()).addMessage(dummy, e.warning);
}
JSCFABuilder builder = makeCGBuilder(loaders, scripts, builderType, irFactory);
SourceModule[] scriptsArray = makeHtmlScope(url, loaders);
JSCFABuilder builder = makeCGBuilder(loaders, scriptsArray, builderType, irFactory);
if(builderType.extractCorrelatedPairs)
builder.setContextSelector(new PropertyNameContextSelector(builder.getAnalysisCache(), 2, builder.getContextSelector()));
builder.setBaseURL(url);
return builder;
}
public static SourceModule[] makeHtmlScope(URL url, JavaScriptLoaderFactory loaders) {
Set<SourceModule> scripts = HashSetFactory.make();
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
scripts.add(getPrologueFile("prologue.js"));
scripts.add(getPrologueFile("preamble.js"));
try {
scripts.addAll(WebUtil.extractScriptFromHTML(url, true).fst);
} catch (Error e) {
SourceModule dummy = new SourceURLModule(url);
scripts.add(dummy);
((CAstAbstractLoader)loaders.getTheLoader()).addMessage(dummy, e.warning);
}
SourceModule[] scriptsArray = scripts.toArray(new SourceModule[ scripts.size() ]);
return scriptsArray;
}
public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException, WalaException {
PropagationCallGraphBuilder b = makeHTMLCGBuilder(url);
CallGraph CG = b.makeCallGraph(b.getOptions());

View File

@ -18,6 +18,7 @@ import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.ArgumentSpecialization;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
@ -41,15 +42,15 @@ public abstract class TestArgumentSensitivity extends TestJSCallGraphShape {
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/y", "tests/args.js/z", "!tests/args.js/wrong" } } };
@Test public void testArgs() throws IOException, IllegalArgumentException, CancelException, ClassHierarchyException, WalaException {
JavaScriptLoaderFactory loaders = JSCallGraphBuilderUtil.makeLoaders(null);
JavaScriptLoaderFactory loaders = JSCallGraphUtil.makeLoaders(null);
AnalysisScope scope = JSCallGraphBuilderUtil.makeScriptScope("tests", "args.js", loaders);
IClassHierarchy cha = JSCallGraphBuilderUtil.makeHierarchy(scope, loaders);
IClassHierarchy cha = JSCallGraphUtil.makeHierarchy(scope, loaders);
com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha);
Iterable<Entrypoint> roots = JSCallGraphBuilderUtil.makeScriptRoots(cha);
JSAnalysisOptions options = JSCallGraphBuilderUtil.makeOptions(scope, cha, roots);
Iterable<Entrypoint> roots = JSCallGraphUtil.makeScriptRoots(cha);
JSAnalysisOptions options = JSCallGraphUtil.makeOptions(scope, cha, roots);
AnalysisCache cache = JSCallGraphBuilderUtil.makeCache(new ArgumentSpecialization.ArgumentCountIRFactory(options.getSSAOptions()));
AnalysisCache cache = CAstCallGraphUtil.makeCache(new ArgumentSpecialization.ArgumentCountIRFactory(options.getSSAOptions()));
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, false);
builder.setContextSelector(new ArgumentSpecialization.ArgumentCountContextSelector(builder.getContextSelector()));

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.ComparisonFailure;
import org.junit.Ignore;
import org.junit.Test;
@ -50,20 +51,27 @@ public abstract class TestForInBodyExtraction {
public void testRewriter(String testName, String in, String out) {
File tmp = null;
String expected = null;
String actual = null;
try {
tmp = File.createTempFile("test", ".js");
FileUtil.writeFile(tmp, in);
CAstImpl ast = new CAstImpl();
String actual = new CAstDumper().dump(new ClosureExtractor(ast, ForInBodyExtractionPolicy.FACTORY).rewrite(parseJS(tmp, ast)));
actual = new CAstDumper().dump(new ClosureExtractor(ast, ForInBodyExtractionPolicy.FACTORY).rewrite(parseJS(tmp, ast)));
actual = eraseGeneratedNames(actual);
FileUtil.writeFile(tmp, out);
String expected = new CAstDumper().dump(parseJS(tmp, ast));
expected = new CAstDumper().dump(parseJS(tmp, ast));
expected = eraseGeneratedNames(expected);
Assert.assertEquals(testName, expected, actual);
} catch (IOException e) {
e.printStackTrace();
} catch (ComparisonFailure e) {
System.err.println("Comparison Failure in " + testName + "!");
System.err.println(expected);
System.err.println(actual);
throw e;
} finally {
if(tmp != null && tmp.exists())
tmp.delete();

View File

@ -17,6 +17,7 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.ipa.callgraph.PropertyNameContextSelector;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
@ -37,7 +38,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
URL url = getClass().getClassLoader().getResource("pages/page3.html");
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
}
@Test public void testPage3WithHack() throws IOException, IllegalArgumentException, CancelException, WalaException {
@ -45,7 +46,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
}
@Ignore("This test now blows up due to proper handling of the || construct, used in extend(). Should handle this eventually.")
@ -54,7 +55,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
}
/*
@ -87,7 +88,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
@Test public void testBadForInWithoutHack() throws IOException, IllegalArgumentException, CancelException, WalaException {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForBadForin);
}
@ -106,7 +107,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin.js");
addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForBadForin);
verifyGraphAssertions(CG, assertionsForBadForinHackPrecision);
}
@ -131,7 +132,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
@Test public void testbadforin2WithoutHack() throws IOException, IllegalArgumentException, CancelException, WalaException {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin2.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForbadforin2);
}
@ -150,7 +151,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin2.js");
addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForbadforin2);
verifyGraphAssertions(CG, assertionsForbadforin2HackPrecision);
}
@ -159,7 +160,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin3.js");
addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
}

View File

@ -12,14 +12,16 @@ package com.ibm.wala.cast.js.test;
import java.util.Collection;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.test.TestCallGraphShape;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
public abstract class TestJSCallGraphShape extends TestCallGraphShape {
@Override
protected Collection getNodes(CallGraph CG, String functionIdentifier) {
return JSCallGraphBuilderUtil.getNodes(CG, functionIdentifier);
protected Collection<CGNode> getNodes(CallGraph CG, String functionIdentifier) {
return JSCallGraphUtil.getNodes(CG, functionIdentifier);
}
}

View File

@ -11,39 +11,25 @@
package com.ibm.wala.cast.js.test;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.PropertyNameContextSelector;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.NullProgressMonitor;
import com.ibm.wala.util.ProgressMaster;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.IVector;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.collections.SparseVector;
import com.ibm.wala.util.intset.IntSetAction;
import com.ibm.wala.util.intset.OrdinalSet;
public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@ -163,7 +149,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "forin.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForForin);
}
@ -255,7 +241,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
B.getOptions().setTraceStringConstants(true);
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForStringPrims);
}
@ -466,7 +452,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "return_this.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForReturnThis);
}
@ -561,7 +547,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "dispatch.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForDispatch);
}
@ -671,7 +657,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
JSCallGraphBuilderUtil.makeScriptCG("tests", "dead_catch.js");
}
@Ignore("need a bug fix")
@Test
public void testUglyLoopCrash() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "ssa-crash.js");
}
@Test
public void testTryFinallyCrash() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "try-finally-crash.js");
@ -682,26 +672,10 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
public void testManyStrings() throws IllegalArgumentException, IOException, CancelException, WalaException {
SSAPropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "many-strings.js");
B.getOptions().setTraceStringConstants(true);
final long startTime = System.currentTimeMillis();
CallGraph CG = B.makeCallGraph(B.getOptions(), new IProgressMonitor() {
@Override
public void beginTask(String task, int totalWork) {
}
@Override
public boolean isCanceled() {
return System.currentTimeMillis() > (startTime + 10000L);
}
@Override
public void done() {
}
@Override
public void worked(int units) {
}
public void subTask(String subTask) {
}
public void cancel() {
}
});
ProgressMaster monitor = ProgressMaster.make(new NullProgressMonitor(), 10000, false);
monitor.beginTask("build CG", 1);
CallGraph CG = B.makeCallGraph(B.getOptions(), monitor);
monitor.done();
CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
}
@ -713,51 +687,4 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
// verifyGraphAssertions(CG, assertionsForDateProperty);
}
protected IVector<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) {
// Created by reversing the points to mapping for local pointer keys.
// Instead of mapping (local) pointer keys to instance keys (with id), we
// map instance keys to VnInContext (which carry the same information as
// local pointer keys)
final IVector<Set<Pair<CGNode, Integer>>> ret = new SparseVector<Set<Pair<CGNode, Integer>>>();
for (PointerKey pk : pa.getPointerKeys()) {
if (pk instanceof LocalPointerKey) {
final LocalPointerKey lpk = (LocalPointerKey) pk;
// we filter out local pointer keys that have no uses.
// NOTE: do to some weird behavior, we get pointer keys with vns that
// don't exist, so we have to filter those before asking about uses.
if (lpk.getNode().getDU().getDef(lpk.getValueNumber()) != null) {
Iterator<SSAInstruction> uses = lpk.getNode().getDU().getUses(lpk.getValueNumber());
if (uses.hasNext()) {
OrdinalSet<InstanceKey> pointsToSet = pa.getPointsToSet(pk);
if (pointsToSet == null || pointsToSet.getBackingSet() == null)
continue;
pointsToSet.getBackingSet().foreach(new IntSetAction() {
@Override
public void act(int ikId) {
Set<Pair<CGNode, Integer>> s = ret.get(ikId);
if (s == null) {
s = HashSetFactory.make();
ret.set(ikId, s);
}
s.add(Pair.make(lpk.getNode(), lpk.getValueNumber()));
}
});
} else {
int i = 0;
i++;
}
} else {
int i = 0;
i++;
}
}
}
return ret;
}
}

View File

@ -16,6 +16,7 @@ import java.net.URL;
import org.junit.Before;
import org.junit.Test;
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.html.IHtmlParser;
import com.ibm.wala.cast.js.html.IHtmlParserFactory;
import com.ibm.wala.cast.js.html.WebUtil;
@ -269,7 +270,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
// JSCallGraphBuilderUtil.AVOID_DUMP = false;
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifySourceAssertions(CG, sourceAssertionsForList);
}
@ -291,9 +292,23 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
URL url = getClass().getClassLoader().getResource("pages/windowx.html");
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForWindowx);
}
private static final Object[][] assertionsForWindowOnload = new Object[][] {
new Object[] { ROOT, new String[] { "windowonload.html" } },
new Object[] { "windowonload.html", new String[] { "windowonload.html/__WINDOW_MAIN__" } },
new Object[] { "windowonload.html/__WINDOW_MAIN__", new String[] { "windowonload.html/__WINDOW_MAIN__/onload_handler" } },
};
@Test public void testWindowOnload() throws IOException, IllegalArgumentException, CancelException, WalaException {
URL url = getClass().getClassLoader().getResource("pages/windowonload.html");
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForWindowOnload);
}
/*
@Test public void testJQuery() throws IOException, IllegalArgumentException, CancelException, WalaException {

View File

@ -27,14 +27,14 @@ public class TestWebUtil extends WalaTestCase {
@Test public void testAjaxslt() throws Error {
URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html");
Assert.assertTrue(url != null);
Set<MappedSourceModule> mod = WebUtil.extractScriptFromHTML( url ).fst;
Set<MappedSourceModule> mod = WebUtil.extractScriptFromHTML( url, true ).fst;
Assert.assertTrue(mod != null);
}
@Test public void testAjaxpath() throws Error {
URL url = getClass().getClassLoader().getResource("ajaxslt/test/xpath.html");
Assert.assertTrue(url != null);
Set<MappedSourceModule> mod = WebUtil.extractScriptFromHTML( url ).fst;
Set<MappedSourceModule> mod = WebUtil.extractScriptFromHTML( url, true ).fst;
Assert.assertTrue(mod != null);
}
}

View File

@ -7,7 +7,8 @@ Bundle-ClassPath: .,
lib/jericho-html-3.2.jar
Bundle-Activator: com.ibm.wala.cast.js.JavaScriptPlugin
Bundle-Vendor: IBM
Export-Package: com.ibm.wala.cast.js,
Export-Package: .,
com.ibm.wala.cast.js,
com.ibm.wala.cast.js.analysis.typeInference,
com.ibm.wala.cast.js.callgraph.fieldbased,
com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph,

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.ibm.wala.cast.java.polyglot" default="getJars" basedir=".">
<project name="com.ibm.wala.cast.js" default="getJars" basedir=".">
<property name="basews" value="${ws}"/>
<property name="baseos" value="${os}"/>

View File

@ -80,11 +80,11 @@ Object.prototype = {
constructor: Object,
toString: function toString() {
toString: function Object_prototype_toString() {
return primitive("ObjectToString", this);
},
toLocaleString: function toLocaleString() {
toLocaleString: function Object_prototype_toLocaleString() {
return primitive("ObjectToLocaleString", this);
},
@ -196,6 +196,13 @@ local_array.prototype = {
push: function Array_prototype_push () {
var n = this.length;
// nasty hack for field-sensitive builders
// TODO: fix this somehow
if (n == 0) {
this[0] = arguments[0];
}
for(var i = 0; i < arguments.length; i++) {
this[ n++ ] = arguments[i];
}

View File

@ -10,24 +10,20 @@
*****************************************************************************/
package com.ibm.wala.cast.js.callgraph.fieldbased;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cast.ipa.callgraph.AstContextInsensitiveSSAContextInterpreter;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.AbstractVertexVisitor;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.CallVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.FuncVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VarVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.Vertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VertexFactory;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraph;
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptConstructTargetSelector;
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptEntryPoints;
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionDotCallTargetSelector;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.types.AstMethodReference;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
@ -41,16 +37,18 @@ import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.cfa.DefaultSSAInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.cfa.DelegatingSSAContextInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.collections.Util;
import com.ibm.wala.util.intset.OrdinalSet;
/**
* Abstract call graph builder class for building a call graph from a field-based flow graph.
@ -87,6 +85,11 @@ public abstract class FieldBasedCallGraphBuilder {
return result;
}
protected FlowGraph flowGraphFactory() {
FlowGraphBuilder builder = new FlowGraphBuilder(cha, cache);
return builder.buildFlowGraph();
}
/**
* Build a flow graph for the program to be analysed.
*/
@ -95,12 +98,14 @@ public abstract class FieldBasedCallGraphBuilder {
/**
* Main entry point: builds a flow graph, then extracts a call graph and returns it.
*/
public JSCallGraph buildCallGraph(IProgressMonitor monitor) throws CancelException {
public Pair<JSCallGraph,PointerAnalysis> buildCallGraph(Iterable<Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
long fgBegin, fgEnd, cgBegin, cgEnd;
if(LOG_TIMINGS) fgBegin = System.currentTimeMillis();
MonitorUtil.beginTask(monitor, "flow graph", 1);
FlowGraph flowGraph = buildFlowGraph(monitor);
MonitorUtil.done(monitor);
if(LOG_TIMINGS) {
fgEnd = System.currentTimeMillis();
@ -108,29 +113,29 @@ public abstract class FieldBasedCallGraphBuilder {
cgBegin = System.currentTimeMillis();
}
JSCallGraph cg = extract(flowGraph, monitor);
MonitorUtil.beginTask(monitor, "extract call graph", 1);
JSCallGraph cg = extract(flowGraph, eps, monitor);
MonitorUtil.done(monitor);
if(LOG_TIMINGS) {
cgEnd = System.currentTimeMillis();
System.out.println("call graph extraction took " + (cgEnd-cgBegin)/1000.0 + " seconds");
}
return cg;
return Pair.make(cg,flowGraph.getPointerAnalysis(monitor));
}
/**
* Extract a call graph from a given flow graph.
*/
@SuppressWarnings("deprecation")
protected JSCallGraph extract(FlowGraph flowgraph, IProgressMonitor monitor) throws CancelException {
// set up call graph
protected JSCallGraph extract(FlowGraph flowgraph, Iterable<Entrypoint> eps, IProgressMonitor monitor) throws CancelException {
// set up call graph
final JSCallGraph cg = new JSCallGraph(cha, options, cache);
cg.init();
cg.setInterpreter(new DelegatingSSAContextInterpreter(new AstContextInsensitiveSSAContextInterpreter(options, cache), new DefaultSSAInterpreter(options, cache)));
// set up call edges from fake root to all script nodes
JavaScriptEntryPoints eps = new JavaScriptEntryPoints(cha, cha.getLoader(JavaScriptTypes.jsLoader));
// set up call edges from fake root to all script nodes
AbstractRootMethod fakeRootMethod = (AbstractRootMethod)cg.getFakeRootNode().getMethod();
CGNode fakeRootNode = cg.findOrCreateNode(fakeRootMethod, Everywhere.EVERYWHERE);
for(Iterator<Entrypoint> iter = eps.iterator(); iter.hasNext();) {
@ -145,65 +150,73 @@ public abstract class FieldBasedCallGraphBuilder {
// now add genuine call edges
Set<Pair<CallVertex, FuncVertex>> edges = extractCallGraphEdges(flowgraph, monitor);
for (Pair<CallVertex, FuncVertex> edge : edges) {
CallVertex callVertex = edge.fst;
FuncVertex targetVertex = edge.snd;
IClass kaller = callVertex.getCaller().getConcreteType();
CGNode caller = cg.findOrCreateNode(kaller.getMethod(AstMethodReference.fnSelector), Everywhere.EVERYWHERE);
CallSiteReference site = callVertex.getSite();
IMethod target = targetSelector.getCalleeTarget(caller, site, targetVertex.getConcreteType());
if (caller.toString().contains("string_ctor"))
System.err.println(caller + " " + site + " " + target);
boolean isFunctionPrototypeCall = target != null
&& target.getName().toString().startsWith(JavaScriptFunctionDotCallTargetSelector.SYNTHETIC_CALL_METHOD_PREFIX);
if (isFunctionPrototypeCall) {
handleFunctionPrototypeCallInvocation(flowgraph, monitor, cg, callVertex, caller, site, target);
} else {
addEdgeToJSCallGraph(cg, site, target, caller);
}
}
for (Pair<CallVertex, FuncVertex> edge : edges) {
CallVertex callVertex = edge.fst;
FuncVertex targetVertex = edge.snd;
IClass kaller = callVertex.getCaller().getIClass();
CGNode caller = cg.findOrCreateNode(kaller.getMethod(AstMethodReference.fnSelector), Everywhere.EVERYWHERE);
CallSiteReference site = callVertex.getSite();
IMethod target = targetSelector.getCalleeTarget(caller, site, targetVertex.getIClass());
boolean isFunctionPrototypeCall = target != null
&& target.getName().toString().startsWith(JavaScriptFunctionDotCallTargetSelector.SYNTHETIC_CALL_METHOD_PREFIX);
if (isFunctionPrototypeCall) {
handleFunctionPrototypeCallInvocation(flowgraph, monitor, cg, callVertex, caller, site, target);
} else {
addEdgeToJSCallGraph(cg, site, target, caller);
}
}
return cg;
}
private void handleFunctionPrototypeCallInvocation(FlowGraph flowgraph, IProgressMonitor monitor, final JSCallGraph cg,
private boolean handleFunctionPrototypeCallInvocation(FlowGraph flowgraph, IProgressMonitor monitor, final JSCallGraph cg,
CallVertex callVertex, CGNode caller, CallSiteReference site,
IMethod target) throws CancelException {
// use to get 1-level of call string for Function.prototype.call, to
// preserve the precision of the field-based call graph
final nCFAContextSelector functionPrototypeCallSelector = new nCFAContextSelector(1, new ContextInsensitiveSelector());
Context calleeContext = functionPrototypeCallSelector.getCalleeTarget(caller, site, target, null);
addCGEdgeWithContext(cg, site, target, caller, calleeContext);
boolean ret = addCGEdgeWithContext(cg, site, target, caller, calleeContext);
CGNode functionPrototypeCallNode = cg.findOrCreateNode(target, calleeContext);
// need to create nodes for reflective targets of call, and then add them
// as callees of the synthetic method
Collection<FuncVertex> reflectiveTargets = getReflectiveTargets(flowgraph, callVertex, monitor);
OrdinalSet<FuncVertex> reflectiveTargets = getReflectiveTargets(flowgraph, callVertex, monitor);
// there should only be one call site in the synthetic method
CallSiteReference reflectiveCallSite = functionPrototypeCallNode.getIR().iterateCallSites().next();
for (FuncVertex f : reflectiveTargets) {
IMethod reflectiveTgtMethod = targetSelector.getCalleeTarget(functionPrototypeCallNode, reflectiveCallSite, f.getIClass());
addEdgeToJSCallGraph(cg, reflectiveCallSite, reflectiveTgtMethod, functionPrototypeCallNode);
IMethod reflectiveTgtMethod = targetSelector.getCalleeTarget(functionPrototypeCallNode, reflectiveCallSite, f.getConcreteType());
ret |= addEdgeToJSCallGraph(cg, reflectiveCallSite, reflectiveTgtMethod, functionPrototypeCallNode);
}
return ret;
}
private IMethod addEdgeToJSCallGraph(final JSCallGraph cg, CallSiteReference site, IMethod target, CGNode caller)
private boolean addEdgeToJSCallGraph(final JSCallGraph cg, CallSiteReference site, IMethod target, CGNode caller)
throws CancelException {
return addCGEdgeWithContext(cg, site, target, caller, Everywhere.EVERYWHERE);
}
Set<IClass> constructedTypes = HashSetFactory.make();
Everywhere targetContext = Everywhere.EVERYWHERE;
@SuppressWarnings("deprecation")
private IMethod addCGEdgeWithContext(final JSCallGraph cg, CallSiteReference site, IMethod target, CGNode caller,
private boolean addCGEdgeWithContext(final JSCallGraph cg, CallSiteReference site, IMethod target, CGNode caller,
Context targetContext) throws CancelException {
boolean ret = false;
if(target != null) {
CGNode callee = cg.findOrCreateNode(target, targetContext);
// add nodes first, to be on the safe side
cg.addNode(caller); cg.addNode(callee);
cg.addNode(caller);
cg.addNode(callee);
// add callee as successor of caller
cg.addEdge(caller, callee);
// add as site-specific target
caller.addTarget(site, callee);
ret = !cg.getPossibleTargets(caller, site).contains(callee);
if (ret) {
cg.addEdge(caller, callee);
caller.addTarget(site, callee);
}
}
return target;
return ret;
}
/**
@ -211,10 +224,10 @@ public abstract class FieldBasedCallGraphBuilder {
* FuncVertex nodes for the reflectively-invoked methods
* @throws CancelException
*/
private Collection<FuncVertex> getReflectiveTargets(FlowGraph flowGraph, CallVertex callVertex, IProgressMonitor monitor) throws CancelException {
private OrdinalSet<FuncVertex> getReflectiveTargets(FlowGraph flowGraph, CallVertex callVertex, IProgressMonitor monitor) throws CancelException {
SSAAbstractInvokeInstruction invoke = callVertex.getInstruction();
VarVertex functionParam = flowGraph.getVertexFactory().makeVarVertex(callVertex.getCaller(), invoke.getUse(1));
return Util.filterByType(flowGraph.getReachingSet(functionParam, monitor), FuncVertex.class);
return flowGraph.getReachingSet(functionParam, monitor);
}
/**
@ -226,14 +239,13 @@ public abstract class FieldBasedCallGraphBuilder {
// find all pairs <call, func> such that call is reachable from func in the flow graph
for(final CallVertex callVertex : factory.getCallVertices()) {
for(Vertex v : flowgraph.getReachingSet(callVertex, monitor)) {
v.accept(new AbstractVertexVisitor<Void>() {
@Override
public Void visitFuncVertex(FuncVertex funcVertex) {
result.add(Pair.make(callVertex, funcVertex));
return null;
}
});
if (callVertex.getCaller().getFullName().contains("string_ctor")) {
System.err.println(callVertex.getCaller().getFullName());
System.err.println(callVertex.getInstruction());
System.err.println(flowgraph.getReachingSet(callVertex, monitor));
}
for(FuncVertex funcVertex : flowgraph.getReachingSet(callVertex, monitor)) {
result.add(Pair.make(callVertex, funcVertex));
}
}

View File

@ -55,7 +55,7 @@ public class JSMethodInstructionVisitor extends JSAbstractInstructionVisitor {
if(fndef instanceof AstGlobalRead) {
AstGlobalRead agr = (AstGlobalRead)fndef;
if(agr.getGlobalName().equals("global Function")) {
if(invk.getNumberOfParameters() == 0)
if(invk.getNumberOfParameters() < 2)
return false;
// this may be a genuine use of "new Function()", not a declaration/expression
if(!symtab.isStringConstant(invk.getUse(1)))

View File

@ -13,11 +13,9 @@ package com.ibm.wala.cast.js.callgraph.fieldbased;
import java.util.Set;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.CallVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.FuncVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VarVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.Vertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VertexFactory;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ssa.JavaScriptInvoke;
@ -30,7 +28,6 @@ import com.ibm.wala.util.MonitorUtil;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.collections.Util;
import com.ibm.wala.util.intset.OrdinalSet;
/**
@ -53,8 +50,7 @@ public class OptimisticCallgraphBuilder extends FieldBasedCallGraphBuilder {
@Override
public FlowGraph buildFlowGraph(IProgressMonitor monitor) throws CancelException {
FlowGraphBuilder builder = new FlowGraphBuilder(cha, cache);
FlowGraph flowgraph = builder.buildFlowGraph();
FlowGraph flowgraph = flowGraphFactory();
// keep track of which call edges we already know about
Set<Pair<CallVertex, FuncVertex>> knownEdges = HashSetFactory.make();
@ -99,11 +95,13 @@ public class OptimisticCallgraphBuilder extends FieldBasedCallGraphBuilder {
JavaScriptInvoke invk = c.getInstruction();
FuncVertex caller = c.getCaller();
for(int i=1;i<invk.getNumberOfParameters();++i)
for(int i=1;i<invk.getNumberOfParameters();++i) {
// only flow receiver into 'this' if invk is, in fact, a method call
flowgraph.addEdge(factory.makeVarVertex(caller, invk.getUse(i)), factory.makeArgVertex(callee));
if(i > 1 || invk.getDeclaredTarget().equals(JavaScriptMethods.dispatchReference))
flowgraph.addEdge(factory.makeVarVertex(caller, invk.getUse(i)), factory.makeParamVertex(callee, i-1));
}
// flow from return vertex to result vertex
flowgraph.addEdge(factory.makeRetVertex(callee), factory.makeVarVertex(caller, invk.getDef()));
}
@ -116,8 +114,7 @@ public class OptimisticCallgraphBuilder extends FieldBasedCallGraphBuilder {
JavaScriptInvoke invk = c.getInstruction();
VarVertex receiverVertex = factory.makeVarVertex(caller, invk.getUse(1));
OrdinalSet<Vertex> reachingSet = flowgraph.getReachingSet(receiverVertex, monitor);
Set<FuncVertex> realCallees = Util.filterByType(reachingSet, FuncVertex.class);
OrdinalSet<FuncVertex> realCallees = flowgraph.getReachingSet(receiverVertex, monitor);
for(FuncVertex realCallee: realCallees) {
// flow from arguments to parameters
for(int i=2;i<invk.getNumberOfParameters();++i)

View File

@ -13,11 +13,11 @@ package com.ibm.wala.cast.js.callgraph.fieldbased;
import java.util.Iterator;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.FlowGraphBuilder;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.FuncVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VertexFactory;
import com.ibm.wala.cast.js.ssa.JavaScriptInvoke;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.types.AstMethodReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
@ -46,17 +46,20 @@ public class PessimisticCallGraphBuilder extends FieldBasedCallGraphBuilder {
@Override
public FlowGraph buildFlowGraph(IProgressMonitor monitor) {
FlowGraphBuilder builder = new FlowGraphBuilder(cha, cache);
FlowGraph flowgraph = builder.buildFlowGraph();
resolveLocalCalls(flowgraph);
FlowGraph flowgraph = flowGraphFactory();
resolveLocalCalls(flowgraph);
return flowgraph;
}
protected boolean filterFunction(IMethod function) {
return function.getDescriptor().equals(AstMethodReference.fnDesc);
}
// add inter-procedural flow for local calls
private void resolveLocalCalls(FlowGraph flowgraph) {
for(IClass klass : cha) {
for(IMethod method : klass.getDeclaredMethods()) {
if(method.getDescriptor().equals(AstMethodReference.fnDesc)) {
if (filterFunction(method)) {
IR ir = cache.getIR(method);
ir.visitAllInstructions(new LocalCallSSAVisitor(method, ir.getSymbolTable(), cache.getDefUse(ir), flowgraph));
}
@ -92,6 +95,10 @@ public class PessimisticCallGraphBuilder extends FieldBasedCallGraphBuilder {
// the name of the function
String fnName = symtab.getStringValue(invk.getUse(1));
IClass fnClass = cha.lookupClass(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, fnName));
if (fnClass == null) {
System.err.println("cannot find " + fnName + " at " + ((AstMethod)method).getSourcePosition());
return;
}
IMethod fn = fnClass.getMethod(AstMethodReference.fnSelector);
FuncVertex callee = factory.makeFuncVertex(fnClass);

View File

@ -136,6 +136,7 @@ public class WorklistBasedOptimisticCallgraphBuilder extends FieldBasedCallGraph
for(int i=1;i<invk.getNumberOfParameters();++i) {
// only flow receiver into 'this' if invk is, in fact, a method call
flowgraph.addEdge(factory.makeVarVertex(caller, invk.getUse(i)), factory.makeArgVertex(callee));
if(i > 1 || invk.getDeclaredTarget().equals(JavaScriptMethods.dispatchReference))
addFlowEdge(flowgraph, factory.makeVarVertex(caller, invk.getUse(i)), factory.makeParamVertex(callee, i-1), worklist);
}

View File

@ -10,16 +10,27 @@
*******************************************************************************/
package com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph;
import java.util.Collection;
import java.util.Iterator;
import com.ibm.wala.analysis.pointers.HeapGraph;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.AbstractVertexVisitor;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.FuncVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.UnknownVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VarVertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.Vertex;
import com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices.VertexFactory;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.Predicate;
import com.ibm.wala.util.collections.IndiscriminateFilter;
import com.ibm.wala.util.collections.Filter;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.GraphReachability;
import com.ibm.wala.util.graph.GraphSlicer;
@ -27,6 +38,7 @@ import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.impl.InvertedGraph;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
import com.ibm.wala.util.intset.OrdinalSet;
import com.ibm.wala.util.intset.OrdinalSetMapping;
/**
* A flow graph models data flow between vertices representing local variables, properties,
@ -43,7 +55,7 @@ public class FlowGraph implements Iterable<Vertex> {
// the transitive closure of the inverse of this.graph,
// but without paths going through the Unknown vertex
private GraphReachability<Vertex> optimistic_closure;
private GraphReachability<Vertex,FuncVertex> optimistic_closure;
public FlowGraph() {
this.graph = new SlowSparseNumberedGraph<Vertex>(1);
@ -74,8 +86,17 @@ public class FlowGraph implements Iterable<Vertex> {
});
// compute transitive closure
optimistic_closure = new GraphReachability<Vertex>(new InvertedGraph<Vertex>(pruned_flowgraph),
IndiscriminateFilter.singleton());
optimistic_closure =
new GraphReachability<Vertex,FuncVertex>(
new InvertedGraph<Vertex>(pruned_flowgraph),
new Filter<Vertex>() {
@Override
public boolean accepts(Vertex o) {
return o instanceof FuncVertex;
}
}
);
optimistic_closure.solve(monitor);
}
@ -103,7 +124,7 @@ public class FlowGraph implements Iterable<Vertex> {
* Computes the set of vertices that may reach <code>dest</code> along paths not containing an
* {@link UnknownVertex}.
*/
public OrdinalSet<Vertex> getReachingSet(Vertex dest, IProgressMonitor monitor) throws CancelException {
public OrdinalSet<FuncVertex> getReachingSet(Vertex dest, IProgressMonitor monitor) throws CancelException {
if(!graph.containsNode(dest))
return OrdinalSet.empty();
@ -119,4 +140,68 @@ public class FlowGraph implements Iterable<Vertex> {
public Iterator<Vertex> iterator() {
return graph.iterator();
}
public PointerAnalysis getPointerAnalysis(final IProgressMonitor monitor) {
return new PointerAnalysis() {
@Override
public OrdinalSet<? extends InstanceKey> getPointsToSet(PointerKey key) {
if (key instanceof LocalPointerKey) {
CGNode node = ((LocalPointerKey)key).getNode();
FuncVertex fn = factory.makeFuncVertex(node.getMethod().getDeclaringClass());
int vn = ((LocalPointerKey)key).getValueNumber();
VarVertex v = factory.makeVarVertex(fn, vn);
try {
return getReachingSet(v, monitor);
} catch (CancelException e) {
return null;
}
} else {
return null;
}
}
@Override
public OrdinalSetMapping<InstanceKey> getInstanceKeyMapping() {
// TODO Auto-generated method stub
return null;
}
@Override
public Iterable<PointerKey> getPointerKeys() {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<InstanceKey> getInstanceKeys() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isFiltered(PointerKey pk) {
return false;
}
@Override
public HeapModel getHeapModel() {
assert false;
return null;
}
@Override
public HeapGraph getHeapGraph() {
assert false;
return null;
}
@Override
public IClassHierarchy getClassHierarchy() {
assert false;
return null;
}
};
}
}

View File

@ -28,6 +28,7 @@ import com.ibm.wala.cast.js.ssa.JavaScriptPropertyWrite;
import com.ibm.wala.cast.js.ssa.PrototypeLookup;
import com.ibm.wala.cast.js.types.JavaScriptMethods;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.js.util.Util;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
import com.ibm.wala.cast.types.AstMethodReference;
@ -79,36 +80,45 @@ public class FlowGraphBuilder {
addPrimitives(flowgraph);
for(IClass klass : cha) {
for(IMethod method : klass.getDeclaredMethods()) {
if(method.getDescriptor().equals(AstMethodReference.fnDesc)) {
IR ir = cache.getIR(method);
FlowGraphSSAVisitor visitor = new FlowGraphSSAVisitor(ir, flowgraph);
// first visit normal instructions
SSAInstruction[] normalInstructions = ir.getInstructions();
for(int i=0;i<normalInstructions.length;++i)
if(normalInstructions[i] != null) {
visitor.instructionIndex = i;
normalInstructions[i].visit(visitor);
}
// now visit phis and catches
visitor.instructionIndex = -1;
for(Iterator<? extends SSAInstruction> iter=ir.iteratePhis();iter.hasNext();)
iter.next().visit(visitor);
for(Iterator<SSAInstruction> iter=ir.iterateCatchInstructions();iter.hasNext();)
iter.next().visit(visitor);
}
}
}
visitProgram(flowgraph);
return flowgraph;
}
protected void visitProgram(FlowGraph flowgraph) {
for(IClass klass : cha) {
for(IMethod method : klass.getDeclaredMethods()) {
if(method.getDescriptor().equals(AstMethodReference.fnDesc))
visitFunction(flowgraph, method);
}
}
}
protected void visitFunction(FlowGraph flowgraph, IMethod method) {
{
IR ir = cache.getIR(method);
FlowGraphSSAVisitor visitor = new FlowGraphSSAVisitor(ir, flowgraph);
// first visit normal instructions
SSAInstruction[] normalInstructions = ir.getInstructions();
for(int i=0;i<normalInstructions.length;++i)
if(normalInstructions[i] != null) {
visitor.instructionIndex = i;
normalInstructions[i].visit(visitor);
}
// now visit phis and catches
visitor.instructionIndex = -1;
for(Iterator<? extends SSAInstruction> iter=ir.iteratePhis();iter.hasNext();)
iter.next().visit(visitor);
for(Iterator<SSAInstruction> iter=ir.iterateCatchInstructions();iter.hasNext();)
iter.next().visit(visitor);
}
}
// primitive functions that are treated specially
private static String[] primitiveFunctions = { "Object", "Function", "Array", "String", "Number", "RegExp" };
private static String[] primitiveFunctions = { "Object", "Function", "Array", "StringObject", "NumberObject", "BooleanObject", "RegExp" };
/**
* Add flows from the special primitive functions to the corresponding global variables.
@ -120,7 +130,8 @@ public class FlowGraphBuilder {
for(String pf : primitiveFunctions) {
TypeReference typeref = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, "L" + pf);
IClass klass = cha.lookupClass(typeref);
flowgraph.addEdge(factory.makeFuncVertex(klass), factory.makePropVertex(pf));
String prop = pf.endsWith("Object")? pf.substring(0, pf.length() - 6): pf;
flowgraph.addEdge(factory.makeFuncVertex(klass), factory.makePropVertex(prop));
}
}
@ -278,6 +289,14 @@ public class FlowGraphBuilder {
w = factory.makeVarVertex(func, pr.getDef());
flowgraph.addEdge(v, w);
}
IntSet argVns = Util.getArgumentsArrayVns(ir, du);
if (argVns.contains(pr.getObjectRef())) {
Vertex v = factory.makeArgVertex(func),
w = factory.makeVarVertex(func, pr.getDef());
flowgraph.addEdge(v, w);
}
handleLexicalDef(pr.getDef());
}
@ -324,6 +343,10 @@ public class FlowGraphBuilder {
// find the function being defined here
IClass klass = cha.lookupClass(TypeReference.findOrCreate(JavaScriptTypes.jsLoader, fn_name));
if (klass == null) {
System.err.println("cannot find " + fn_name + " at " + ((AstMethod)ir.getMethod()).getSourcePosition(ir.getCallInstructionIndices(invk.getCallSite()).intIterator().next()));
return;
}
IMethod fn = klass.getMethod(AstMethodReference.fnSelector);
FuncVertex fnVertex = factory.makeFuncVertex(klass);

View File

@ -50,6 +50,11 @@ public class AbstractVertexVisitor<T> implements VertexVisitor<T> {
return visitVertex(retVertex);
}
@Override
public T visitArgVertex(ArgVertex argVertex) {
return visitVertex(argVertex);
}
@Override
public T visitCalleeVertex(CallVertex calleeVertex) {
return visitVertex(calleeVertex);

View File

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2002 - 2012 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.callgraph.fieldbased.flowgraph.vertices;
/**
* A return vertex represents the 'arguments' array of a given function.
*
* @author Julian Dolby (dolby@us.ibm.com)
*
*/
public class ArgVertex extends Vertex {
private final FuncVertex func;
ArgVertex(FuncVertex func) {
this.func = func;
}
public FuncVertex getFunc() {
return func;
}
@Override
public <T> T accept(VertexVisitor<T> visitor) {
return visitor.visitArgVertex(this);
}
@Override
public String toString() {
return "Args(" + func + ")";
}
}

View File

@ -10,7 +10,14 @@
*****************************************************************************/
package com.ibm.wala.cast.js.callgraph.fieldbased.flowgraph.vertices;
import java.util.Iterator;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.util.collections.Pair;
/**
* A function vertex represents a function object (or, more precisely, all function objects
@ -18,7 +25,7 @@ import com.ibm.wala.classLoader.IClass;
*
* @author mschaefer
*/
public class FuncVertex extends Vertex {
public class FuncVertex extends Vertex implements InstanceKey {
// the IClass representing this function in the class hierarchy
private final IClass klass;
@ -26,7 +33,8 @@ public class FuncVertex extends Vertex {
this.klass = method;
}
public IClass getIClass() {
@Override
public IClass getConcreteType() {
return klass;
}
@ -44,4 +52,10 @@ public class FuncVertex extends Vertex {
String methodName = klass.getName().toString();
return "Func(" + methodName.substring(methodName.lastIndexOf('/')+1) + ")";
}
@Override
public Iterator<Pair<CGNode, NewSiteReference>> getCreationSites(CallGraph CG) {
assert false;
return null;
}
}

View File

@ -31,6 +31,7 @@ public class VertexFactory {
private final Map<Pair<FuncVertex, Integer>, ParamVertex> paramVertexCache = HashMapFactory.make();
private final Map<String, PropVertex> propVertexCache = HashMapFactory.make();
private final Map<FuncVertex, RetVertex> retVertexCache = HashMapFactory.make();
private final Map<FuncVertex, ArgVertex> argVertexCache = HashMapFactory.make();
private final Map<Pair<FuncVertex, Integer>, VarVertex> varVertexCache = HashMapFactory.make();
private final Map<Pair<String, String>, LexicalVarVertex> lexicalAccessVertexCache = HashMapFactory.make();
@ -84,6 +85,13 @@ public class VertexFactory {
return value;
}
public ArgVertex makeArgVertex(FuncVertex func) {
ArgVertex value = argVertexCache.get(func);
if(value == null)
argVertexCache.put(func, value = new ArgVertex(func));
return value;
}
public UnknownVertex makeUnknownVertex() {
return UnknownVertex.INSTANCE;
}

View File

@ -20,4 +20,5 @@ public interface VertexVisitor<T> {
public abstract T visitRetVertex(RetVertex retVertex);
public abstract T visitCalleeVertex(CallVertex calleeVertex);
public abstract T visitLexicalAccessVertex(LexicalVarVertex lexicalAccessVertex);
public abstract T visitArgVertex(ArgVertex argVertex);
}

View File

@ -53,9 +53,9 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
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));
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a), true);
} catch (MalformedURLException ex) {
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl, false);
}
}
}
@ -84,7 +84,7 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
if (pos == null){
domRegion.println(indentedLine.toString());
} else {
domRegion.println(indentedLine.toString(), pos, entrypointUrl);
domRegion.println(indentedLine.toString(), pos, entrypointUrl, false);
}
}
@ -93,6 +93,7 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
}
private String makeRef(String object, String property) {
assert object != null && property != null;
return object + "[\"" + property + "\"]";
}
@ -135,6 +136,7 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
}
}
assert varName != null && !"".equals(varName);
printlnIndented(varName + " = this;", tag);
printlnIndented("document." + varName + " = this;", tag);
printlnIndented("parent.appendChild(this);", tag);
@ -149,18 +151,18 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
//There should probably be more checking to see what the attributes are since we allow things like: ; to be used as attributes now.
if(attr.length() >= 2 && 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);
entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl, false);
} else if (value != null) {
if (value.indexOf('\'') > 0) {
value = value.replaceAll("\\'", "\\\\'");
}
if (value.indexOf('\n') > 0) {
value = value.replaceAll("\\n", "\\\\n");
}
Pair<String, Character> x = quotify(value);
value = x.fst;
char quote = x.snd;
if (attr.equals(attr.toUpperCase())) {
attr = attr.toLowerCase();
}
printlnIndented(varName + "['" + attr + "'] = '" + value + "';", tag);
printlnIndented(varName + "['" + attr + "'] = " + quote + value + quote + ";", tag);
}
}

View File

@ -12,9 +12,11 @@ package com.ibm.wala.cast.js.html;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
@ -28,9 +30,15 @@ import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
/**
* extracts JavaScript source code from HTML, with no model of the actual
* DOM data structure
*/
public class DomLessSourceExtractor extends JSSourceExtractor {
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("^[a-zA-Z$_][a-zA-Z\\d$_]*$");
private static final Pattern LEGAL_JS_KEYWORD_REGEXP = Pattern.compile("^((break)|(case)|(catch)|(continue)|(debugger)|(default)|(delete)|(do)|(else)|(finally)|(for)|(function)|(if)|(in)|(instanceof)|(new)|(return)|(switch)|(this)|(throw)|(try)|(typeof)|(var)|(void)|(while)|(with))$");
protected interface IGeneratorCallback extends IHtmlCallback {
void writeToFinalRegion(SourceRegion finalRegion);
}
@ -57,8 +65,14 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
this.scriptRegion = new SourceRegion();
this.domRegion = new SourceRegion();
this.entrypointRegion = new SourceRegion();
addDefaultHandlerInvocations();
}
private void addDefaultHandlerInvocations() {
// always invoke window.onload
entrypointRegion.println("window.onload();");
}
protected Position makePos(int lineNumber, ITag governingTag) {
return makePos(entrypointUrl, lineNumber, governingTag);
}
@ -91,7 +105,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
e.printStackTrace();
}
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
scriptRegion.println(text, currentScriptTag.getContentPosition(), url, true);
}
}
@ -106,6 +120,12 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
handleDOM(tag);
}
private boolean isUsableIdentifier(String x) {
return x != null &&
LEGAL_JS_IDENTIFIER_REGEXP.matcher(x).matches() &&
!LEGAL_JS_KEYWORD_REGEXP.matcher(x).matches();
}
/**
* Model the HTML DOM
*
@ -117,7 +137,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
// running counter
Pair<String,Position> idAttribute = tag.getAttributeByName("id");
String funcName;
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
if (idAttribute != null && isUsableIdentifier(idAttribute.fst)) {
funcName = idAttribute.fst;
} else {
funcName = "node" + (nodeCounter++);
@ -149,16 +169,35 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
String signatureLine = "function " + fName + "(event) {";
// Defines the function
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url, true);
// Run it
entrypointRegion.println("\t" + fName + "(null);", pos, url);
entrypointRegion.println("\t" + fName + "(null);", pos, url, true);
}
}
protected static Pair<String,Character> quotify(String value) {
char quote;
if (value.indexOf('"') < 0) {
quote= '"';
} else if (value.indexOf("'") < 0) {
quote= '"';
} else {
quote= '"';
value = value.replaceAll("\"", "\\\"");
}
if (value.indexOf('\n') >= 0) {
value = value.replaceAll("\n", "\\n");
}
return Pair.make(value, quote);
}
private String extructJS(String attValue) {
if (attValue == null){
return "";
}
String content;
if (attValue.toLowerCase().equals("javascript:")) {
content = attValue.substring("javascript:".length());
@ -171,12 +210,12 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
protected void handleScript(ITag tag) {
Pair<String,Position> value = tag.getAttributeByName("src");
Pair<String,Position> content = tag.getAttributeByName("src");
try {
if (value != null) {
if (content != null) {
// script is out-of-line
getScriptFromUrl(value.fst, tag);
getScriptFromUrl(content.fst, tag);
}
} catch (IOException e) {
@ -187,15 +226,16 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
}
private void getScriptFromUrl(String urlAsString, ITag scriptTag) throws IOException, MalformedURLException {
URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
URL scriptSrc = urlResolver.resolve(absoluteUrl);
// URL absoluteUrl = UrlManipulator.relativeToAbsoluteUrl(urlAsString, this.entrypointUrl);
// URL scriptSrc = urlResolver.resolve(absoluteUrl);
URL scriptSrc = new URL(entrypointUrl, urlAsString);
if (scriptSrc == null) { //Error resolving URL
return;
}
InputStream scriptInputStream;
Reader scriptInputStream;
try {
scriptInputStream = scriptSrc.openConnection().getInputStream();
scriptInputStream = new InputStreamReader(scriptSrc.openConnection().getInputStream());
} catch (Exception e) {
//it looks like this happens when we can't resolve the url?
if (DEBUG) {
@ -209,13 +249,13 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
BufferedReader scriptReader = null;
try {
String line;
scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
scriptReader = new BufferedReader(scriptInputStream);
StringBuffer x = new StringBuffer();
while ((line = scriptReader.readLine()) != null) {
x.append(line).append("\n");
}
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc, false);
} finally {
if (scriptReader != null) {
@ -260,7 +300,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
public Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver)
throws IOException, Error {
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
Reader inputStreamReader = WebUtil.getStream(entrypointUrl);
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
@ -270,7 +310,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
// writing the final region into one SourceFileModule.
File outputFile = createOutputFile(entrypointUrl, DELETE_UPON_EXIT, USE_TEMP_NAME);
tempFile = outputFile;
FileMapping fileMapping = finalRegion.writeToFile(new PrintStream(outputFile));
FileMapping fileMapping = finalRegion.writeToFile(new PrintWriter(new FileWriter(outputFile)));
if (fileMapping == null) {
fileMapping = new EmptyFileMapping();
}
@ -284,10 +324,14 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
private File createOutputFile(URL url, boolean delete, boolean useTempName) throws IOException {
File outputFile;
String fileName = new File(url.getFile()).getName();
if (fileName.length() < 5) {
fileName = "xxxx" + fileName;
}
if (useTempName) {
outputFile = File.createTempFile(new File(url.getFile()).getName(), ".js");
outputFile = File.createTempFile(fileName, ".js");
} else {
outputFile = new File(new File(url.getFile()).getName());
outputFile = new File(fileName);
}
if (outputFile.exists()){
outputFile.delete();

View File

@ -10,7 +10,7 @@
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
@ -29,6 +29,6 @@ public interface IHtmlParser {
* @param fileName
* @throws Error
*/
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) throws Error;
public void parse(URL url, Reader reader, IHtmlCallback callback, String fileName) throws Error;
}

View File

@ -11,7 +11,7 @@
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import com.ibm.wala.cast.js.html.RangeFileMapping.Range;
@ -69,8 +69,8 @@ public class NestedRangeMapping implements FileMapping {
}
@Override
public InputStream getInputStream() throws IOException {
return pos.getInputStream();
public Reader getReader() throws IOException {
return pos.getReader();
}
});
} else {

View File

@ -11,7 +11,8 @@
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
@ -19,7 +20,7 @@ import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
public class RangeFileMapping implements FileMapping {
public static class Range {
public final static class Range {
private final int rangeStart;
private final int rangeEnd;
private final int rangeStartingLine;
@ -113,9 +114,9 @@ public class RangeFileMapping implements FileMapping {
return includedURL;
}
@Override
public InputStream getInputStream() throws IOException {
return includedURL.openConnection().getInputStream();
}
public Reader getReader() throws IOException {
return RangeFileMapping.this.getInputStream();
}
@Override
public Position getIncludePosition() {
return includePosition;
@ -132,5 +133,8 @@ public class RangeFileMapping implements FileMapping {
}
}
public Reader getInputStream() throws IOException {
return new InputStreamReader(includedURL.openStream());
}
}

View File

@ -10,7 +10,10 @@
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.io.PrintStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
@ -33,15 +36,25 @@ public class SourceRegion {
public SourceRegion() {
}
public void print(String text, Position originalPos, URL url){
public void print(final String text, Position originalPos, URL url, boolean bogusURL){
int startOffset = source.length();
source.append(text);
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);
RangeFileMapping map;
if (bogusURL) {
map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url) {
@Override
public Reader getInputStream() throws IOException {
return new StringReader(text);
}
};
} else {
map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
}
if (fileMapping == null) {
fileMapping = map;
} else {
@ -52,20 +65,21 @@ public class SourceRegion {
currentLine += numberOfLineDrops;
}
public void println(String text, Position originalPos, URL url){
print(text + "\n", originalPos, url);
public void println(String text, Position originalPos, URL url, boolean bogusURL){
print(text + "\n", originalPos, url, bogusURL);
}
public void print(String text){
print(text, null, null);
print(text, null, null, true);
}
public void println(String text){
print(text + "\n");
}
public FileMapping writeToFile(PrintStream ps){
public FileMapping writeToFile(PrintWriter ps){
ps.print(source.toString());
ps.flush();
return fileMapping;
}
@ -89,7 +103,7 @@ public class SourceRegion {
currentLine += numberOfLineDrops;
}
public void dump(PrintStream ps){
public void dump(PrintWriter ps){
ps.println(source.toString());
}

View File

@ -1,124 +0,0 @@
/******************************************************************************
* 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);
}
}
@Override
public void close() throws IOException {
init();
internalIn2.close();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
init();
return internalIn2.read(cbuf, off, len);
}
}

View File

@ -16,13 +16,17 @@ import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.ssa.JSInstructionFactory;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.rewrite.CAstRewriterFactory;
import com.ibm.wala.cast.tree.visit.CAstVisitor;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.TypeReference;
public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
@ -42,17 +46,21 @@ public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
return new JSAstTranslator(this) {
private final CAst Ast = new CAstImpl();
private boolean isNestedWithinScriptBody(WalkContext context) {
return isScriptBody(context) || context.getName().contains("__WINDOW_MAIN__");
}
private boolean isScriptBody(WalkContext context) {
return context.top().getName().equals( "__WINDOW_MAIN__" );
}
@Override
protected int doGlobalRead(CAstNode n, WalkContext context, String name) {
protected int doGlobalRead(CAstNode n, WalkContext context, String name, TypeReference type) {
int result = context.currentScope().allocateTempValue();
if (isScriptBody(context) && ! "$$undefined".equals(name) && ! "window".equals(name)) {
if (isNestedWithinScriptBody(context) && ! "$$undefined".equals(name) && ! "window".equals(name)) {
// check if field is defined on 'window'
int windowVal = super.doLocalRead(context, "this");
int windowVal = isScriptBody(context)? super.doLocalRead(context, "this", JavaScriptTypes.Root): super.doGlobalRead(n, context, "window", type);
int isDefined = context.currentScope().allocateTempValue();
context.currentScope().getConstantValue(name);
doIsFieldDefined(context, isDefined, windowVal, Ast.makeConstant(name));
@ -73,7 +81,7 @@ public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
// read global
context.cfg().newBlock(false);
PreBasicBlock falseB = context.cfg().getCurrentBlock();
int sr = super.doGlobalRead(n, context, name);
int sr = super.doGlobalRead(n, context, name, type);
context.cfg().addInstruction(((JSInstructionFactory) insts).AssignInstruction(context.cfg().getCurrentInstruction(), result, sr));
// end
@ -85,19 +93,31 @@ public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
return result;
} else {
return super.doGlobalRead(n, context, name);
return super.doGlobalRead(n, context, name, type);
}
}
@Override
protected void doLocalWrite(WalkContext context, String nm, int rval) {
protected void doLocalWrite(WalkContext context, String nm, TypeReference type, int rval) {
if (isScriptBody(context)) {
int windowVal = super.doLocalRead(context, "this");
int windowVal = super.doLocalRead(context, "this", type);
context.currentScope().getConstantValue(nm);
context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), windowVal, rval, nm));
}
super.doLocalWrite(context, nm, rval);
super.doLocalWrite(context, nm, type, rval);
}
@Override
protected void leaveFunctionStmt(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
super.leaveFunctionStmt(n, context, visitor);
if (isScriptBody(context)) {
CAstEntity fn = (CAstEntity) n.getChild(0).getValue();
int fnValue = context.currentScope().lookup(fn.getName()).valueNumber();
assert fnValue > 0;
int windowVal = super.doLocalRead(context, "this", JavaScriptTypes.Function);
context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(context.cfg().getCurrentInstruction(), windowVal, fnValue, fn.getName()));
}
}
};
}

View File

@ -12,7 +12,8 @@ package com.ibm.wala.cast.js.html;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
@ -45,9 +46,9 @@ public class WebUtil {
* such file exists)
* @throws Error
*/
public static Pair<Set<MappedSourceModule>,File> extractScriptFromHTML(URL url) throws Error {
public static Pair<Set<MappedSourceModule>,File> extractScriptFromHTML(URL url, boolean useDOMModel) throws Error {
try {
JSSourceExtractor extractor = new DefaultSourceExtractor();
JSSourceExtractor extractor = useDOMModel? new DefaultSourceExtractor(): new DomLessSourceExtractor();
Set<MappedSourceModule> sources = extractor.extractSources(url, factory.getParser(), new IdentityUrlResolver());
return Pair.make(sources, extractor.getTempFile());
} catch (IOException e) {
@ -56,15 +57,15 @@ public class WebUtil {
}
public static void main(String[] args) throws MalformedURLException, Error {
System.err.println(extractScriptFromHTML(new URL(args[0])));
System.err.println(extractScriptFromHTML(new URL(args[0]), Boolean.parseBoolean(args[1])));
}
public static InputStream getStream(URL url) throws IOException {
public static Reader getStream(URL url) throws IOException {
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(false);
conn.setUseCaches(false);
return conn.getInputStream();
return new InputStreamReader(conn.getInputStream());
}
}

View File

@ -11,7 +11,7 @@
package com.ibm.wala.cast.js.html.jericho;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
@ -102,7 +102,7 @@ public class JerichoHtmlParser implements IHtmlParser{
}
@Override
public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) throws TranslatorToCAst.Error {
public void parse(URL url, Reader reader, IHtmlCallback callback, String fileName) throws TranslatorToCAst.Error {
warnings.clear();
Parser parser = new Parser(callback, fileName);
Source src;
@ -115,7 +115,7 @@ public class JerichoHtmlParser implements IHtmlParser{
parser.parse(e);
}
if (! warnings.isEmpty()) {
throw new TranslatorToCAst.Error(warnings.iterator().next());
throw new TranslatorToCAst.Error(warnings);
}
} catch (IOException e) {
System.err.println("Error parsing file: " + e.getMessage());

View File

@ -10,9 +10,9 @@
*****************************************************************************/
package com.ibm.wala.cast.js.html.jericho;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
@ -57,12 +57,14 @@ public class JerichoTag implements ITag {
@Override
public int getFirstCol() {
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
return -1;
// return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
}
@Override
public int getLastCol() {
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
return -1;
//return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
}
@Override
@ -85,8 +87,8 @@ public class JerichoTag implements ITag {
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(sourceFile);
public Reader getReader() throws IOException {
return new FileReader(sourceFile);
}
};
}
@ -122,7 +124,7 @@ public class JerichoTag implements ITag {
public Pair<Integer, String> getBodyText() {
Segment content = innerElement.getContent();
Integer lineNum = innerElement.getSource().getRow(content.getBegin());
String body = content.toString();
String body = content.toString().replace(content.getSource().getNewLine(), "\n");
return Pair.make(lineNum, body);
}

View File

@ -184,7 +184,7 @@ public class ArgumentSpecialization {
class FixedArgumentsRewriter extends CAstBasicRewriter {
private final CAstEntity e;
Map<String, CAstNode> argRefs = HashMapFactory.make();
private final Map<String, CAstNode> argRefs = HashMapFactory.make();
public FixedArgumentsRewriter(CAst Ast) {
super(Ast, false);

View File

@ -106,5 +106,4 @@ public class JSCallGraph extends AstCallGraph {
}
}
}

View File

@ -117,7 +117,7 @@ public class JSCallGraphUtil extends com.ibm.wala.cast.ipa.callgraph.CAstCallGra
return ClassHierarchy.make(scope, loaders, JavaScriptLoader.JS);
}
public static Iterable<Entrypoint> makeScriptRoots(IClassHierarchy cha) {
public static JavaScriptEntryPoints makeScriptRoots(IClassHierarchy cha) {
return new JavaScriptEntryPoints(cha, cha.getLoader(JavaScriptTypes.jsLoader));
}
@ -130,13 +130,9 @@ public class JSCallGraphUtil extends com.ibm.wala.cast.ipa.callgraph.CAstCallGra
* funName exactly.
*/
public static Collection<CGNode> getNodes(CallGraph CG, String funName) {
boolean ctor = funName.startsWith("ctor:");
boolean suffix = funName.startsWith("suffix:");
if (ctor) {
TypeReference TR = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + funName.substring(5)));
MethodReference MR = JavaScriptMethods.makeCtorReference(TR);
return CG.getNodes(MR);
} else if (suffix) {
if (suffix) {
Set<CGNode> nodes = new HashSet<CGNode>();
String tail = funName.substring(7);
for (CGNode n : CG) {
@ -145,11 +141,24 @@ public class JSCallGraphUtil extends com.ibm.wala.cast.ipa.callgraph.CAstCallGra
}
}
return nodes;
}
MethodReference MR = getMethodReference(funName);
return CG.getNodes(MR);
}
public static MethodReference getMethodReference(String funName) {
boolean ctor = funName.startsWith("ctor:");
MethodReference MR;
if (ctor) {
TypeReference TR = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + funName.substring(5)));
MR = JavaScriptMethods.makeCtorReference(TR);
} else {
TypeReference TR = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("L" + funName));
MethodReference MR = AstMethodReference.fnReference(TR);
return CG.getNodes(MR);
MR = AstMethodReference.fnReference(TR);
}
return MR;
}
/**

View File

@ -55,22 +55,28 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
private final Map<Object, IMethod> constructors = HashMapFactory.make();
class JavaScriptConstructor extends JavaScriptSummarizedFunction {
public static class JavaScriptConstructor extends JavaScriptSummarizedFunction {
private final String toStringExtra;
private JavaScriptConstructor(MethodReference ref, MethodSummary summary, IClass declaringClass, String toStringExtra) {
private final IClass constructorForType;
private JavaScriptConstructor(MethodReference ref, MethodSummary summary, IClass declaringClass, IClass constructorForType, String toStringExtra) {
super(ref, summary, declaringClass);
this.toStringExtra = toStringExtra;
this.constructorForType = constructorForType;
}
private JavaScriptConstructor(MethodReference ref, MethodSummary summary, IClass declaringClass) {
this(ref, summary, declaringClass, "");
private JavaScriptConstructor(MethodReference ref, MethodSummary summary, IClass declaringClass, IClass constructorForType) {
this(ref, summary, declaringClass, constructorForType, "");
}
@Override
public String toString() {
return "<ctor for " + getReference().getDeclaringClass() + toStringExtra + ">";
}
public IClass constructedType() {
return constructorForType;
}
}
public JavaScriptConstructTargetSelector(IClassHierarchy cha, MethodTargetSelector base) {
@ -106,7 +112,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(9, new ConstantValue("__proto__"));
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cls);
}
private IMethod makeUnaryValueConstructor(IClass cls) {
@ -131,7 +137,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(7, new ConstantValue("__proto__"));
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cls);
}
private IMethod makeValueConstructor(IClass cls, int nargs, Object value) {
@ -171,7 +177,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(6, new ConstantValue("__proto__"));
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Object));
}
private IMethod makeUnaryObjectConstructor(IClass cls) {
@ -182,7 +188,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.ReturnInstruction(S.getNumberOfStatements(), 2, false));
S.getNextProgramCounter();
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Object));
}
private IMethod makeObjectConstructor(IClass cls, int nargs) {
@ -234,7 +240,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(7, new ConstantValue("__proto__"));
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Array));
}
private IMethod makeArrayContentsConstructor(IClass cls, int nargs) {
@ -270,7 +276,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(vn, new ConstantValue("__proto__"));
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Array));
}
private IMethod makeArrayConstructor(IClass cls, int nargs) {
@ -291,7 +297,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.ReturnInstruction(S.getNumberOfStatements(), 2, false));
S.getNextProgramCounter();
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.String));
}
private IMethod makeUnaryStringCall(IClass cls) {
@ -308,7 +314,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.ReturnInstruction(S.getNumberOfStatements(), 5, false));
S.getNextProgramCounter();
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.String));
}
private IMethod makeStringCall(IClass cls, int nargs) {
@ -331,7 +337,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.ReturnInstruction(S.getNumberOfStatements(), 2, false));
S.getNextProgramCounter();
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Number));
}
private IMethod makeUnaryNumberCall(IClass cls) {
@ -348,7 +354,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
S.addStatement(insts.ReturnInstruction(S.getNumberOfStatements(), 5, false));
S.getNextProgramCounter();
return new JavaScriptConstructor(ref, S, cls);
return new JavaScriptConstructor(ref, S, cls, cha.lookupClass(JavaScriptTypes.Number));
}
private IMethod makeNumberCall(IClass cls, int nargs) {
@ -395,9 +401,9 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(8, new ConstantValue("__proto__"));
if (receiver != cls)
return record(tableKey, new JavaScriptConstructor(ref, S, receiver, "(" + cls.getReference().getName() + ")"));
return record(tableKey, new JavaScriptConstructor(ref, S, receiver, cls, "(" + cls.getReference().getName() + ")"));
else
return record(tableKey, new JavaScriptConstructor(ref, S, receiver));
return record(tableKey, new JavaScriptConstructor(ref, S, receiver, cls));
}
private int ctorCount = 0;
@ -409,11 +415,11 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
return makeFunctionConstructor(cls, cls);
} else if (nargs == 1) {
if (ST.isStringConstant(callStmt.getUse(1))) {
TypeReference ref = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName((String) ST
TypeReference ref = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName(ST
.getStringValue(callStmt.getUse(1))));
if (DEBUG) {
System.err.println(("ctor type name is " + (String) ST.getStringValue(callStmt.getUse(1))));
System.err.println(("ctor type name is " + ST.getStringValue(callStmt.getUse(1))));
}
IClass cls2 = cha.lookupClass(ref);
@ -511,7 +517,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector {
//S.addConstant(nargs + 9, new ConstantValue("__proto__"));
return record(key, new JavaScriptConstructor(ref, S, cls));
return record(key, new JavaScriptConstructor(ref, S, cls, cls));
}
private IMethod findOrCreateConstructorMethod(IR callerIR, SSAAbstractInvokeInstruction callStmt, IClass receiver, int nargs) {

View File

@ -56,7 +56,7 @@ public class LoadFileTargetSelector implements MethodTargetSelector {
Set<String> names = new HashSet<String>();
SSAInstruction call = caller.getIR().getInstructions()[caller.getIR().getCallInstructionIndices(site).intIterator().next()];
LocalPointerKey fileNameV = new LocalPointerKey(caller, call.getUse(1));
OrdinalSet<InstanceKey> ptrs = builder.getPointerAnalysis().getPointsToSet(fileNameV);
OrdinalSet<? extends InstanceKey> ptrs = builder.getPointerAnalysis().getPointsToSet(fileNameV);
for(InstanceKey k : ptrs) {
if (k instanceof ConstantKey) {
Object v = ((ConstantKey)k).getValue();

View File

@ -262,7 +262,7 @@ public class CorrelationFinder {
} else {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
try {
scripts = WebUtil.extractScriptFromHTML(url).fst;
scripts = WebUtil.extractScriptFromHTML(url, true).fst;
} catch (Error e) {
e.printStackTrace();
assert false : e.warning;

View File

@ -39,6 +39,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
@ -508,7 +509,7 @@ public class ClosureExtractor extends CAstRewriterExt {
}
// prepend declaration "var <theLocal>;"
CAstNode theLocalDecl = Ast.makeNode(DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(theLocal)),
CAstNode theLocalDecl = Ast.makeNode(DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(theLocal, JSAstTranslator.Any)),
addExnFlow(makeVarRef("$$undefined"), JavaScriptTypes.ReferenceError, entity, context));
if(fun_body_stmts.size() > 1) {
CAstNode newBlock = Ast.makeNode(BLOCK_STMT, fun_body_stmts.toArray(new CAstNode[0]));

View File

@ -233,12 +233,6 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
return new JavaScriptInvoke(iindex, function, results, params, exception, site);
}
@Override
public JavaScriptInvoke Invoke(int iindex, int function, int[] results, int[] params, int exception, CallSiteReference site,
Access[] lexicalReads, Access[] lexicalWrites) {
return new JavaScriptInvoke(iindex, function, results, params, exception, site, lexicalReads, lexicalWrites);
}
@Override
public JavaScriptInvoke Invoke(int iindex, int function, int result, int[] params, int exception, CallSiteReference site) {
return new JavaScriptInvoke(iindex, function, result, params, exception, site);
@ -347,8 +341,8 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
}
@Override
public AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName) {
return new AstLexicalRead(iindex, lhs, definer, globalName);
public AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName, TypeReference type) {
return new AstLexicalRead(iindex, lhs, definer, globalName, type);
}
@Override
@ -362,8 +356,8 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
}
@Override
public AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, int rhs) {
return new AstLexicalWrite(iindex, definer, globalName, rhs);
public AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, TypeReference type, int rhs) {
return new AstLexicalWrite(iindex, definer, globalName, type, rhs);
}
@Override
@ -1018,29 +1012,6 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
bootstrapFileNames.add(prologueFileName);
}
/**
* adds the {@link #bootstrapFileNames bootstrap files} to the list of modules
* and then invokes the superclass method
*/
@Override
public void init(List<Module> modules) {
List<Module> all = new LinkedList<Module>();
for (final String fn : bootstrapFileNames) {
all.add(new SourceURLModule(getClass().getClassLoader().getResource(fn)) {
@Override
public String getName() {
return fn;
}
});
}
all.addAll(modules);
super.init(all);
}
@SuppressWarnings("unchecked")
@Override
protected TranslatorToCAst getTranslatorToCAst(final CAst ast, SourceModule module) {

View File

@ -11,7 +11,6 @@
package com.ibm.wala.cast.js.ssa;
import com.ibm.wala.cast.ir.ssa.AstInstructionFactory;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
@ -26,8 +25,6 @@ public interface JSInstructionFactory extends AstInstructionFactory {
JavaScriptInvoke Invoke(int iindex, int function, int results[], int[] params, int exception, CallSiteReference site);
JavaScriptInvoke Invoke(int iindex, int function, int results[], int[] params, int exception, CallSiteReference site, Access[] lexicalReads, Access[] lexicalWrites);
JavaScriptInvoke Invoke(int iindex, int function, int result, int[] params, int exception, CallSiteReference site);
JavaScriptInvoke Invoke(int iindex, int function, int[] params, int exception, CallSiteReference site);

View File

@ -12,8 +12,7 @@ package com.ibm.wala.cast.js.ssa;
import java.util.Collection;
import com.ibm.wala.cast.ir.ssa.AbstractLexicalInvoke;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.ir.ssa.MultiReturnValueInvokeInstruction;
import com.ibm.wala.cast.js.types.JavaScriptMethods;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ssa.SSAInstruction;
@ -21,7 +20,7 @@ import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
public class JavaScriptInvoke extends AbstractLexicalInvoke {
public class JavaScriptInvoke extends MultiReturnValueInvokeInstruction {
/**
* The value numbers of the arguments passed to the call.
*/
@ -35,13 +34,6 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
this.params = params;
}
public JavaScriptInvoke(int iindex, int function, int results[], int[] params, int exception, CallSiteReference site, Access[] lexicalReads,
Access[] lexicalWrites) {
super(iindex, results, exception, site, lexicalReads, lexicalWrites);
this.function = function;
this.params = params;
}
public JavaScriptInvoke(int iindex, int function, int result, int[] params, int exception, CallSiteReference site) {
this(iindex, function, new int[] { result }, params, exception, site);
}
@ -54,7 +46,6 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
int fn = function;
int newParams[] = params;
Access[] reads = lexicalReads;
if (uses != null) {
int i = 0;
@ -65,17 +56,11 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
for (int j = 0; j < newParams.length; j++)
newParams[j] = uses[i++];
if (lexicalReads != null) {
reads = new Access[lexicalReads.length];
for (int j = 0; j < reads.length; j++)
reads[j] = new Access(lexicalReads[j].variableName, lexicalReads[j].variableDefiner, uses[i++]);
}
}
int newLvals[] = new int[results.length];
System.arraycopy(results, 0, newLvals, 0, results.length);
int newExp = exception;
Access[] writes = lexicalWrites;
if (defs != null) {
int i = 0;
@ -87,14 +72,15 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
newLvals[j] = defs[i++];
}
if (lexicalWrites != null) {
writes = new Access[lexicalWrites.length];
for (int j = 0; j < writes.length; j++)
writes[j] = new Access(lexicalWrites[j].variableName, lexicalWrites[j].variableDefiner, defs[i++]);
}
}
return ((JSInstructionFactory)insts).Invoke(iindex, fn, newLvals, newParams, newExp, site, reads, writes);
return ((JSInstructionFactory)insts).Invoke(iindex, fn, newLvals, newParams, newExp, site);
}
@Override
public int getNumberOfUses() {
return getNumberOfParameters();
}
@Override
@ -130,30 +116,9 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
s.append(" exception:").append(getValueString(symbolTable, exception));
}
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();
}
/**
* @see com.ibm.domo.ssa.Instruction#visit(Visitor)
*/
@Override
public void visit(IVisitor v) {
assert v instanceof JSInstructionVisitor;
@ -169,9 +134,6 @@ public class JavaScriptInvoke extends AbstractLexicalInvoke {
}
}
/**
* @see com.ibm.domo.ssa.Instruction#getUse(int)
*/
@Override
public int getUse(int j) {
if (j == 0)

View File

@ -10,13 +10,18 @@
*****************************************************************************/
package com.ibm.wala.cast.js.translator;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.js.loader.JSCallSiteReference;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.ssa.JSInstructionFactory;
import com.ibm.wala.cast.js.ssa.JavaScriptInstanceOf;
import com.ibm.wala.cast.js.ssa.PrototypeLookup;
import com.ibm.wala.cast.js.types.JavaScriptMethods;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
@ -30,6 +35,8 @@ import com.ibm.wala.cast.types.AstMethodReference;
import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.IBasicBlock;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
@ -75,10 +82,29 @@ public class JSAstTranslator extends AstTranslator {
@Override
protected TypeReference makeType(CAstType type) {
Assertions.UNREACHABLE("JavaScript does not use CAstType");
return null;
assert "Any".equals(type.getName());
return JavaScriptTypes.Root;
}
@Override
protected boolean ignoreName(String name) {
return super.ignoreName(name) || name.endsWith(" temp");
}
@Override
protected String[] makeNameMap(CAstEntity n, Set<Scope> scopes, SSAInstruction[] insts) {
String[] names = super.makeNameMap(n, scopes, insts);
for(SSAInstruction inst : insts) {
if (inst instanceof PrototypeLookup) {
if (names[ inst.getUse(0)] != null) {
names[ inst.getDef() ] = names[ inst.getUse(0) ];
}
}
}
return names;
}
/**
* generate an instruction that checks if readVn is undefined and throws an exception if it isn't
*/
@ -96,16 +122,16 @@ public class JSAstTranslator extends AstTranslator {
}
@Override
protected int doLexicallyScopedRead(CAstNode n, WalkContext context, String name) {
int readVn = super.doLexicallyScopedRead(n, context, name);
protected int doLexicallyScopedRead(CAstNode n, WalkContext context, String name, TypeReference type) {
int readVn = super.doLexicallyScopedRead(n, context, name, type);
// should get an exception if name is undefined
addDefinedCheck(n, context, readVn);
return readVn;
}
@Override
protected int doGlobalRead(CAstNode n, WalkContext context, String name) {
int readVn = super.doGlobalRead(n, context, name);
protected int doGlobalRead(CAstNode n, WalkContext context, String name, TypeReference type) {
int readVn = super.doGlobalRead(n, context, name, type);
// add a check if name is undefined, unless we're reading the value 'undefined'
if (!("undefined".equals(name) || "$$undefined".equals(name))) {
addDefinedCheck(n, context, readVn);
@ -200,7 +226,7 @@ public class JSAstTranslator extends AstTranslator {
protected void doMaterializeFunction(CAstNode n, WalkContext context, int result, int exception, CAstEntity fn) {
int nm = context.currentScope().getConstantValue("L" + composeEntityName(context, fn));
// "Function" is the name we use to model the constructor of function values
int tmp = super.doGlobalRead(n, context, "Function");
int tmp = super.doGlobalRead(n, context, "Function", JavaScriptTypes.Function);
context.cfg().addInstruction(
((JSInstructionFactory)insts).Invoke(context.cfg().getCurrentInstruction(), tmp, result, new int[]{ nm }, exception,
new JSCallSiteReference(JavaScriptMethods.ctorReference, context.cfg().getCurrentInstruction())));
@ -394,14 +420,13 @@ public class JSAstTranslator extends AstTranslator {
int tempVal = context.currentScope().allocateTempValue();
doNewObject(context, null, tempVal, "Array", null);
CAstSymbol args = new CAstSymbolImpl("arguments");
CAstSymbol args = new CAstSymbolImpl("arguments", Any);
context.currentScope().declare(args, tempVal);
//context.cfg().addInstruction(((JSInstructionFactory)insts).PutInstruction(context.cfg().getCurrentInstruction(), 1, tempVal, "arguments"));
}
@Override
protected boolean doVisit(CAstNode n, WalkContext cntxt, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext) cntxt;
protected boolean doVisit(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
switch (n.getKind()) {
case CAstNode.TYPE_OF: {
int result = context.currentScope().allocateTempValue();
@ -432,4 +457,27 @@ public class JSAstTranslator extends AstTranslator {
}
}
public static final CAstType Any = new CAstType() {
@Override
public String getName() {
return "Any";
}
@Override
public Collection getSupertypes() {
return Collections.EMPTY_SET;
}
};
@Override
protected CAstType topType() {
return Any;
}
@Override
protected CAstType exceptionType() {
return Any;
}
}

View File

@ -164,7 +164,7 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
result = Ast.makeNode(
CAstNode.BLOCK_EXPR,
// declare loop variable and initialize to the receiver
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, false, false)), receiver),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, JSAstTranslator.Any, false, false)), receiver),
Ast.makeNode(CAstNode.LOOP,
// while the desired property of the loop variable is not
// defined...
@ -208,8 +208,8 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode get;
CAstNode result = Ast.makeNode(
CAstNode.BLOCK_EXPR,
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, false, false)), receiver),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(elementTemp, false, false)), element),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(receiverTemp, JSAstTranslator.Any, false, false)), receiver),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(elementTemp, JSAstTranslator.Any, false, false)), element),
Ast.makeNode(
CAstNode.LOOP,
Ast.makeNode(
@ -260,11 +260,11 @@ public class PropertyReadExpander extends CAstRewriter<PropertyReadExpander.Rewr
CAstNode copy = Ast.makeNode(
CAstNode.BLOCK_EXPR,
// assign lval to temp1 (where lval is a block that includes the prototype chain loop)
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(temp1, true, false)), lval),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(temp1, JSAstTranslator.Any, true, false)), lval),
// ? --MS
//rval,
// assign temp2 the new value to be assigned
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(temp2, true, false)),
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new InternalCAstSymbol(temp2, JSAstTranslator.Any, true, false)),
Ast.makeNode(CAstNode.BINARY_EXPR, op, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(temp1)), rval)),
// write temp2 into the property
Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, ctxt.receiverTemp, ctxt.elementTemp),

View File

@ -11,7 +11,8 @@
package com.ibm.wala.cast.js.translator;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
@ -78,7 +79,7 @@ public class RangePosition extends AbstractSourcePosition implements Position {
}
@Override
public InputStream getInputStream() throws IOException {
return url.openStream();
public Reader getReader() throws IOException {
return new InputStreamReader(url.openStream());
}
}

View File

@ -12,11 +12,20 @@ package com.ibm.wala.cast.js.util;
import java.util.Iterator;
import com.ibm.wala.cast.js.ssa.PrototypeLookup;
import com.ibm.wala.cast.loader.CAstAbstractLoader;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.ModuleEntry;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAPhiInstruction;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetAction;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
import com.ibm.wala.util.warnings.Warning;
public class Util {
@ -47,6 +56,49 @@ public class Util {
throw new WalaException(String.valueOf(message));
}
}
public static IntSet getArgumentsArrayVns(IR ir, final DefUse du) {
int originalArgsVn = getArgumentsArrayVn(ir);
final MutableIntSet result = IntSetUtil.make();
if (originalArgsVn == -1) {
return result;
}
result.add(originalArgsVn);
int size;
do {
size = result.size();
result.foreach(new IntSetAction() {
@Override
public void act(int vn) {
for(Iterator<SSAInstruction> insts = du.getUses(vn); insts.hasNext(); ) {
SSAInstruction inst = insts.next();
if (inst instanceof PrototypeLookup || inst instanceof SSAPhiInstruction) {
result.add(inst.getDef());
}
}
}
});
} while (size != result.size());
return result;
}
public static int getArgumentsArrayVn(IR ir) {
for(int i = 0; i < ir.getInstructions().length; i++) {
SSAInstruction inst = ir.getInstructions()[i];
if (inst != null) {
for(int v = 0; v < inst.getNumberOfUses(); v++) {
String[] names = ir.getLocalNames(i, inst.getUse(v));
if (names != null && names.length == 1 && "arguments".equals(names[0])) {
return inst.getUse(v);
}
}
}
}
return -1;
}
}

View File

@ -60,7 +60,7 @@ public class AstCallGraph extends ExplicitCallGraph {
}
public AstLexicalRead addGlobalRead(TypeReference type, String name) {
AstLexicalRead s = new AstLexicalRead(statements.size(), nextLocal++, null, name);
AstLexicalRead s = new AstLexicalRead(statements.size(), nextLocal++, null, name, type);
statements.add(s);
return s;
}

View File

@ -18,7 +18,6 @@ import java.util.Set;
import com.ibm.wala.analysis.reflection.ReflectionContextInterpreter;
import com.ibm.wala.cast.ipa.callgraph.AstCallGraph.AstCGNode;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
import com.ibm.wala.cast.ir.ssa.AbstractLexicalInvoke;
import com.ibm.wala.cast.ir.ssa.AstAssertInstruction;
import com.ibm.wala.cast.ir.ssa.AstEchoInstruction;
import com.ibm.wala.cast.ir.ssa.AstGlobalRead;
@ -61,7 +60,6 @@ import com.ibm.wala.ipa.callgraph.propagation.cfa.DelegatingSSAContextInterprete
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.SSAPutInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.util.collections.HashSetFactory;
@ -425,7 +423,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable objects = (IntSetVariable) rhs;
final IntSetVariable objects = rhs;
if (objects.getValue() != null) {
objects.getValue().foreach(new IntSetAction() {
@Override
@ -491,7 +489,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable objects = (IntSetVariable) rhs;
final IntSetVariable objects = rhs;
if (objects.getValue() != null) {
objects.getValue().foreach(new IntSetAction() {
@Override
@ -535,43 +533,6 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
}
@Override
protected void visitInvokeInternal(final SSAAbstractInvokeInstruction instruction, InvariantComputer invs) {
super.visitInvokeInternal(instruction, invs);
if (instruction instanceof AbstractLexicalInvoke) {
AbstractLexicalInvoke I = (AbstractLexicalInvoke) instruction;
for (int wi = 0; wi < I.getNumberOfDefs(); wi++) {
if (I.isLexicalDef(wi)) {
Access w = I.getLexicalDef(wi);
for (int ri = 0; ri < I.getNumberOfUses(); ri++) {
if (I.isLexicalUse(ri)) {
Access r = I.getLexicalUse(ri);
if (w.variableName.equals(r.variableName)) {
if (w.variableDefiner == null ? r.variableDefiner == null : w.variableDefiner.equals(r.variableDefiner)) {
// handle the control-flow paths through the (transitive)
// callees where the name is not written;
// in such cases, the original value (rk) is preserved
PointerKey rk = getBuilder().getPointerKeyForLocal(node, r.valueNumber);
PointerKey wk = getBuilder().getPointerKeyForLocal(node, w.valueNumber);
if (contentsAreInvariant(node.getIR().getSymbolTable(), du, r.valueNumber)) {
system.recordImplicitPointsToSet(rk);
final InstanceKey[] objKeys = getInvariantContents(r.valueNumber);
for (int i = 0; i < objKeys.length; i++) {
system.newConstraint(wk, objKeys[0]);
}
} else {
system.newConstraint(wk, assignOperator, rk);
}
}
}
}
}
}
}
}
}
// /////////////////////////////////////////////////////////////////////////
//
// lexical scoping handling
@ -950,8 +911,8 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
@Override
public byte evaluate(PointsToSetVariable lhs, final PointsToSetVariable[] rhs) {
final IntSetVariable receivers = (IntSetVariable) rhs[0];
final IntSetVariable fields = (IntSetVariable) rhs[1];
final IntSetVariable receivers = rhs[0];
final IntSetVariable fields = rhs[1];
if (receivers.getValue() != null && fields.getValue() != null) {
receivers.getValue().foreach(new IntSetAction() {
@Override
@ -1011,7 +972,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable objects = (IntSetVariable) rhs;
final IntSetVariable objects = rhs;
if (objects.getValue() != null) {
objects.getValue().foreach(new IntSetAction() {
@Override
@ -1075,7 +1036,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.newSideEffect(new UnaryOperator<PointsToSetVariable>() {
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
final IntSetVariable fields = (IntSetVariable) rhs;
final IntSetVariable fields = rhs;
if (fields.getValue() != null) {
fields.getValue().foreach(new IntSetAction() {
@Override

View File

@ -11,7 +11,6 @@ package com.ibm.wala.cast.ipa.callgraph;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
@ -19,7 +18,6 @@ import com.ibm.wala.cast.loader.SingleClassLoaderFactory;
import com.ibm.wala.classLoader.ArrayClassLoader;
import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.classLoader.SourceURLModule;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.debug.Assertions;
@ -42,13 +40,6 @@ public class CAstAnalysisScope extends AnalysisScope {
}
}
public CAstAnalysisScope(URL[] sources, SingleClassLoaderFactory loaders, Collection<Language> languages) throws IOException {
this(loaders, languages);
for (int i = 0; i < sources.length; i++) {
addToScope(theLoader, new SourceURLModule(sources[i]));
}
}
public CAstAnalysisScope(SourceModule[] sources, SingleClassLoaderFactory loaders, Collection<Language> languages)
throws IOException {
this(loaders, languages);

View File

@ -68,11 +68,6 @@ public class CAstCallGraphUtil {
return result;
}
public static AnalysisScope makeScope(URL[] files, SingleClassLoaderFactory loaders, Language language) throws IOException {
CAstAnalysisScope result = new CAstAnalysisScope(files, loaders, Collections.singleton(language));
return result;
}
public static AnalysisCache makeCache(IRFactory<IMethod> factory) {
return new AnalysisCache(factory);
}

View File

@ -103,8 +103,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
result = new CompoundIterator<CGNode>(result, new NonNullSingletonIterator<CGNode>(callerOfConstructor));
} else {
PointerKey funcKey = builder.getPointerKeyForLocal(callerOfConstructor, 1);
OrdinalSet<InstanceKey> funcPtrs = builder.getPointerAnalysis().getPointsToSet(funcKey);
for (InstanceKey funcPtr : funcPtrs) {
for (InstanceKey funcPtr : builder.getPointerAnalysis().getPointsToSet(funcKey)) {
if (funcPtr instanceof ScopeMappingInstanceKey) {
result = new CompoundIterator<CGNode>(result, ((ScopeMappingInstanceKey) funcPtr).getFunargNodes(name));
}

View File

@ -103,4 +103,16 @@ public abstract class ScriptEntryPoints implements Iterable<Entrypoint> {
return ES.iterator();
}
}
public Entrypoint make(String scriptName) {
IClass cls = cha.lookupClass(TypeReference.findOrCreate(scriptType.getClassLoader().getReference(), scriptName));
assert cls != null && cha.isSubclassOf(cls, scriptType) && !cls.isAbstract() : String.valueOf(cls) + " for " + scriptName;
for (IMethod method : cls.getDeclaredMethods()) {
if (keep(method)) {
return new ScriptEntryPoint(method);
}
}
assert false;
return null;
}
}

View File

@ -71,7 +71,7 @@ public class CrossLanguageClassHierarchy implements IClassHierarchy {
}
private IClassHierarchy getHierarchy(Atom language) {
return (IClassHierarchy) hierarchies.get(language);
return hierarchies.get(language);
}
private IClassHierarchy getHierarchy(IClassLoader loader) {
@ -105,7 +105,7 @@ public class CrossLanguageClassHierarchy implements IClassHierarchy {
loaders.add(getLoader((ClassLoaderReference) ldrs.next()));
}
return (IClassLoader[]) loaders.toArray(new IClassLoader[loaders.size()]);
return loaders.toArray(new IClassLoader[loaders.size()]);
}
@Override

View File

@ -121,7 +121,7 @@ public class LexicalModRef {
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
// use scope-mapping instance keys in pointer analysis. may need a different
// scheme for CG construction not based on pointer analysis
OrdinalSet<InstanceKey> functionValues = pa.getPointsToSet(pa.getHeapModel().getPointerKeyForLocal(n, 1));
OrdinalSet<? extends InstanceKey> functionValues = pa.getPointsToSet(pa.getHeapModel().getPointerKeyForLocal(n, 1));
for (InstanceKey ik : functionValues) {
if (ik instanceof ScopeMappingInstanceKey) {
ScopeMappingInstanceKey smik = (ScopeMappingInstanceKey) ik;

View File

@ -1,168 +0,0 @@
/******************************************************************************
* 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 iindex, int results[], int exception, CallSiteReference site) {
super(iindex, results, exception, site);
}
protected AbstractLexicalInvoke(int iindex, int result, int exception, CallSiteReference site) {
this(iindex, new int[] { result }, exception, site);
}
protected AbstractLexicalInvoke(int iindex, int results[], int exception, CallSiteReference site, Access[] lexicalReads,
Access[] lexicalWrites) {
this(iindex, results, exception, site);
this.lexicalReads = lexicalReads;
this.lexicalWrites = lexicalWrites;
}
@Override
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;
}
}
@Override
public int getUse(int j) {
assert j >= getNumberOfParameters();
assert lexicalReads != null;
assert lexicalReads[j - getNumberOfParameters()] != null;
return lexicalReads[j - getNumberOfParameters()].valueNumber;
}
@Override
public int getNumberOfDefs() {
if (lexicalWrites == null)
return super.getNumberOfDefs();
else
return super.getNumberOfDefs() + lexicalWrites.length;
}
@Override
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()];
}
@Override
public int hashCode() {
return site.hashCode() * 7529;
}
@Override
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

@ -261,7 +261,7 @@ public abstract class AbstractSSAConversion {
initializeVariables();
SEARCH((SSACFG.BasicBlock) CFG.entry());
SEARCH(CFG.entry());
}

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
public interface AstInstructionFactory extends SSAInstructionFactory {
@ -38,13 +39,13 @@ public interface AstInstructionFactory extends SSAInstructionFactory {
AstLexicalRead LexicalRead(int iindex, Access access);
AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName);
AstLexicalRead LexicalRead(int iindex, int lhs, String definer, String globalName, TypeReference type);
AstLexicalWrite LexicalWrite(int iindex, Access[] accesses);
AstLexicalWrite LexicalWrite(int iindex, Access access);
AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, int rhs);
AstLexicalWrite LexicalWrite(int iindex, String definer, String globalName, TypeReference type, int rhs);
EachElementGetInstruction EachElementGetInstruction(int iindex, int lValue, int objectRef);

View File

@ -39,14 +39,19 @@ public abstract class AstLexicalAccess extends SSAInstruction {
* name of entity that defines the variable
*/
public final String variableDefiner;
/**
* type of the lexical value
*/
public final TypeReference type;
/**
* value number used for name where access is being performed (not in the declaring entity)
*/
public final int valueNumber;
public Access(String name, String definer, int vn) {
public Access(String name, String definer, TypeReference type, int vn) {
variableName = name;
variableDefiner = definer;
this.type = type;
valueNumber = vn;
}

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
/**
* A set of lexical reads. This instruction represents reads of a set of variables that are defined by a pair of
@ -32,8 +33,8 @@ public class AstLexicalRead extends AstLexicalAccess {
this(iindex, new Access[] { access });
}
public AstLexicalRead(int iindex, int lhs, String definer, String globalName) {
this(iindex, new Access(globalName, definer, lhs));
public AstLexicalRead(int iindex, int lhs, String definer, String globalName, TypeReference type) {
this(iindex, new Access(globalName, definer, type, lhs));
}
@Override
@ -44,7 +45,7 @@ public class AstLexicalRead extends AstLexicalAccess {
Access[] accesses = new Access[getAccessCount()];
for (int i = 0; i < accesses.length; i++) {
Access oldAccess = getAccess(i);
accesses[i] = new Access(oldAccess.variableName, oldAccess.variableDefiner, defs[i]);
accesses[i] = new Access(oldAccess.variableName, oldAccess.variableDefiner, oldAccess.type, defs[i]);
}
return ((AstInstructionFactory)insts).LexicalRead(iindex, accesses);

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
/**
* A set of lexical writes. This instruction represents writes of a set of variables that are defined by a pair of
@ -24,8 +25,8 @@ import com.ibm.wala.ssa.SymbolTable;
*/
public class AstLexicalWrite extends AstLexicalAccess {
public AstLexicalWrite(int iindex, String definer, String globalName, int rhs) {
this(iindex, new Access(globalName, definer, rhs));
public AstLexicalWrite(int iindex, String definer, String globalName, TypeReference type, int rhs) {
this(iindex, new Access(globalName, definer, type, rhs));
}
public AstLexicalWrite(int iindex, Access access) {
@ -44,7 +45,7 @@ public class AstLexicalWrite extends AstLexicalAccess {
Access[] accesses = new Access[getAccessCount()];
for (int i = 0; i < accesses.length; i++) {
Access oldAccess = getAccess(i);
accesses[i] = new Access(oldAccess.variableName, oldAccess.variableDefiner, uses[i]);
accesses[i] = new Access(oldAccess.variableName, oldAccess.variableDefiner, oldAccess.type, uses[i]);
}
return ((AstInstructionFactory)insts).LexicalWrite(iindex, accesses);

View File

@ -10,21 +10,21 @@
*****************************************************************************/
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.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
/**
* This abstract instruction extends the abstract lexical invoke with
* This abstract instruction extends the abstract invoke with
* functionality to support invocations with a fixed number of
* arguments---the only case in some languages and a common case even
* in scripting languages.
*
*
* @author Julian Dolby (dolby@us.ibm.com)
*/
public abstract class FixedParametersLexicalInvokeInstruction
extends AbstractLexicalInvoke
public abstract class FixedParametersInvokeInstruction
extends MultiReturnValueInvokeInstruction
{
/**
@ -34,12 +34,12 @@ public abstract class FixedParametersLexicalInvokeInstruction
*/
private final int[] params;
public FixedParametersLexicalInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site) {
public FixedParametersInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site) {
super(iindex, results, exception, site);
this.params = params;
}
public FixedParametersLexicalInvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site) {
public FixedParametersInvokeInstruction(int iindex, int result, int[] params, int exception, CallSiteReference site) {
this(iindex, new int[]{result}, params, exception, site);
}
@ -48,61 +48,43 @@ public abstract class FixedParametersLexicalInvokeInstruction
* @param i
* @param params
*/
public FixedParametersLexicalInvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site) {
public FixedParametersInvokeInstruction(int iindex, int[] params, int exception, CallSiteReference site) {
this(iindex, null, params, exception, site);
}
protected FixedParametersLexicalInvokeInstruction(int iindex, int results[], int[] params, int exception, CallSiteReference site, Access[] lexicalReads, Access[] lexicalWrites) {
super(iindex, results, exception, site, lexicalReads, lexicalWrites);
this.params = params;
}
protected abstract SSAInstruction copyInstruction(SSAInstructionFactory insts, int result[], int[] params, int exception, Access[] lexicalReads, Access[] lexicalWrites);
protected abstract SSAInstruction copyInstruction(SSAInstructionFactory insts, int result[], int[] params, int exception);
@Override
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
int newParams[] = params;
Access[] reads = lexicalReads;
if (uses != null) {
int i = 0;
newParams = new int[ params.length ];
for(int j = 0; j < newParams.length; j++)
newParams[j] = uses[i++];
if (lexicalReads != null) {
reads = new Access[ lexicalReads.length ];
for(int j = 0; j < reads.length; j++)
reads[j] = new Access(lexicalReads[j].variableName, lexicalReads[j].variableDefiner, uses[i++]);
}
newParams = new int[params.length];
for (int j = 0; j < newParams.length; j++)
newParams[j] = uses[i++];
}
int newLvals[] = null;
if (getNumberOfReturnValues() > 0) {
newLvals = new int[ results.length ];
newLvals = new int[results.length];
System.arraycopy(results, 0, newLvals, 0, results.length);
}
int newExp = exception;
Access[] writes = lexicalWrites;
if (defs != null) {
int i = 0;
if (getNumberOfReturnValues() > 0) {
newLvals[0] = defs[i++];
newLvals[0] = defs[i++];
}
newExp = defs[i++];
for(int j = 1; j < getNumberOfReturnValues(); j++) {
newLvals[j] = defs[i++];
}
if (lexicalWrites != null) {
writes = new Access[ lexicalWrites.length ];
for(int j = 0; j < writes.length; j++)
writes[j] = new Access(lexicalWrites[j].variableName, lexicalWrites[j].variableDefiner, defs[i++]);
for (int j = 1; j < getNumberOfReturnValues(); j++) {
newLvals[j] = defs[i++];
}
}
return copyInstruction(insts, newLvals, newParams, newExp, reads, writes);
return copyInstruction(insts, newLvals, newParams, newExp);
}
@Override
@ -114,9 +96,26 @@ public abstract class FixedParametersLexicalInvokeInstruction
}
}
/**
* @see com.ibm.wala.ssa.Instruction#getUse(int)
*/
@Override
public void visit(IVisitor v) {
// TODO Auto-generated method stub
assert false;
}
@Override
public int getNumberOfUses() {
return getNumberOfParameters();
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
assert false;
return 0;
}
@Override
public int getUse(int j) {
if (j < getNumberOfParameters())

View File

@ -13,7 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
abstract class MultiReturnValueInvokeInstruction
public abstract class MultiReturnValueInvokeInstruction
extends SSAAbstractInvokeInstruction
{
protected final int results[];

View File

@ -206,7 +206,7 @@ public class SSAConversion extends AbstractSSAConversion {
PhiUseRecord use = (PhiUseRecord) x;
int bb = use.BBnumber;
int phi = use.phiNumber;
SSACFG.BasicBlock BB = (SSACFG.BasicBlock) CFG.getNode(bb);
SSACFG.BasicBlock BB = CFG.getNode(bb);
BB.addPhiForLocal(phi, (SSAPhiInstruction) undo(BB.getPhiForLocal(phi), use.useNumber, lhs));
copyPropagationMap.remove(use);
}
@ -273,7 +273,7 @@ public class SSAConversion extends AbstractSSAConversion {
private CopyPropagationRecord topR(int v) {
if (R[v] != null && !R[v].isEmpty()) {
CopyPropagationRecord rec = (CopyPropagationRecord) R[v].peek();
CopyPropagationRecord rec = R[v].peek();
if (top(v) == rec.rhs) {
return rec;
}
@ -474,7 +474,7 @@ public class SSAConversion extends AbstractSSAConversion {
this.R = new Stack[ir.getSymbolTable().getMaxValueNumber() + 1];
for (int i = 0; i < CFG.getNumberOfNodes(); i++) {
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i);
SSACFG.BasicBlock bb = CFG.getNode(i);
if (bb.hasPhi()) {
int n = 0;
for (Iterator X = bb.iteratePhis(); X.hasNext(); n++)

Some files were not shown because too many files have changed in this diff Show More