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:
parent
eac23e97a9
commit
30686135da
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue