more changes.
[IRC.git] / Robust / src / Analysis / SSJava / LocationInference.java
index 275b5293f1d6d1005f75f0bb96ec5bfa4f45f009..cb2bb28b804465a23f6866cafe0b5e9315485a68 100644 (file)
@@ -1,10 +1,12 @@
 package Analysis.SSJava;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -17,6 +19,7 @@ import IR.NameDescriptor;
 import IR.Operation;
 import IR.State;
 import IR.SymbolTable;
+import IR.TypeDescriptor;
 import IR.VarDescriptor;
 import IR.Tree.ArrayAccessNode;
 import IR.Tree.AssignmentNode;
@@ -121,41 +124,44 @@ public class LocationInference {
       }
     }
 
+    _debug_printGraph();
+
   }
 
   private void analyzeMethodBody(ClassDescriptor cd, MethodDescriptor md) {
     BlockNode bn = state.getMethodBody(md);
-    analyzeBlockNode(md, md.getParameterTable(), bn);
+    analyzeFlowBlockNode(md, md.getParameterTable(), bn, null);
   }
 
-  private void analyzeBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
+  private void analyzeFlowBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn,
+      NodeTupleSet implicitFlowTupleSet) {
 
     bn.getVarTable().setParent(nametable);
     for (int i = 0; i < bn.size(); i++) {
       BlockStatementNode bsn = bn.get(i);
-      analyzeBlockStatementNode(md, bn.getVarTable(), bsn);
+      analyzeBlockStatementNode(md, bn.getVarTable(), bsn, implicitFlowTupleSet);
     }
 
   }
 
   private void analyzeBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
-      BlockStatementNode bsn) {
+      BlockStatementNode bsn, NodeTupleSet implicitFlowTupleSet) {
 
     switch (bsn.kind()) {
     case Kind.BlockExpressionNode:
-      analyzeBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
+      analyzeBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, implicitFlowTupleSet);
       break;
 
     case Kind.DeclarationNode:
-      analyzeFlowDeclarationNode(md, nametable, (DeclarationNode) bsn, new NTuple<Descriptor>());
+      analyzeFlowDeclarationNode(md, nametable, (DeclarationNode) bsn, implicitFlowTupleSet);
       break;
 
     case Kind.IfStatementNode:
-      analyzeIfStatementNode(md, nametable, (IfStatementNode) bsn);
+      analyzeFlowIfStatementNode(md, nametable, (IfStatementNode) bsn, implicitFlowTupleSet);
       break;
 
     case Kind.LoopNode:
-      analyzeLoopNode(md, nametable, (LoopNode) bsn);
+      analyzeFlowLoopNode(md, nametable, (LoopNode) bsn, implicitFlowTupleSet);
       break;
 
     case Kind.ReturnNode:
@@ -163,7 +169,7 @@ public class LocationInference {
       break;
 
     case Kind.SubBlockNode:
-      analyzeSubBlockNode(md, nametable, (SubBlockNode) bsn);
+      analyzeFlowSubBlockNode(md, nametable, (SubBlockNode) bsn, implicitFlowTupleSet);
       break;
 
     case Kind.ContinueBreakNode:
@@ -183,9 +189,9 @@ public class LocationInference {
 
   }
 
-  private void analyzeSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode bsn) {
-    // TODO Auto-generated method stub
-
+  private void analyzeFlowSubBlockNode(MethodDescriptor md, SymbolTable nametable,
+      SubBlockNode sbn, NodeTupleSet implicitFlowTupleSet) {
+    analyzeFlowBlockNode(md, nametable, sbn.getBlockNode(), implicitFlowTupleSet);
   }
 
   private void analyzeReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode bsn) {
@@ -193,65 +199,117 @@ public class LocationInference {
 
   }
 
-  private void analyzeLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode bsn) {
-    // TODO Auto-generated method stub
+  private void analyzeFlowLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln,
+      NodeTupleSet implicitFlowTupleSet) {
+
+    if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
+
+      NodeTupleSet condTupleNode = new NodeTupleSet();
+      analyzeFlowExpressionNode(md, nametable, ln.getCondition(), condTupleNode, null,
+          implicitFlowTupleSet);
+      condTupleNode.addTupleSet(implicitFlowTupleSet);
+      System.out.println("condTupleNode=" + condTupleNode);
+
+      // add edges from condNodeTupleSet to all nodes of conditional nodes
+      analyzeFlowBlockNode(md, nametable, ln.getBody(), condTupleNode);
+
+    } else {
+      // check 'for loop' case
+      BlockNode bn = ln.getInitializer();
+      analyzeFlowBlockNode(md, nametable, bn, implicitFlowTupleSet);
+      bn.getVarTable().setParent(nametable);
+
+      NodeTupleSet condTupleNode = new NodeTupleSet();
+      analyzeFlowExpressionNode(md, nametable, ln.getCondition(), condTupleNode, null,
+          implicitFlowTupleSet);
+      condTupleNode.addTupleSet(implicitFlowTupleSet);
+      System.out.println("condTupleNode=" + condTupleNode);
+
+      analyzeFlowBlockNode(md, bn.getVarTable(), ln.getUpdate(), condTupleNode);
+      analyzeFlowBlockNode(md, bn.getVarTable(), ln.getBody(), condTupleNode);
+
+    }
 
   }
 
