/** * Displays the heap so that it can be visualized as a graph * * @return */ public String toGraphRep() { Location global = this.getGlobal(); String graphviz = "digraph G{"; Set<Location> locs = heap.keySet(); for (Location l : locs) { JSObject lj = heap.get(l); if (l == global) { graphviz += l.getObjValue() + "[ fillcolor = \"green\", style = \"filled\"];"; } if (lj.isin("at_Taint")) { if (lj.get("at_Taint") != null) { if (((SecurityType) lj.get("at_Taint")).isTainted()) { graphviz += l.getObjValue() + "[ fillcolor = \"red\", style = \"filled\"];"; } else { graphviz += l.getObjValue() + "[ fillcolor = \"lightblue\", style = \"filled\"];"; } } } Set<String> keys = lj.getKeySet(); for (String key : keys) { ObjectValue ov = lj.get(key); if (ov != null) { if (ov instanceof Location) { if (key.equals("innerHTML")) { graphviz += ov.getObjValue() + "[ fillcolor = \"lightblue\", style = \"filled\"];"; } JSObject jsov = heap.get(ov); if (jsov != null) { if (jsov.isin("at_Taint")) { if (jsov.get("at_Taint") != null) { if (((SecurityType) jsov.get("at_Taint")).isTainted()) { graphviz += ov.getObjValue() + "[ fillcolor = \"red\", style = \"filled\"];"; } else { graphviz += ov.getObjValue() + "[ fillcolor = \"lightblue\", style = \"filled\"];"; } } } } String key_new = key; if (key.endsWith("\"")) { key_new = key.substring(1, key.length() - 1); key = key_new; } // if(!key_new.equals("at_Class") && !key_new.equals("__constructor__") && // !key_new.equals("at_FScope") && !key_new.equals("at_Scope") ){ graphviz += "\n" + l.getObjValue() + " -> " + ov.getObjValue() + " [ label = \"" + key_new + "\" ];"; // } } } } } graphviz += "}"; return graphviz; }
/** * Recursive function to check if the JSObjects in both the heaps match * * @param other * @param this_global * @param other_global * @return */ private boolean checkContentEquality(Heap other, Location this_obj, Location other_obj) { JSObject curr_obj = this.get(this_obj); JSObject test_obj = other.get(other_obj); if (curr_obj == null && test_obj == null) return true; if ((curr_obj != null && test_obj == null) || (curr_obj == null && test_obj != null)) return false; SecurityType curr_taint = (SecurityType) curr_obj.get("at_Taint"); SecurityType test_taint = (SecurityType) test_obj.get("at_Taint"); // Proceed further only if the JSObject taints match if (curr_taint.equals(test_taint)) { // If the location is a dummy object, it suffices to just check the taints if (other.isDummy(other_obj) && this.isDummy(this_obj)) { return true; } Set<String> this_keyset = curr_obj.getKeySet(); Set<String> other_keyset = test_obj.getKeySet(); // Proceed further only if the keys in both the JSObjects match if (this_keyset.containsAll(other_keyset) && other_keyset.containsAll(this_keyset)) { // For each key compare the object values boolean retval = true; for (String key : this_keyset) { // we don't want to go into libraryProperties as they will lead to the parents // creating a circular check and infinite recursion if (ProgramAnalyzerC.libraryProperties.contains(key)) continue; if (key.equals("at_Taint")) // we already compared taints continue; ObjectValue this_val = curr_obj.get(key); ObjectValue other_val = test_obj.get(key); if (this_val == null && other_val == null) { continue; } if ((this_val == null && other_val != null) || (this_val != null && other_val == null)) { retval = false; return retval; } if (this_val.getClass() != other_val.getClass()) { retval = false; // If the class types don't match return retval; } if (this_val instanceof Location) retval = retval && checkContentEquality(other, (Location) this_val, (Location) other_val); if (this_val instanceof FunctionValue) retval = retval && ((FunctionValue) this_val).equals((FunctionValue) other_val); if (this_val instanceof ObjectValue) retval = retval && this_val.equals(other_val); if (retval == false) return false; } return retval; } } return false; }