Never mind. Works now and passes all tests.
http://i.imgur.com/0vtZhPW.png
For the other Groups i'd like to tell you what we did. I also would like to post the complete Code but i suppose i'm not allowed to, or am I? If so I'd gladly give the other Groups some help. Anyway some talk about what we did, might be helpful as well:
We implemented the Analysis pseudo-recursive. Each time we find a new Invoke-Expr we analyse it after mapping the Contexts from the Caller into the Callee. For this we used a CallContext:
Code: Alles auswählen
public class CallContext {
private SootMethod sourceCaller;
private SootMethod targetCallee;
private int args_n;
private InvokeExpr invokeExpr;
private ArrayList<Set<AccessPath>> paramCallAP;
private ArrayList<Set<AccessPath>> paramRetAP;
private Set<AccessPath> returnAP = new HashSet<AccessPath>();
private Set<AccessPath> thisAP = new HashSet<AccessPath>();
This CallContext gets pushed onto a CallStack where the new Method just grabs it and maps it into their Scope. (This can be done via a simple Statemachine: Call -> Grab Context -> Analyze -> ..... -> Return -> Map Context Back)
On the CallStack structure we implemented sanity Checks like to check when you hit a Return Stmt if the current Method actually got called before or if we just started our analysis in that method without calling it (flow insensitive). This happened frequently to us due to the fact that the analysis usually started in some init method which never got called before.
Code: Alles auswählen
// This method checks if there has been an appropriate Call before.
public boolean hasBeenCalledBefore(SootMethod m){
if(height == 0)
return false;
else if (!this.peek().getTargetCallee().getSignature().equals(m.getSignature()))
return false;
return true;
}
public boolean isDirectRecursion(SootMethod m){
if(height == 0)
return false;
else if(this.peek().getSourceCaller().getSignature().equals(m.getSignature()))
return true;
return false;
}
Also a indirect Recursion via-Prefix-Checks would be implementable, but wasnt neccasary for us.
Another annoying thing that we stumbled opon was the fact that any static method doesnt have a this-Variable. So we made sure that before mapping a This-Variable that the Method is non-Static:
The hardest Test to pass was the switchString-Test because it is a recursive-call with multiple return-paths. We introduced a merging for this case.
The second hardest Test was the objectFieldSetter-Test, mostly because of annoying this-mapping problems.
Recursion in itself wasnt too big of a problem, we implemented the easiest possible way by just setting an upper bound for the callstack.