-  private void analyzeIfStatementNode(MethodDescriptor md, SymbolTable nametable,
-      IfStatementNode bsn) {
-    // TODO Auto-generated method stub
+  private void analyzeFlowIfStatementNode(MethodDescriptor md, SymbolTable nametable,
+      IfStatementNode isn, NodeTupleSet implicitFlowTupleSet) {
+
+    NodeTupleSet condTupleNode = new NodeTupleSet();
+    analyzeFlowExpressionNode(md, nametable, isn.getCondition(), condTupleNode, null,
+        implicitFlowTupleSet);
+
+    // add edges from condNodeTupleSet to all nodes of conditional nodes
+    condTupleNode.addTupleSet(implicitFlowTupleSet);
+    analyzeFlowBlockNode(md, nametable, isn.getTrueBlock(), condTupleNode);
+
+    if (isn.getFalseBlock() != null) {
+      analyzeFlowBlockNode(md, nametable, isn.getFalseBlock(), condTupleNode);
+    }
 
   }
 
-  private NTuple<Descriptor> analyzeFlowDeclarationNode(MethodDescriptor md, SymbolTable nametable,
-      DeclarationNode dn, NTuple<Descriptor> base) {
+  private void analyzeFlowDeclarationNode(MethodDescriptor md, SymbolTable nametable,
+      DeclarationNode dn, NodeTupleSet implicitFlowTupleSet) {
 
     VarDescriptor vd = dn.getVarDescriptor();
-    base.add(vd);
-    getFlowGraph(md).createNewFlowNode(base);
+    NTuple<Descriptor> tupleLHS = new NTuple<Descriptor>();
+    tupleLHS.add(vd);
+    getFlowGraph(md).createNewFlowNode(tupleLHS);
 
     if (dn.getExpression() != null) {
 
-      NTuple<Descriptor> rhsDescTuple =
-          analyzeFlowExpressionNode(md, nametable, dn.getExpression(), new NTuple<Descriptor>());
+      NodeTupleSet tupleSetRHS = new NodeTupleSet();
+      analyzeFlowExpressionNode(md, nametable, dn.getExpression(), tupleSetRHS, null,
+          implicitFlowTupleSet);
 
       // add a new flow edge from rhs to lhs
-      if (rhsDescTuple != null) { // rhs is null when values come from the top
-                                  // location
-        getFlowGraph(md).addValueFlowEdge(rhsDescTuple, base);
+      for (Iterator<NTuple<Descriptor>> iter = tupleSetRHS.iterator(); iter.hasNext();) {
+        NTuple<Descriptor> from = iter.next();
+        addFlowGraphEdge(md, from, tupleLHS);
       }
 
     }
 
-    return null;
-
   }
 
   private void analyzeBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
-      BlockExpressionNode ben) {
-    analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null);
+      BlockExpressionNode ben, NodeTupleSet implicitFlowTupleSet) {
+    analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null, null, implicitFlowTupleSet);
   }
 
   private NTuple<Descriptor> analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable,
