Fix for bug with pi nodes reported by Andreas Sewe

We weren't handling the case where the val of the pi instruction
had an implicit points-to set.
This commit is contained in:
Manu Sridharan 2013-05-07 14:43:49 -07:00
parent eac23e97a9
commit 30686135da
3 changed files with 48 additions and 15 deletions

View File

@ -24,14 +24,17 @@ class PiNodeCallGraphTestCase {
static class This implements Whatever { static class This implements Whatever {
@Override
public void unary1() { public void unary1() {
unary2(); unary2();
} }
@Override
public void unary2() { public void unary2() {
} }
@Override
public void binary(Whatever arg) { public void binary(Whatever arg) {
this.unary1(); this.unary1();
arg.unary2(); arg.unary2();
@ -41,14 +44,17 @@ class PiNodeCallGraphTestCase {
static class That implements Whatever { static class That implements Whatever {
@Override
public void unary1() { public void unary1() {
} }
@Override
public void unary2() { public void unary2() {
unary1(); unary1();
} }
@Override
public void binary(Whatever arg) { public void binary(Whatever arg) {
this.unary1(); this.unary1();
arg.unary2(); arg.unary2();
@ -67,6 +73,14 @@ class PiNodeCallGraphTestCase {
x.binary(z); x.binary(z);
else else
y.binary(z); y.binary(z);
localCast();
}
private static void localCast() {
Whatever y = new That();
if (y instanceof This) {
y.binary(y);
}
} }
} }

View File

@ -14,6 +14,7 @@ import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.CallSiteReference;
@ -37,6 +38,7 @@ import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.CancelException; import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2List;
import com.ibm.wala.util.strings.Atom; import com.ibm.wala.util.strings.Atom;
/** /**
@ -83,7 +85,7 @@ public class PiNodeCallGraphTest extends WalaTestCase {
return CallGraphTestUtil.buildZeroCFA(options, new AnalysisCache(), cha, scope, false); return CallGraphTestUtil.buildZeroCFA(options, new AnalysisCache(), cha, scope, false);
} }
private void checkCallAssertions(CallGraph cg, int desiredNumberOfTargets, int desiredNumberOfCalls) { private void checkCallAssertions(CallGraph cg, int desiredNumberOfTargets, int desiredNumberOfCalls, int numLocalCastCallees) {
int numberOfCalls = 0; int numberOfCalls = 0;
Set<CGNode> callerNodes = HashSetFactory.make(); Set<CGNode> callerNodes = HashSetFactory.make();
@ -93,7 +95,7 @@ public class PiNodeCallGraphTest extends WalaTestCase {
for (CGNode n : callerNodes) { for (CGNode n : callerNodes) {
for (Iterator<CallSiteReference> sites = n.iterateCallSites(); sites.hasNext();) { for (Iterator<CallSiteReference> sites = n.iterateCallSites(); sites.hasNext();) {
CallSiteReference csRef = (CallSiteReference) sites.next(); CallSiteReference csRef = sites.next();
if (csRef.getDeclaredTarget().equals(unary2Ref)) { if (csRef.getDeclaredTarget().equals(unary2Ref)) {
numberOfCalls++; numberOfCalls++;
assert cg.getNumberOfTargets(n, csRef) == desiredNumberOfTargets; assert cg.getNumberOfTargets(n, csRef) == desiredNumberOfTargets;
@ -101,15 +103,20 @@ public class PiNodeCallGraphTest extends WalaTestCase {
} }
} }
assert numberOfCalls == desiredNumberOfCalls; assert numberOfCalls == desiredNumberOfCalls;
CGNode localCastNode = cg.getNodes(MethodReference.findOrCreate(TypeReference.findOrCreate(loader, TestConstants.PI_TEST_MAIN), "localCast", "()V")).iterator().next();
int actualLocalCastCallees = cg.getSuccNodeCount(localCastNode);
Assert.assertEquals(numLocalCastCallees, actualLocalCastCallees);
} }
@Test public void testNoPiNodes() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { @Test public void testNoPiNodes() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
checkCallAssertions(doGraph(false), 2, 2); checkCallAssertions(doGraph(false), 2, 2, 2);
} }
@Test public void testPiNodes() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { @Test public void testPiNodes() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
checkCallAssertions(doGraph(true), 1, 2); checkCallAssertions(doGraph(true), 1, 2, 1);
} }
} }

View File

@ -1262,6 +1262,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
system.recordImplicitPointsToSet(dst); system.recordImplicitPointsToSet(dst);
} else { } else {
ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph(); ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph();
int val = instruction.getVal();
if (com.ibm.wala.cfg.Util.endsWithConditionalBranch(cfg, getBasicBlock()) && cfg.getSuccNodeCount(getBasicBlock()) == 2) { if (com.ibm.wala.cfg.Util.endsWithConditionalBranch(cfg, getBasicBlock()) && cfg.getSuccNodeCount(getBasicBlock()) == 2) {
SSAConditionalBranchInstruction cond = (SSAConditionalBranchInstruction) com.ibm.wala.cfg.Util.getLastInstruction(cfg, SSAConditionalBranchInstruction cond = (SSAConditionalBranchInstruction) com.ibm.wala.cfg.Util.getLastInstruction(cfg,
getBasicBlock()); getBasicBlock());
@ -1275,31 +1276,42 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
IClass cls = getClassHierarchy().lookupClass(type); IClass cls = getClassHierarchy().lookupClass(type);
if (cls == null) { if (cls == null) {
PointerKey dst = getPointerKeyForLocal(instruction.getDef()); PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal()); addPiAssignment(dst, val);
} else { } else {
PointerKey dst = getFilteredPointerKeyForLocal(instruction.getDef(), new FilteredPointerKey.SingleClassFilter(cls)); PointerKey dst = getFilteredPointerKeyForLocal(instruction.getDef(), new FilteredPointerKey.SingleClassFilter(cls));
PointerKey src = getPointerKeyForLocal(instruction.getVal()); // if true, only allow objects assignable to cls. otherwise, only allow objects
if ((target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && direction == 1) // *not* assignable to cls
|| (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && direction == -1)) { boolean useFilter = (target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && direction == 1)
system.newConstraint(dst, getBuilder().filterOperator, src); || (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && direction == -1);
PointerKey src = getPointerKeyForLocal(val);
if (contentsAreInvariant(symbolTable, du, val)) {
system.recordImplicitPointsToSet(src);
InstanceKey[] ik = getInvariantContents(val);
for (int j = 0; j < ik.length; j++) {
boolean assignable = getClassHierarchy().isAssignableFrom(cls, ik[j].getConcreteType());
if ((assignable && useFilter) || (!assignable && !useFilter)) {
system.newConstraint(dst, ik[j]);
}
}
} else { } else {
system.newConstraint(dst, getBuilder().inverseFilterOperator, src); FilterOperator op = useFilter ? getBuilder().filterOperator : getBuilder().inverseFilterOperator;
system.newConstraint(dst, op, src);
} }
} }
} }
} else if ((dir = nullConstantTest(cond, instruction.getVal())) != 0) { } else if ((dir = nullConstantTest(cond, val)) != 0) {
if ((target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && dir == -1) if ((target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && dir == -1)
|| (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && dir == 1)) { || (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && dir == 1)) {
PointerKey dst = getPointerKeyForLocal(instruction.getDef()); PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal()); addPiAssignment(dst, val);
} }
} else { } else {
PointerKey dst = getPointerKeyForLocal(instruction.getDef()); PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal()); addPiAssignment(dst, val);
} }
} else { } else {
PointerKey dst = getPointerKeyForLocal(instruction.getDef()); PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal()); addPiAssignment(dst, val);
} }
} }
} }