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 {
@Override
public void unary1() {
unary2();
}
@Override
public void unary2() {
}
@Override
public void binary(Whatever arg) {
this.unary1();
arg.unary2();
@ -41,14 +44,17 @@ class PiNodeCallGraphTestCase {
static class That implements Whatever {
@Override
public void unary1() {
}
@Override
public void unary2() {
unary1();
}
@Override
public void binary(Whatever arg) {
this.unary1();
arg.unary2();
@ -67,6 +73,14 @@ class PiNodeCallGraphTestCase {
x.binary(z);
else
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.Set;
import org.junit.Assert;
import org.junit.Test;
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.util.CancelException;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Iterator2List;
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);
}
private void checkCallAssertions(CallGraph cg, int desiredNumberOfTargets, int desiredNumberOfCalls) {
private void checkCallAssertions(CallGraph cg, int desiredNumberOfTargets, int desiredNumberOfCalls, int numLocalCastCallees) {
int numberOfCalls = 0;
Set<CGNode> callerNodes = HashSetFactory.make();
@ -93,7 +95,7 @@ public class PiNodeCallGraphTest extends WalaTestCase {
for (CGNode n : callerNodes) {
for (Iterator<CallSiteReference> sites = n.iterateCallSites(); sites.hasNext();) {
CallSiteReference csRef = (CallSiteReference) sites.next();
CallSiteReference csRef = sites.next();
if (csRef.getDeclaredTarget().equals(unary2Ref)) {
numberOfCalls++;
assert cg.getNumberOfTargets(n, csRef) == desiredNumberOfTargets;
@ -101,15 +103,20 @@ public class PiNodeCallGraphTest extends WalaTestCase {
}
}
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 {
checkCallAssertions(doGraph(false), 2, 2);
checkCallAssertions(doGraph(false), 2, 2, 2);
}
@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);
} else {
ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph();
int val = instruction.getVal();
if (com.ibm.wala.cfg.Util.endsWithConditionalBranch(cfg, getBasicBlock()) && cfg.getSuccNodeCount(getBasicBlock()) == 2) {
SSAConditionalBranchInstruction cond = (SSAConditionalBranchInstruction) com.ibm.wala.cfg.Util.getLastInstruction(cfg,
getBasicBlock());
@ -1275,31 +1276,42 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
IClass cls = getClassHierarchy().lookupClass(type);
if (cls == null) {
PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal());
addPiAssignment(dst, val);
} else {
PointerKey dst = getFilteredPointerKeyForLocal(instruction.getDef(), new FilteredPointerKey.SingleClassFilter(cls));
PointerKey src = getPointerKeyForLocal(instruction.getVal());
if ((target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && direction == 1)
|| (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && direction == -1)) {
system.newConstraint(dst, getBuilder().filterOperator, src);
// if true, only allow objects assignable to cls. otherwise, only allow objects
// *not* assignable to cls
boolean useFilter = (target == com.ibm.wala.cfg.Util.getTakenSuccessor(cfg, getBasicBlock()) && direction == 1)
|| (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 {
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)
|| (target == com.ibm.wala.cfg.Util.getNotTakenSuccessor(cfg, getBasicBlock()) && dir == 1)) {
PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal());
addPiAssignment(dst, val);
}
} else {
PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal());
addPiAssignment(dst, val);
}
} else {
PointerKey dst = getPointerKeyForLocal(instruction.getDef());
addPiAssignment(dst, instruction.getVal());
addPiAssignment(dst, val);
}
}
}