-      ExpressionNode en, NTuple<Descriptor> base) {
+      ExpressionNode en, NodeTupleSet nodeSet, NTuple<Descriptor> base,
+      NodeTupleSet implicitFlowTupleSet) {
+
+    // note that expression node can create more than one flow node
+    // nodeSet contains of flow nodes
+    // base is always assigned to null except name node case!
+
+    NTuple<Descriptor> flowTuple;
 
     switch (en.kind()) {
 
     case Kind.AssignmentNode:
-      analyzeFlowAssignmentNode(md, nametable, (AssignmentNode) en, base);
+      analyzeFlowAssignmentNode(md, nametable, (AssignmentNode) en, base, implicitFlowTupleSet);
       break;
 
     case Kind.FieldAccessNode:
-      analyzeFieldAccessNode(md, nametable, (FieldAccessNode) en);
-      break;
+      flowTuple =
+          analyzeFlowFieldAccessNode(md, nametable, (FieldAccessNode) en, nodeSet, base,
+              implicitFlowTupleSet);
+      nodeSet.addTuple(flowTuple);
+      return flowTuple;
 
     case Kind.NameNode:
-      return analyzeFlowNameNode(md, nametable, (NameNode) en, base);
+      NodeTupleSet nameNodeSet = new NodeTupleSet();
+      flowTuple =
+          analyzeFlowNameNode(md, nametable, (NameNode) en, nameNodeSet, base, implicitFlowTupleSet);
+      nodeSet.addTuple(flowTuple);
+      return flowTuple;
 
     case Kind.OpNode:
-      // return analyzeOpNode(md, nametable, (OpNode) en, new
-      // HashSet<FlowNode>());
+      analyzeFlowOpNode(md, nametable, (OpNode) en, nodeSet, implicitFlowTupleSet);
       break;
 
     case Kind.CreateObjectNode:
@@ -332,19 +390,21 @@ public class LocationInference {
 
   }
 
-  private Set<FlowNode> analyzeOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
-      Set<FlowNode> nodeSet) {
+  private void analyzeFlowOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
+      NodeTupleSet nodeSet, NodeTupleSet implicitFlowTupleSet) {
 
-    ClassDescriptor cd = md.getClassDesc();
+    NodeTupleSet leftOpSet = new NodeTupleSet();
+    NodeTupleSet rightOpSet = new NodeTupleSet();
 
     // left operand
-    NTuple<Descriptor> leftOpTuple =
-        analyzeFlowExpressionNode(md, nametable, on.getLeft(), new NTuple<Descriptor>());
+    analyzeFlowExpressionNode(md, nametable, on.getLeft(), leftOpSet, null, implicitFlowTupleSet);
+    System.out.println("leftOpSet=" + leftOpSet);
 
     if (on.getRight() != null) {
       // right operand
-      NTuple<Descriptor> rightOpTuple =
-          analyzeFlowExpressionNode(md, nametable, on.getRight(), new NTuple<Descriptor>());
+      analyzeFlowExpressionNode(md, nametable, on.getRight(), rightOpSet, null,
+          implicitFlowTupleSet);
+      System.out.println("rightOpSet=" + rightOpSet);
     }
 
     Operation op = on.getOp();
@@ -355,7 +415,8 @@ public class LocationInference {
     case Operation.UNARYMINUS:
     case Operation.LOGIC_NOT:
       // single operand
-      // return leftLoc;
+      nodeSet.addTupleSet(leftOpSet);
+      break;
 
     case Operation.LOGIC_OR:
     case Operation.LOGIC_AND:
@@ -379,12 +440,10 @@ public class LocationInference {
     case Operation.RIGHTSHIFT:
     case Operation.URIGHTSHIFT:
 
-      Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
-      // inputSet.add(leftLoc);
-      // inputSet.add(rightLoc);
-      // CompositeLocation glbCompLoc =
-      // CompositeLattice.calculateGLB(inputSet, generateErrorMessage(cd, on));
-      // return glbCompLoc;
+      // there are two operands
+      nodeSet.addTupleSet(leftOpSet);
+      nodeSet.addTupleSet(rightOpSet);
+      break;
 
     default:
       throw new Error(op.toString());
@@ -392,11 +451,16 @@ public class LocationInference {
   }
 
   private NTuple<Descriptor> analyzeFlowNameNode(MethodDescriptor md, SymbolTable nametable,
-      NameNode nn, NTuple<Descriptor> base) {
+      NameNode nn, NodeTupleSet nodeSet, NTuple<Descriptor> base, NodeTupleSet implicitFlowTupleSet) {
+
+    if (base == null) {
+      base = new NTuple<Descriptor>();
+    }
 
     NameDescriptor nd = nn.getName();
     if (nd.getBase() != null) {
-      analyzeFlowExpressionNode(md, nametable, nn.getExpression(), base);
+      analyzeFlowExpressionNode(md, nametable, nn.getExpression(), nodeSet, base,
+          implicitFlowTupleSet);
     } else {
       String varname = nd.toString();
       if (varname.equals("this")) {
@@ -443,12 +507,10 @@ public class LocationInference {
           base.add(md.getThis());
         }
 
-        // Location fieldLoc = (Location) fd.getType().getExtension();
-        // loc.addLocation(fieldLoc);
         base.add(fd);
       } else if (d == null) {
         // access static field
-        // FieldDescriptor fd = nn.getField();
+        // FieldDescriptor fd = nn.getField();addFlowGraphEdge
         //
         // MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
         // String globalLocId = localLattice.getGlobalLoc();
@@ -473,17 +535,57 @@ public class LocationInference {
 
   }
 
-  private void analyzeFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode en) {
-    // TODO Auto-generated method stub
+  private NTuple<Descriptor> analyzeFlowFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
+      FieldAccessNode fan, NodeTupleSet nodeSet, NTuple<Descriptor> base,
+      NodeTupleSet implicitFlowTupleSet) {
+
+    ExpressionNode left = fan.getExpression();
+    TypeDescriptor ltd = left.getType();
+    FieldDescriptor fd = fan.getField();
+
+    String varName = null;
+    if (left.kind() == Kind.NameNode) {
+      NameDescriptor nd = ((NameNode) left).getName();
+      varName = nd.toString();
+    }
+
+    if (ltd.isClassNameRef() || (varName != null && varName.equals("this"))) {
+      // using a class name directly or access using this
+      if (fd.isStatic() && fd.isFinal()) {
+        // loc.addLocation(Location.createTopLocation(md));
+        // return loc;
+      }
+    }
+
+    // if (left instanceof ArrayAccessNode) {
+    // ArrayAccessNode aan = (ArrayAccessNode) left;
+    // left = aan.getExpression();
+    // }
+    // fanNodeSet
+    base = analyzeFlowExpressionNode(md, nametable, left, nodeSet, base, implicitFlowTupleSet);
+
+    if (!left.getType().isPrimitive()) {
+
+      if (fd.getSymbol().equals("length")) {
+        // TODO
+        // array.length access, return the location of the array
+        // return loc;
+      }
+
+      base.add(fd);
+    }
+
+    return base;
 
   }
 
   private void analyzeFlowAssignmentNode(MethodDescriptor md, SymbolTable nametable,
-      AssignmentNode an, NTuple<Descriptor> base) {
+      AssignmentNode an, NTuple<Descriptor> base, NodeTupleSet implicitFlowTupleSet) {
 
     System.out.println("analyzeFlowAssignmentNode=" + an);
 
-    ClassDescriptor cd = md.getClassDesc();
+    NodeTupleSet nodeSetRHS = new NodeTupleSet();
+    NodeTupleSet nodeSetLHS = new NodeTupleSet();
 
     boolean postinc = true;
     if (an.getOperation().getBaseOp() == null
@@ -494,19 +596,40 @@ public class LocationInference {
 
     // if LHS is array access node, need to capture value flows between an array
     // and its index value
-    analyzeFlowExpressionNode(md, nametable, an.getDest(), base);
+    analyzeFlowExpressionNode(md, nametable, an.getDest(), nodeSetLHS, null, implicitFlowTupleSet);
+    System.out.println("ASSIGNMENT NODE nodeSetLHS=" + nodeSetLHS);
     // NTuple<Descriptor> lhsDescTuple = analyzeFlowExpressionNode(md,
     // nametable, an.getDest(), base);
 
     if (!postinc) {
       // analyze value flows of rhs expression
-      NTuple<Descriptor> rhsDescTuple =
-          analyzeFlowExpressionNode(md, nametable, an.getSrc(), new NTuple<Descriptor>());
+      analyzeFlowExpressionNode(md, nametable, an.getSrc(), nodeSetRHS, null, implicitFlowTupleSet);
+      System.out.println("ASSIGNMENT NODE nodeSetRHS=" + nodeSetRHS);
+
+      // creates edges from RHS to LHS
+      for (Iterator<NTuple<Descriptor>> iter = nodeSetRHS.iterator(); iter.hasNext();) {
+        NTuple<Descriptor> fromTuple = iter.next();
+        for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
+          NTuple<Descriptor> toTuple = iter2.next();
+          addFlowGraphEdge(md, fromTuple, toTuple);
+        }
+      }
 
-    } else {
+      // creates edges from implicitFlowTupleSet to LHS
+      for (Iterator<NTuple<Descriptor>> iter = implicitFlowTupleSet.iterator(); iter.hasNext();) {
+        NTuple<Descriptor> fromTuple = iter.next();
+        for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
+          NTuple<Descriptor> toTuple = iter2.next();
+          addFlowGraphEdge(md, fromTuple, toTuple);
+        }
+      }
 
+    } else {
       // postinc case
-      // src & dest are same
+      for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
+        NTuple<Descriptor> tuple = iter2.next();
+        addFlowGraphEdge(md, tuple, tuple);
+      }
 
     }
 
@@ -516,4 +639,24 @@ public class LocationInference {
     return mapMethodDescriptorToFlowGraph.get(md);
   }
 
+  public void addFlowGraphEdge(MethodDescriptor md, NTuple<Descriptor> from, NTuple<Descriptor> to) {
+    FlowGraph graph = getFlowGraph(md);
+    graph.addValueFlowEdge(from, to);
+  }
+
+  public void _debug_printGraph() {
+    Set<MethodDescriptor> keySet = mapMethodDescriptorToFlowGraph.keySet();
+
+    for (Iterator<MethodDescriptor> iterator = keySet.iterator(); iterator.hasNext();) {
+      MethodDescriptor md = (MethodDescriptor) iterator.next();
+      FlowGraph fg = mapMethodDescriptorToFlowGraph.get(md);
+      try {
+        fg.writeGraph();
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+
+  }
+
 }