diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java index 4108c37a6..e50a55cd2 100644 --- a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/RhinoToAstTranslator.java @@ -896,35 +896,44 @@ public class RhinoToAstTranslator { case Token.FINALLY: case Token.BLOCK: case Token.LABEL: { -// CAstNode ast; - Node c1 = n.getFirstChild(); - if (c1 != null && c1.getType() == Token.SWITCH) { - Node switchValue = c1.getFirstChild(); + Node c1 = n.getFirstChild(); + if (c1 != null && c1.getType() == Token.SWITCH) { + Node switchValue = c1.getFirstChild(); - CAstNode defaultLabel = Ast.makeNode(CAstNode.LABEL_STMT, Ast.makeNode(CAstNode.EMPTY)); - context.cfg().map(defaultLabel, defaultLabel); + CAstNode defaultLabel = Ast.makeNode(CAstNode.LABEL_STMT, Ast.makeNode(CAstNode.EMPTY)); + context.cfg().map(defaultLabel, defaultLabel); - for (Node kase = switchValue.getNext(); kase != null; kase = kase.getNext()) { - assert kase.getType() == Token.CASE; - Node caseLbl = kase.getFirstChild(); - Node target = ((Node.Jump) kase).target; - context.cfg().add(c1, target, walkNodes(caseLbl, context)); + List labelCasts = new ArrayList(); + for (Node kase = switchValue.getNext(); kase != null; kase = kase.getNext()) { + assert kase.getType() == Token.CASE; + Node caseLbl = kase.getFirstChild(); + Node target = ((Node.Jump) kase).target; + CAstNode labelCast = walkNodes(caseLbl, context); + labelCasts.add(labelCast); + context.cfg().add(c1, target, labelCast); + } + CAstNode[] children = new CAstNode[labelCasts.size()+1]; + int i = 0; + children[i++] = Ast.makeNode(CAstNode.BLOCK_STMT, defaultLabel, gatherChildren(n, context, 1)); + + // Note that we are placing the labels as children in the AST + // even if they are not used, because we want them copied when AST is re-written. + for (CAstNode labelCast : labelCasts){ + children[i++] = labelCast; + } + + context.cfg().add(c1, defaultLabel, CAstControlFlowMap.SWITCH_DEFAULT); + CAstNode switchAst = Ast.makeNode(CAstNode.SWITCH, walkNodes(switchValue, context), children); + + noteSourcePosition(context, switchAst, c1); + context.cfg().map(c1, switchAst); + return switchAst; } - context.cfg().add(c1, defaultLabel, CAstControlFlowMap.SWITCH_DEFAULT); - - CAstNode switchAst = Ast.makeNode(CAstNode.SWITCH, walkNodes(switchValue, context), Ast.makeNode(CAstNode.BLOCK_STMT, - defaultLabel, gatherChildren(n, context, 1))); - - noteSourcePosition(context, switchAst, c1); - context.cfg().map(c1, switchAst); - return switchAst; + else { + return Ast.makeNode(CAstNode.BLOCK_STMT, gatherChildren(n, context)); + } } - - else { - return Ast.makeNode(CAstNode.BLOCK_STMT, gatherChildren(n, context)); - } - } case Token.EXPR_VOID: case Token.EXPR_RESULT: { diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js b/com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js new file mode 100644 index 000000000..5e7d7d346 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js @@ -0,0 +1,7 @@ +function f(){ + switch (a){ + case b: + return "wow" + } +} +f(); diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java index eb5368119..70b1bb284 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java @@ -256,8 +256,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForPrototypeContamination); verifyNoEdges(CG, "suffix:test1", "suffix:foo_of_B"); verifyNoEdges(CG, "suffix:test2", "suffix:foo_of_A"); - } + @Test public void testRewriterDoesNotChangeLablesBug() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "rewrite_does_not_change_lables_bug.js"); + // all we need is for it to finish building CG successfully. + } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java index 2acedff76..0da1861ba 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java @@ -111,12 +111,12 @@ public abstract class CAstRewriter, K e } while (LS.hasNext()) { - Object label = LS.next(); - CAstNode oldTarget = orig.getTarget(oldSource, label); + Object origLabel = LS.next(); + CAstNode oldTarget = orig.getTarget(oldSource, origLabel); assert oldTarget != null; if (DEBUG) { - System.err.println(("old: " + label + " --> " + CAstPrinter.print(oldTarget))); + System.err.println(("old: " + origLabel + " --> " + CAstPrinter.print(oldTarget))); } Pair targetKey; @@ -130,16 +130,23 @@ public abstract class CAstRewriter, K e } } while (!nodeMap.containsKey(targetKey)); + Object newLabel; + if (nodeMap.containsKey(Pair.make(origLabel, targetKey.snd))){ // label is mapped too + newLabel = nodeMap.get(Pair.make(origLabel, targetKey.snd)); + } else { + newLabel = origLabel; + } + CAstNode newTarget; if (nodeMap.containsKey(targetKey)) { newTarget = (CAstNode) nodeMap.get(targetKey); - newMap.add(newSource, newTarget, label); + newMap.add(newSource, newTarget, newLabel); allNewTargetNodes.add(newTarget); } else { - newTarget = flowOutTo(nodeMap, oldSource, label, oldTarget, orig, newSrc); + newTarget = flowOutTo(nodeMap, oldSource, origLabel, oldTarget, orig, newSrc); allNewTargetNodes.add(newTarget); - newMap.add(newSource, newTarget, label); + newMap.add(newSource, newTarget, newLabel); if (newTarget != CAstControlFlowMap.EXCEPTION_TO_EXIT && !mappedOutsideNodes.contains(newTarget)) { mappedOutsideNodes.add(newTarget); newMap.map(newTarget, newTarget); @@ -147,8 +154,8 @@ public abstract class CAstRewriter, K e } if (DEBUG) { - System.err.println(("mapping:old: " + CAstPrinter.print(oldSource) + "-- " + label + " --> " + CAstPrinter.print(oldTarget))); - System.err.println(("mapping:new: " + CAstPrinter.print(newSource) + "-- " + label + " --> " + CAstPrinter.print(newTarget))); + System.err.println(("mapping:old: " + CAstPrinter.print(oldSource) + "-- " + origLabel + " --> " + CAstPrinter.print(oldTarget))); + System.err.println(("mapping:new: " + CAstPrinter.print(newSource) + "-- " + newLabel + " --> " + CAstPrinter.print(newTarget))); } } }