diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index 58f7eda52..234f6f09a 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -1420,6 +1420,26 @@ public class RhinoToAstTranslator { return result; } + + case Token.GET_REF: { + // read of __proto__ + // first and only child c1 is of type Token.REF_SPECIAL whose NAME_PROP property should be "__proto__". + // c1 has a single child, the base pointer for the reference + Node child1 = n.getFirstChild(); + assert child1.getType() == Token.REF_SPECIAL; + assert child1.getProp(Node.NAME_PROP).equals("__proto__"); + Node receiver = child1.getFirstChild(); + assert child1.getNext() == null; + CAstNode rcvr = walkNodes(receiver, context); + final CAstNode result = Ast.makeNode(CAstNode.OBJECT_REF, rcvr, Ast.makeConstant("__proto__")); + + if (context.getCatchTarget() != null) { + context.cfg().map(result, result); + context.cfg().add(result, context.getCatchTarget(), JavaScriptTypes.TypeError); + } + + return result; + } case Token.SETPROP: case Token.SETELEM: { @@ -1432,6 +1452,23 @@ public class RhinoToAstTranslator { return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, walkNodes(elt, context)), walkNodes(val, context)); } + + case Token.SET_REF: { + // first child c1 is of type Token.REF_SPECIAL whose NAME_PROP property should be "__proto__". + // c1 has a single child, the base pointer for the reference + // second child c2 is RHS of assignment + Node child1 = n.getFirstChild(); + assert child1.getType() == Token.REF_SPECIAL; + assert child1.getProp(Node.NAME_PROP).equals("__proto__"); + Node receiver = child1.getFirstChild(); + Node val = child1.getNext(); + + CAstNode rcvr = walkNodes(receiver, context); + + return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, Ast.makeConstant("__proto__")), + walkNodes(val, context)); + } + case Token.DELPROP: { Node receiver = n.getFirstChild(); diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index a910bfad0..d57d4c0da 100644 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -71,6 +71,8 @@ Object.prototype = { prototype: null, + __proto__: null, + constructor: Object, toString: function toString() { @@ -97,6 +99,7 @@ Object.prototype = { }; + /************************************************************************/ /* Function properties, see spec 15.3 */ /************************************************************************/ @@ -105,6 +108,8 @@ Function.prototype = { constructor: Function, + __proto__: Object.prototype, + toString: function functionToString() { return primitive("FunctionToString", this); }, @@ -126,7 +131,7 @@ Function.prototype = { Array.prototype = { - prototype: Object.prototype, + __proto__: Object.prototype, constructor: Array, @@ -245,7 +250,7 @@ Array.prototype = { String.prototype = { - prototype: Object.prototype, + __proto__: Object.prototype, constructor: String, @@ -321,7 +326,7 @@ String.prototype = { Number.prototype = { - prototype: Object.prototype, + __proto__: Object.prototype, constructor: Number, @@ -409,7 +414,7 @@ Math = { RegExp.prototype = { - prototype: Object.prototype, + __proto__: Object.prototype, constructor: RegExp diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java index c3b00ad38..aa94c02bb 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java @@ -42,6 +42,10 @@ import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.Pair; +/** + * generates instructions to simulate the semantics of JS constructor invocations + * + */ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { private static final boolean DEBUG = false; @@ -88,7 +92,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(5, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference()))); - S.addStatement(insts.PutInstruction(5, 4, "prototype")); + S.addStatement(insts.PutInstruction(5, 4, "__proto__")); S.getNextProgramCounter(); S.addConstant(new Integer(8), new ConstantValue(value)); @@ -111,7 +115,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(6, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference()))); - S.addStatement(insts.PutInstruction(6, 5, "prototype")); + S.addStatement(insts.PutInstruction(6, 5, "__proto__")); S.getNextProgramCounter(); S.addStatement(insts.PutInstruction(6, 2, "$value")); @@ -138,6 +142,9 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { } } + /** + * create a method for constructing an Object with no arguments passed + */ private IMethod makeNullaryObjectConstructor(IClass cls) { JSInstructionFactory insts = (JSInstructionFactory)cls.getClassLoader().getInstructionFactory(); MethodReference ref = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Object); @@ -148,7 +155,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(5, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object))); - S.addStatement(insts.PutInstruction(5, 4, "prototype")); + S.addStatement(insts.PutInstruction(5, 4, "__proto__")); S.getNextProgramCounter(); S.addStatement(insts.ReturnInstruction(5, false)); @@ -205,7 +212,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(6, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Array))); - S.addStatement(insts.PutInstruction(6, 5, "prototype")); + S.addStatement(insts.PutInstruction(6, 5, "__proto__")); S.getNextProgramCounter(); S.addStatement(insts.PutInstruction(6, 2, "length")); @@ -230,7 +237,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { insts.NewInstruction(nargs + 5, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Array))); - S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "prototype")); + S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__")); S.getNextProgramCounter(); S.addConstant(new Integer(nargs + 7), new ConstantValue(nargs)); @@ -355,6 +362,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(7, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object))); + // TODO fix these writes to operate on __proto__, once we're sure we're doing the right thing here S.addStatement(insts.PutInstruction(7, 4, "prototype")); S.getNextProgramCounter(); @@ -466,7 +474,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object))); - S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "prototype")); + S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__")); S.getNextProgramCounter(); CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter()); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java index b396fe828..e33d33225 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java @@ -120,8 +120,8 @@ public class PropertyReadExpander extends CAstRewriter