From c1c73620aa141435021d162f6914e19e03c941ff Mon Sep 17 00:00:00 2001 From: Eliott Robson Date: Wed, 1 Mar 2017 13:41:01 +0000 Subject: [PATCH 1/2] Implementing sid at instrumentation time --- src/js/instrument/esnstrument.js | 127 ++++++++++++------ src/js/runtime/analysis.js | 146 ++++++++++----------- src/js/runtime/analysisCallbackTemplate.js | 93 ++++++++----- 3 files changed, 217 insertions(+), 149 deletions(-) mode change 100644 => 100755 src/js/instrument/esnstrument.js mode change 100644 => 100755 src/js/runtime/analysis.js diff --git a/src/js/instrument/esnstrument.js b/src/js/instrument/esnstrument.js old mode 100644 new mode 100755 index ee67f13d..668e0194 --- a/src/js/instrument/esnstrument.js +++ b/src/js/instrument/esnstrument.js @@ -225,6 +225,10 @@ if (typeof J$ === 'undefined') { return createLiteralAst(tmpIid); } + function getSid() { + var tmpSid = sandbox.sid; + return createLiteralAst(tmpSid); + } function printLineInfoAux(i, ast) { if (ast && ast.loc) { @@ -353,7 +357,8 @@ if (typeof J$ === 'undefined') { printIidToLoc(node); var ret = replaceInExpr( logPutFieldFunName + - "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4," + (createBitPattern(isComputed, false)) + ")", + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + RP + "5, " + (createBitPattern(isComputed, false)) + ")", + getSid(), getIid(), base, offset, @@ -370,7 +375,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_PROPERTY_BINARY_ASSIGNMENT || Config.INSTR_PROPERTY_BINARY_ASSIGNMENT(op, node.computed ? null : offset.value, node)) { printModIidToLoc(node); var ret = replaceInExpr( - logAssignFunName + "(" + RP + "1," + RP + "2," + RP + "3," + RP + "4," + (createBitPattern(isComputed)) + ")(" + RP + "5)", + logAssignFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + RP + "5, " + (createBitPattern(isComputed)) + ")(" + RP + "5)", + getSid(), getIid(), base, offset, @@ -388,7 +394,8 @@ if (typeof J$ === 'undefined') { printIidToLoc(node); printSpecialIidToLoc(node.callee); var ret = replaceInExpr( - logMethodCallFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + (createBitPattern(isCtor, isComputed)) + ")", + logMethodCallFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + (createBitPattern(isCtor, isComputed)) + ")", + getSid(), getIid(), base, offset @@ -400,7 +407,8 @@ if (typeof J$ === 'undefined') { function wrapFunCall(node, ast, isCtor) { printIidToLoc(node); var ret = replaceInExpr( - logFunCallFunName + "(" + RP + "1, " + RP + "2, " + (createBitPattern(isCtor)) + ")", + logFunCallFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + (createBitPattern(isCtor)) + ")", + getSid(), getIid(), ast ); @@ -412,7 +420,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_GETFIELD || Config.INSTR_GETFIELD(node.computed ? null : offset.value, node)) { printIidToLoc(node); var ret = replaceInExpr( - logGetFieldFunName + "(" + RP + "1, " + RP + "2, " + RP + "3," + (createBitPattern(isComputed,false, false)) + ")", + logGetFieldFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + (createBitPattern(isComputed,false, false)) + ")", + getSid(), getIid(), base, offset @@ -428,7 +437,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_READ || Config.INSTR_READ(name, node)) { printIidToLoc(node); var ret = replaceInExpr( - logReadFunName + "(" + RP + "1, " + RP + "2, " + RP + "3," + (createBitPattern(isGlobal,isScriptLocal)) + ")", + logReadFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + (createBitPattern(isGlobal,isScriptLocal)) + ")", + getSid(), isReUseIid ? getPrevIidNoInc() : getIid(), name, val @@ -477,7 +487,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_WRITE || Config.INSTR_WRITE(name, node)) { printIidToLoc(node); var ret = replaceInExpr( - logWriteFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4," + (createBitPattern(isGlobal,isScriptLocal,isDeclaration)) + ")", + logWriteFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + RP + "5, " + (createBitPattern(isGlobal,isScriptLocal,isDeclaration)) + ")", + getSid(), getIid(), name, val, @@ -613,7 +624,8 @@ if (typeof J$ === 'undefined') { internalFunId = getFnIdFromAst(scope.funNodes[node.name]); } ret = replaceInExpr( - logLitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3," + hasGetterSetter + ", " + internalFunId + ")", + logLitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + hasGetterSetter + ", " + internalFunId + ")", + getSid(), getIid(), ast, createLiteralAst(funId), @@ -621,7 +633,8 @@ if (typeof J$ === 'undefined') { ); } else { ret = replaceInExpr( - logLitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3," + hasGetterSetter + ")", + logLitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + hasGetterSetter + ")", + getSid(), getIid(), ast, createLiteralAst(funId) @@ -641,7 +654,8 @@ if (typeof J$ === 'undefined') { expr = createIdentifierAst("undefined"); } var ret = replaceInExpr( - logReturnFunName + "(" + RP + "1, " + RP + "2)", + logReturnFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getIid(), expr ); @@ -652,7 +666,8 @@ if (typeof J$ === 'undefined') { function wrapThrow(node, expr) { printIidToLoc(expr); var ret = replaceInExpr( - logThrowFunName + "(" + RP + "1, " + RP + "2)", + logThrowFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getIid(), expr ); @@ -666,7 +681,11 @@ if (typeof J$ === 'undefined') { if (!ast || ast.type.indexOf("Expression") <= 0) return ast; printIidToLoc(node); var ret = replaceInExpr( - logX1FunName + "(" + RP + "1," + RP + "2)", getIid(), ast); + logX1FunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), + getIid(), + ast + ); transferLoc(ret, node); return ret; } else { @@ -677,7 +696,8 @@ if (typeof J$ === 'undefined') { function wrapHash(node, ast) { printIidToLoc(node); var ret = replaceInExpr( - logHashFunName + "(" + RP + "1, " + RP + "2)", + logHashFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getIid(), ast ); @@ -688,8 +708,9 @@ if (typeof J$ === 'undefined') { function wrapEvalArg(ast) { printIidToLoc(ast); var ret = replaceInExpr( - instrumentCodeFunName + "(" + RP + "1, " + RP + "2, true)", + instrumentCodeFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, true)", ast, + getSid(), getIid() ); transferLoc(ret, ast); @@ -700,7 +721,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_UNARY || Config.INSTR_UNARY(operator, node)) { printOpIidToLoc(node); var ret = replaceInExpr( - logUnaryOpFunName + "(" + RP + "1," + RP + "2," + RP + "3)", + logUnaryOpFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4)", + getSid(), getOpIid(), createLiteralAst(operator), argument @@ -716,7 +738,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_BINARY || Config.INSTR_BINARY(operator, operator)) { printOpIidToLoc(node); var ret = replaceInExpr( - logBinaryOpFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4," + (createBitPattern(isComputed, false, false)) + ")", + logBinaryOpFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + RP + "5, " + (createBitPattern(isComputed, false, false)) + ")", + getSid(), getOpIid(), createLiteralAst(operator), left, @@ -733,7 +756,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("&&", node)) { printCondIidToLoc(node); var ret = replaceInExpr( - logConditionalFunName + "(" + RP + "1, " + RP + "2)?" + RP + "3:" + logLastFunName + "()", + logConditionalFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)?" + RP + "3:" + logLastFunName + "()", + getSid(), getCondIid(), left, right @@ -749,7 +773,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("||", node)) { printCondIidToLoc(node); var ret = replaceInExpr( - logConditionalFunName + "(" + RP + "1, " + RP + "2)?" + logLastFunName + "():" + RP + "3", + logConditionalFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)?" + logLastFunName + "():" + RP + "3", + getSid(), getCondIid(), left, right @@ -765,7 +790,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("switch", node)) { printCondIidToLoc(node); var ret = replaceInExpr( - logSwitchLeftFunName + "(" + RP + "1, " + RP + "2)", + logSwitchLeftFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getCondIid(), discriminant ); @@ -780,7 +806,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("switch", node)) { printCondIidToLoc(node); var ret = replaceInExpr( - logSwitchRightFunName + "(" + RP + "1, " + RP + "2)", + logSwitchRightFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getCondIid(), test ); @@ -795,7 +822,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("with", node)) { printIidToLoc(node); var ret = replaceInExpr( - logWithFunName + "(" + RP + "1, " + RP + "2)", + logWithFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getIid(), node ); @@ -814,7 +842,8 @@ if (typeof J$ === 'undefined') { if (!Config.INSTR_CONDITIONAL || Config.INSTR_CONDITIONAL("other", node)) { printCondIidToLoc(node); var ret = replaceInExpr( - logConditionalFunName + "(" + RP + "1, " + RP + "2)", + logConditionalFunName + "(" + RP + "1, " + RP + "2, " + RP + "3)", + getSid(), getCondIid(), test ); @@ -853,15 +882,17 @@ if (typeof J$ === 'undefined') { if (isAssign) ret = replaceInStatement( - RP + "1 = " + logInitFunName + "(" + RP + "2, " + RP + "3, " + RP + "4, " + createBitPattern(isArgumentSync, false, isCatchParam) + ")", + RP + "1 = " + logInitFunName + "(" + RP + "2, " + RP + "3, " + RP + "4, " + RP + "5, " + createBitPattern(isArgumentSync, false, isCatchParam) + ")", lhs, + getSid(), getIid(), name, val ); else ret = replaceInStatement( - logInitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + createBitPattern(isArgumentSync, false, isCatchParam) + ")", + logInitFunName + "(" + RP + "1, " + RP + "2, " + RP + "3, " + RP + "4, " + createBitPattern(isArgumentSync, false, isCatchParam) + ")", + getSid(), getIid(), name, val @@ -874,7 +905,8 @@ if (typeof J$ === 'undefined') { function createCallAsFunEnterStatement(node) { printIidToLoc(node); var ret = replaceInStatement( - logFunctionEnterFunName + "(" + RP + "1,arguments.callee, this, arguments)", + logFunctionEnterFunName + "(" + RP + "1, " + RP + "2, arguments.callee, this, arguments)", + getSid(), getIid() ); transferLoc(ret[0].expression, node); @@ -883,7 +915,8 @@ if (typeof J$ === 'undefined') { function createCallAsScriptEnterStatement(node) { printIidToLoc(node); - var ret = replaceInStatement(logScriptEntryFunName + "(" + RP + "1," + RP + "2, " + RP + "3)", + var ret = replaceInStatement(logScriptEntryFunName + "(" + RP + "1," + RP + "2, " + RP + "3, " + RP + "4)", + getSid(), getIid(), createLiteralAst(instCodeFileName), createLiteralAst(origCodeFileName)); transferLoc(ret[0].expression, node); @@ -953,10 +986,13 @@ if (typeof J$ === 'undefined') { var ret = replaceInStatement( "function n() { jalangiLabel" + l + ": while(true) { try {" + RP + "1} catch(" + JALANGI_VAR + "e) { //console.log(" + JALANGI_VAR + "e); console.log(" + - JALANGI_VAR + "e.stack);\n " + logUncaughtExceptionFunName + "(" + RP + "2," + JALANGI_VAR + + JALANGI_VAR + "e.stack);\n " + logUncaughtExceptionFunName + "(" + RP + "2, " + RP + "3, " + JALANGI_VAR + "e); } finally { if (" + logScriptExitFunName + "(" + - RP + "3)) { " + logLastComputedFunName + "(); continue jalangiLabel" + l + ";\n } else {\n " + logLastComputedFunName + "(); break jalangiLabel" + l + ";\n }}\n }}", body, + RP + "4, " + RP + "5)) { " + logLastComputedFunName + "(); continue jalangiLabel" + l + ";\n } else {\n " + logLastComputedFunName + "(); break jalangiLabel" + l + ";\n }}\n }}", + body, + getSid(), iid1, + getSid(), getIid() ); //console.log(JSON.stringify(ret)); @@ -978,10 +1014,13 @@ if (typeof J$ === 'undefined') { var ret = replaceInStatement( "function n() { jalangiLabel" + l + ": while(true) { try {" + RP + "1} catch(" + JALANGI_VAR + "e) { //console.log(" + JALANGI_VAR + "e); console.log(" + - JALANGI_VAR + "e.stack);\n " + logUncaughtExceptionFunName + "(" + RP + "2," + JALANGI_VAR + + JALANGI_VAR + "e.stack);\n " + logUncaughtExceptionFunName + "(" + RP + "2, " + RP + "3, " + JALANGI_VAR + "e); } finally { if (" + logFunctionReturnFunName + "(" + - RP + "3)) continue jalangiLabel" + l + ";\n else \n return " + logReturnAggrFunName + "();\n }\n }}", body, + RP + "3, " + RP + "4)) continue jalangiLabel" + l + ";\n else \n return " + logReturnAggrFunName + "();\n }\n }}", + body, + getSid(), iid1, + getSid(), getIid() ); //console.log(JSON.stringify(ret)); @@ -1176,9 +1215,9 @@ if (typeof J$ === 'undefined') { var tmp2; if (scope.hasVar(node.left.name)) { - tmp2 = wrapWrite(node, createLiteralAst(node.left.name), tmp1, node.left, false, scope.isGlobal(node.left.name), false); + tmp2 = wrapWrite(node.right, createLiteralAst(node.left.name), tmp1, node.left, false, scope.isGlobal(node.left.name), false); } else { - tmp2 = wrapWriteWithUndefinedCheck(node, createLiteralAst(node.left.name), tmp1, node.left); + tmp2 = wrapWriteWithUndefinedCheck(node.right, createLiteralAst(node.left.name), tmp1, node.left); } tmp2 = wrapLHSOfModStore(node, node.left, tmp2); @@ -1210,7 +1249,8 @@ if (typeof J$ === 'undefined') { var ret = wrapRHSOfModStore(ast, ast, right, op); return ret; } - + + // Should 'Program' nodes in the AST be wrapped with prefix code to load libraries, // code to indicate script entry and exit, etc.? // we need this flag since when we're instrumenting eval'd code, the code is parsed @@ -1232,7 +1272,8 @@ if (typeof J$ === 'undefined') { function mergeBodies(node) { printIidToLoc(node); var ret = replaceInStatement( - "function n() { if (!" + logSampleFunName + "(" + RP + "1, arguments.callee)){" + RP + "2} else {" + RP + "3}}", + "function n() { if (!" + logSampleFunName + "(" + RP + "1, " + RP + "2, arguments.callee)){" + RP + "3} else {" + RP + "4}}", + getSid(), getIid(), node.bodyOrig.body, node.body.body @@ -1909,23 +1950,28 @@ if (typeof J$ === 'undefined') { /** * Instruments the provided code. * - * @param {{isEval: boolean, code: string, thisIid: int, origCodeFileName: string, instCodeFileName: string, inlineSourceMap: boolean, inlineSource: boolean, url: string, isDirect: boolean }} options + * @param {{isEval: boolean, code: string, thisSid: int, thisIid: int, origCodeFileName: string, instCodeFileName: string, inlineSourceMap: boolean, inlineSource: boolean, url: string, isDirect: boolean }} options * @return {{code:string, instAST: object, sourceMapObject: object, sourceMapString: string}} * */ function instrumentCode(options) { var aret, skip = false; var isEval = options.isEval, - code = options.code, thisIid = options.thisIid, inlineSource = options.inlineSource, url = options.url; + code = options.code, + thisSid = options.thisSid || (sandbox.globalSid || (sandbox.globalSid = 0)) + 1, + thisIid = options.thisIid, + inlineSource = options.inlineSource, + url = options.url; iidSourceInfo = {}; initializeIIDCounters(isEval); instCodeFileName = options.instCodeFileName ? options.instCodeFileName : (options.isDirect?"eval":"evalIndirect"); origCodeFileName = options.origCodeFileName ? options.origCodeFileName : (options.isDirect?"eval":"evalIndirect"); + sandbox.sid = thisSid; if (sandbox.analysis && sandbox.analysis.instrumentCodePre) { - aret = sandbox.analysis.instrumentCodePre(thisIid, code, options.isDirect); + aret = sandbox.analysis.instrumentCodePre(thisSid, thisIid, code, options.isDirect); if (aret) { code = aret.code; skip = aret.skip; @@ -1945,11 +1991,10 @@ if (typeof J$ === 'undefined') { // post-process AST to hoist function declarations (required for Firefox) var hoistedFcts = []; newAst = hoistFunctionDeclaration(newAst, hoistedFcts); - var newCode = esotope.generate(newAst, {comment: true ,parse: acorn.parse}); + var newCode = esotope.generate(newAst, {comment: true}); code = newCode + "\n" + noInstr + "\n"; } catch(ex) { - console.log("Failed to instrument", code); - throw ex; + console.log("Failed to instrument "+code+"\n"+ex); } } @@ -1978,7 +2023,7 @@ if (typeof J$ === 'undefined') { } if (isEval && sandbox.analysis && sandbox.analysis.instrumentCode) { - aret = sandbox.analysis.instrumentCode(thisIid, instCode, newAst, options.isDirect); + aret = sandbox.analysis.instrumentCode(thisSid, thisIid, instCode, newAst, options.isDirect); if (aret) { instCode = aret.result; } diff --git a/src/js/runtime/analysis.js b/src/js/runtime/analysis.js old mode 100644 new mode 100755 index 2296f72a..fb6d87e1 --- a/src/js/runtime/analysis.js +++ b/src/js/runtime/analysis.js @@ -109,7 +109,7 @@ if (typeof J$ === 'undefined') { function updateSid(f) { sidStack.push(sandbox.sid); - sandbox.sid = getPropSafe(f, SPECIAL_PROP_SID); + sandbox.sid = f[SPECIAL_PROP_SID]; } @@ -163,11 +163,11 @@ if (typeof J$ === 'undefined') { } } - function invokeEval(base, f, args, iid) { - return f(sandbox.instrumentEvalCode(args[0], iid, false)); + function invokeEval(base, f, args, sid, iid) { + return f(sandbox.instrumentEvalCode(args[0], sid, iid, false)); } - function invokeFunctionDecl(base, f, args, iid) { + function invokeFunctionDecl(base, f, args, sid, iid) { // Invoke with the original parameters to preserve exceptional behavior if input is invalid f.apply(base, args); // Otherwise input is valid, so instrument and invoke via eval @@ -176,20 +176,20 @@ if (typeof J$ === 'undefined') { newArgs[i] = args[i]; } var code = '(function(' + newArgs.join(', ') + ') { ' + args[args.length-1] + ' })'; - var code = sandbox.instrumentEvalCode(code, iid, false); + code = sandbox.instrumentEvalCode(code, sid, iid, false); // Using EVAL_ORG instead of eval() is important as it preserves the scoping semantics of Function() var out = EVAL_ORG(code); return out; } - function callFun(f, base, args, isConstructor, iid) { + function callFun(f, base, args, isConstructor, sid, iid) { var result; pushSwitchKey(); try { if (f === EVAL_ORG) { - result = invokeEval(base, f, args, iid); + result = invokeEval(base, f, args, sid, iid); } else if (f === Function) { - result = invokeFunctionDecl(base, f, args, iid); + result = invokeFunctionDecl(base, f, args, sid, iid); } else if (isConstructor) { result = callAsConstructor(f, args); } else { @@ -201,11 +201,11 @@ if (typeof J$ === 'undefined') { } } - function invokeFun(iid, base, f, args, isConstructor, isMethod) { + function invokeFun(sid, iid, base, f, args, isConstructor, isMethod) { var aret, skip = false, result; if (sandbox.analysis && sandbox.analysis.invokeFunPre) { - aret = sandbox.analysis.invokeFunPre(iid, f, base, args, isConstructor, isMethod, getPropSafe(f, SPECIAL_PROP_IID), getPropSafe(f, SPECIAL_PROP_SID)); + aret = sandbox.analysis.invokeFunPre(sid, iid, f, base, args, isConstructor, isMethod, f[SPECIAL_PROP_IID], f[SPECIAL_PROP_SID]); if (aret) { f = aret.f; base = aret.base; @@ -214,10 +214,10 @@ if (typeof J$ === 'undefined') { } } if (!skip) { - result = callFun(f, base, args, isConstructor, iid); + result = callFun(f, base, args, isConstructor, sid, iid); } if (sandbox.analysis && sandbox.analysis.invokeFun) { - aret = sandbox.analysis.invokeFun(iid, f, base, args, result, isConstructor, isMethod, getPropSafe(f, SPECIAL_PROP_IID), getPropSafe(f, SPECIAL_PROP_SID)); + aret = sandbox.analysis.invokeFun(sid, iid, f, base, args, result, isConstructor, isMethod, f[SPECIAL_PROP_IID], f[SPECIAL_PROP_SID]); if (aret) { result = aret.result; } @@ -226,20 +226,20 @@ if (typeof J$ === 'undefined') { } // Function call (e.g., f()) - function F(iid, f, flags) { + function F(sid, iid, f, flags) { var bFlags = decodeBitPattern(flags, 1); // [isConstructor] return function () { var base = this; - return (lastComputedValue = invokeFun(iid, base, f, arguments, bFlags[0], false)); + return (lastComputedValue = invokeFun(sid, iid, base, f, arguments, bFlags[0], false)); } } // Method call (e.g., e.f()) - function M(iid, base, offset, flags) { + function M(sid, iid, base, offset, flags) { var bFlags = decodeBitPattern(flags, 2); // [isConstructor, isComputed] - var f = G(iid + 2, base, offset, createBitPattern(bFlags[1], false, true)); + var f = G(sid, iid + 2, base, offset, createBitPattern(bFlags[1], false, true)); return function () { - return (lastComputedValue = invokeFun(iid, base, f, arguments, bFlags[0], true)); + return (lastComputedValue = invokeFun(sid, iid, base, f, arguments, bFlags[0], true)); }; } @@ -250,7 +250,7 @@ if (typeof J$ === 'undefined') { var hasGetOwnPropertyDescriptor = typeof Object.getOwnPropertyDescriptor === 'function'; // object/function/regexp/array Literal - function T(iid, val, type, hasGetterSetter, internalIid) { + function T(sid, iid, val, type, hasGetterSetter, internalIid) { var aret; associateSidWithFunction(val, internalIid); if (hasGetterSetter) { @@ -259,17 +259,17 @@ if (typeof J$ === 'undefined') { var desc = Object.getOwnPropertyDescriptor(val, offset); if (desc !== undefined) { if (typeof desc.get === 'function') { - T(iid, desc.get, 12, false, internalIid); + T(sid, iid, desc.get, 12, false, internalIid); } if (typeof desc.set === 'function') { - T(iid, desc.set, 12, false, internalIid); + T(sid, iid, desc.set, 12, false, internalIid); } } } } } if (sandbox.analysis && sandbox.analysis.literal) { - aret = sandbox.analysis.literal(iid, val, hasGetterSetter); + aret = sandbox.analysis.literal(sid, iid, val, hasGetterSetter); if (aret) { val = aret.result; } @@ -278,10 +278,10 @@ if (typeof J$ === 'undefined') { } // wrap object o in for (x in o) { ... } - function H(iid, val) { + function H(sid, iid, val) { var aret; if (sandbox.analysis && sandbox.analysis.forinObject) { - aret = sandbox.analysis.forinObject(iid, val); + aret = sandbox.analysis.forinObject(sid, iid, val); if (aret) { val = aret.result; } @@ -290,7 +290,7 @@ if (typeof J$ === 'undefined') { } // variable declaration (Init) - function N(iid, name, val, flags) { + function N(sid, iid, name, val, flags) { var bFlags = decodeBitPattern(flags, 3); // [isArgument, isLocalSync, isCatchParam] // isLocalSync is only true when we sync variables inside a for-in loop var aret; @@ -300,9 +300,9 @@ if (typeof J$ === 'undefined') { } if (!bFlags[1] && sandbox.analysis && sandbox.analysis.declare) { if (bFlags[0] && argIndex > 1) { - aret = sandbox.analysis.declare(iid, name, val, bFlags[0], argIndex - 2, bFlags[2]); + sandbox.analysis.declare(sid, iid, name, val, bFlags[0], argIndex - 2, bFlags[2]); } else { - aret = sandbox.analysis.declare(iid, name, val, bFlags[0], -1, bFlags[2]); + sandbox.analysis.declare(sid, iid, name, val, bFlags[0], -1, bFlags[2]); } if (aret) { val = aret.result; @@ -312,13 +312,13 @@ if (typeof J$ === 'undefined') { } // getField (property read) - function G(iid, base, offset, flags) { + function G(sid, iid, base, offset, flags) { var bFlags = decodeBitPattern(flags, 3); // [isComputed, isOpAssign, isMethodCall] var aret, skip = false, val; if (sandbox.analysis && sandbox.analysis.getFieldPre) { - aret = sandbox.analysis.getFieldPre(iid, base, offset, bFlags[0], bFlags[1], bFlags[2]); + aret = sandbox.analysis.getFieldPre(sid, iid, base, offset, bFlags[0], bFlags[1], bFlags[2]); if (aret) { base = aret.base; offset = aret.offset; @@ -330,7 +330,7 @@ if (typeof J$ === 'undefined') { val = base[offset]; } if (sandbox.analysis && sandbox.analysis.getField) { - aret = sandbox.analysis.getField(iid, base, offset, val, bFlags[0], bFlags[1], bFlags[2]); + aret = sandbox.analysis.getField(sid, iid, base, offset, val, bFlags[0], bFlags[1], bFlags[2]); if (aret) { val = aret.result; } @@ -339,13 +339,13 @@ if (typeof J$ === 'undefined') { } // putField (property write) - function P(iid, base, offset, val, flags) { + function P(sid, iid, base, offset, val, flags) { var bFlags = decodeBitPattern(flags, 2); // [isComputed, isOpAssign] var aret, skip = false; if (sandbox.analysis && sandbox.analysis.putFieldPre) { - aret = sandbox.analysis.putFieldPre(iid, base, offset, val, bFlags[0], !!bFlags[1]); + aret = sandbox.analysis.putFieldPre(sid, iid, base, offset, val, bFlags[0], !!bFlags[1]); if (aret) { base = aret.base; offset = aret.offset; @@ -358,7 +358,7 @@ if (typeof J$ === 'undefined') { base[offset] = val; } if (sandbox.analysis && sandbox.analysis.putField) { - aret = sandbox.analysis.putField(iid, base, offset, val, bFlags[0], !!bFlags[1]); + aret = sandbox.analysis.putField(sid, iid, base, offset, val, bFlags[0], !!bFlags[1]); if (aret) { val = aret.result; } @@ -369,12 +369,12 @@ if (typeof J$ === 'undefined') { // variable write // isGlobal means that the variable is global and not declared as var // isScriptLocal means that the variable is global and is declared as var - function R(iid, name, val, flags) { + function R(sid, iid, name, val, flags) { var aret; var bFlags = decodeBitPattern(flags, 2); // [isGlobal, isScriptLocal] if (sandbox.analysis && sandbox.analysis.read) { - aret = sandbox.analysis.read(iid, name, val, bFlags[0], bFlags[1]); + aret = sandbox.analysis.read(sid, iid, name, val, bFlags[0], bFlags[1]); if (aret) { val = aret.result; } @@ -383,11 +383,11 @@ if (typeof J$ === 'undefined') { } // variable write - function W(iid, name, val, lhs, flags) { + function W(sid, iid, name, val, lhs, flags) { var bFlags = decodeBitPattern(flags, 3); //[isGlobal, isScriptLocal, isDeclaration] var aret; if (sandbox.analysis && sandbox.analysis.write) { - aret = sandbox.analysis.write(iid, name, val, lhs, bFlags[0], bFlags[1]); + aret = sandbox.analysis.write(sid, iid, name, val, lhs, bFlags[0], bFlags[1]); if (aret) { val = aret.result; } @@ -401,9 +401,9 @@ if (typeof J$ === 'undefined') { } // with statement - function Wi(iid, val) { + function Wi(sid, iid, val) { if (sandbox.analysis && sandbox.analysis._with) { - aret = sandbox.analysis._with(iid, val); + aret = sandbox.analysis._with(sid, iid, val); if (aret) { val = aret.result; } @@ -412,15 +412,15 @@ if (typeof J$ === 'undefined') { } // Uncaught exception - function Ex(iid, e) { + function Ex(sid, iid, e) { wrappedExceptionVal = {exception:e}; } // Throw statement - function Th(iid, val) { + function Th(sid, iid, val) { var aret; if (sandbox.analysis && sandbox.analysis._throw) { - aret = sandbox.analysis._throw(iid, val); + aret = sandbox.analysis._throw(sid, iid, val); if (aret) { val = aret.result; } @@ -429,10 +429,10 @@ if (typeof J$ === 'undefined') { } // Return statement - function Rt(iid, val) { + function Rt(sid, iid, val) { var aret; if (sandbox.analysis && sandbox.analysis._return) { - aret = sandbox.analysis._return(iid, val); + aret = sandbox.analysis._return(sid, iid, val); if (aret) { val = aret.result; } @@ -452,23 +452,23 @@ if (typeof J$ === 'undefined') { } // Function enter - function Fe(iid, f, dis /* this */, args) { + function Fe(sid, iid, f, dis /* this */, args) { argIndex = 0; returnStack.push(undefined); wrappedExceptionVal = undefined; updateSid(f); if (sandbox.analysis && sandbox.analysis.functionEnter) { - sandbox.analysis.functionEnter(iid, f, dis, args); + sandbox.analysis.functionEnter(sid, iid, f, dis, args); } } // Function exit - function Fr(iid) { + function Fr(sid, iid) { var isBacktrack = false, tmp, aret, returnVal; returnVal = returnStack.pop(); if (sandbox.analysis && sandbox.analysis.functionExit) { - aret = sandbox.analysis.functionExit(iid, returnVal, wrappedExceptionVal); + aret = sandbox.analysis.functionExit(sid, iid, returnVal, wrappedExceptionVal); if (aret) { returnVal = aret.returnVal; wrappedExceptionVal = aret.wrappedExceptionVal; @@ -490,19 +490,19 @@ if (typeof J$ === 'undefined') { } // Script enter - function Se(iid, val, origFileName) { + function Se(sid, iid, val, origFileName) { createAndAssignNewSid(); if (sandbox.analysis && sandbox.analysis.scriptEnter) { - sandbox.analysis.scriptEnter(iid, val, origFileName); + sandbox.analysis.scriptEnter(sid, iid, val, origFileName); } lastComputedValue = undefined; } // Script exit - function Sr(iid) { + function Sr(sid, iid) { var tmp, aret, isBacktrack; if (sandbox.analysis && sandbox.analysis.scriptExit) { - aret = sandbox.analysis.scriptExit(iid, wrappedExceptionVal); + aret = sandbox.analysis.scriptExit(sid, iid, wrappedExceptionVal); if (aret) { wrappedExceptionVal = aret.wrappedExceptionVal; isBacktrack = aret.isBacktrack; @@ -519,24 +519,24 @@ if (typeof J$ === 'undefined') { // Modify and assign +=, -= ... - function A(iid, base, offset, op, flags) { + function A(sid, iid, base, offset, op, flags) { var bFlags = decodeBitPattern(flags, 1); // [isComputed] // avoid iid collision: make sure that iid+2 has the same source map as iid (@todo) - var oprnd1 = G(iid+2, base, offset, createBitPattern(bFlags[0], true, false)); + var oprnd1 = G(sid, iid+2, base, offset, createBitPattern(bFlags[0], true, false)); return function (oprnd2) { // still possible to get iid collision with a mem operation - var val = B(iid, op, oprnd1, oprnd2, createBitPattern(false, true, false)); - return P(iid, base, offset, val, createBitPattern(bFlags[0], true)); + var val = B(sid, iid, op, oprnd1, oprnd2, createBitPattern(false, true, false)); + return P(sid, iid, base, offset, val, createBitPattern(bFlags[0], true)); }; } // Binary operation - function B(iid, op, left, right, flags) { + function B(sid, iid, op, left, right, flags) { var bFlags = decodeBitPattern(flags, 3); // [isComputed, isOpAssign, isSwitchCaseComparison] var result, aret, skip = false; if (sandbox.analysis && sandbox.analysis.binaryPre) { - aret = sandbox.analysis.binaryPre(iid, op, left, right, bFlags[1], bFlags[2], bFlags[0]); + aret = sandbox.analysis.binaryPre(sid, iid, op, left, right, bFlags[1], bFlags[2], bFlags[0]); if (aret) { op = aret.op; left = aret.left; @@ -621,7 +621,7 @@ if (typeof J$ === 'undefined') { } if (sandbox.analysis && sandbox.analysis.binary) { - aret = sandbox.analysis.binary(iid, op, left, right, result, bFlags[1], bFlags[2], bFlags[0]); + aret = sandbox.analysis.binary(sid, iid, op, left, right, result, bFlags[1], bFlags[2], bFlags[0]); if (aret) { result = aret.result; } @@ -631,15 +631,15 @@ if (typeof J$ === 'undefined') { // Unary operation - function U(iid, op, left) { + function U(sid, iid, op, left) { var result, aret, skip = false; if (sandbox.analysis && sandbox.analysis.unaryPre) { - aret = sandbox.analysis.unaryPre(iid, op, left); + aret = sandbox.analysis.unaryPre(sid, iid, op, left); if (aret) { op = aret.op; left = aret.left; - skip = aret.skip + skip = aret.skip; } } @@ -665,12 +665,11 @@ if (typeof J$ === 'undefined') { break; default: throw new Error(op + " at " + iid + " not found"); - break; } } if (sandbox.analysis && sandbox.analysis.unary) { - aret = sandbox.analysis.unary(iid, op, left, result); + aret = sandbox.analysis.unary(sid, iid, op, left, result); if (aret) { result = aret.result; } @@ -693,20 +692,20 @@ if (typeof J$ === 'undefined') { // Switch key // E.g., for 'switch (x) { ... }', // C1 is invoked with value of x - function C1(iid, left) { + function C1(sid, iid, left) { switchLeft = left; return (lastComputedValue = left); } // case label inside switch - function C2(iid, right) { + function C2(sid, iid, right) { var aret, result; // avoid iid collision; iid may not have a map in the sourcemap - result = B(iid+1, "===", switchLeft, right, createBitPattern(false, false, true)); + result = B(sid, iid+1, "===", switchLeft, right, createBitPattern(false, false, true)); if (sandbox.analysis && sandbox.analysis.conditional) { - aret = sandbox.analysis.conditional(iid, result); + aret = sandbox.analysis.conditional(sid, iid, result); if (aret) { if (result && !aret.result) { right = !right; @@ -719,10 +718,10 @@ if (typeof J$ === 'undefined') { } // Expression in conditional - function C(iid, left) { + function C(sid, iid, left) { var aret; if (sandbox.analysis && sandbox.analysis.conditional) { - aret = sandbox.analysis.conditional(iid, left); + aret = sandbox.analysis.conditional(sid, iid, left); if (aret) { left = aret.result; } @@ -732,9 +731,9 @@ if (typeof J$ === 'undefined') { return (lastComputedValue = left); } - function S(iid, f) { + function S(sid, iid, f) { if (sandbox.analysis && sandbox.analysis.runInstrumentedFunctionBody) { - return sandbox.analysis.runInstrumentedFunctionBody(iid, f, getPropSafe(f, SPECIAL_PROP_IID), getPropSafe(f, SPECIAL_PROP_SID)); + return sandbox.analysis.runInstrumentedFunctionBody(sid, iid, f, f[SPECIAL_PROP_IID], f[SPECIAL_PROP_SID]); } return true; } @@ -744,9 +743,9 @@ if (typeof J$ === 'undefined') { } - function X1(iid, val) { + function X1(sid, iid, val) { if (sandbox.analysis && sandbox.analysis.endExpression) { - sandbox.analysis.endExpression(iid); + sandbox.analysis.endExpression(sid, iid); } return (lastComputedValue = val); @@ -808,4 +807,3 @@ if (typeof J$ === 'undefined') { sandbox.EVAL_ORG = EVAL_ORG; sandbox.log = log; })(J$); - diff --git a/src/js/runtime/analysisCallbackTemplate.js b/src/js/runtime/analysisCallbackTemplate.js index 0f2f999a..ebff42e8 100644 --- a/src/js/runtime/analysisCallbackTemplate.js +++ b/src/js/runtime/analysisCallbackTemplate.js @@ -121,6 +121,7 @@ * f.apply(y, args); * } * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {function} f - The function object that going to be invoked * @param {object} base - The receiver object for the function f @@ -139,7 +140,7 @@ * an object is returned. * */ - this.invokeFunPre = function (iid, f, base, args, isConstructor, isMethod, functionIid, functionSid) { + this.invokeFunPre = function (sid, iid, f, base, args, isConstructor, isMethod, functionIid, functionSid) { return {f: f, base: base, args: args, skip: false}; }; @@ -152,7 +153,7 @@ * // the above call roughly gets instrumented as follows: * * var skip = false; - * var aret = analysis.invokeFunPre(113, f, y, [a, b, c], false, true); + * var aret = analysis.invokeFunPre(1, 113, f, y, [a, b, c], false, true); * if (aret) { * f = aret.f; * y = aret.y; @@ -162,13 +163,14 @@ * if (!skip) { * result =f.apply(y, args); * } - * aret = analysis.invokeFun(117, f, y, args, result, false, true); + * aret = analysis.invokeFun(1, 117, f, y, args, result, false, true); * if (aret) { * x = aret.result * } else { * x = result; * } * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {function} f - The function object that was invoked * @param {*} base - The receiver object for the function f @@ -187,7 +189,7 @@ * value that is returned by the actual function invocation. * */ - this.invokeFun = function (iid, f, base, args, result, isConstructor, isMethod, functionIid, functionSid) { + this.invokeFun = function (sid, iid, f, base, args, result, isConstructor, isMethod, functionIid, functionSid) { return {result: result}; }; @@ -201,13 +203,14 @@ * // the above call roughly gets instrumented as follows: * * var result = "Hello"; - * var aret = analysis.literal(201, result, false); + * var aret = analysis.literal(1, 201, result, false); * if (aret) { * result = aret.result; * } * x = result; * * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} val - The literal value * @param {boolean} hasGetterSetter - True if the literal is an object and the object defines getters and setters @@ -215,7 +218,7 @@ * replaced with the value stored in the result property of the object. * */ - this.literal = function (iid, val, hasGetterSetter) { + this.literal = function (sid, iid, val, hasGetterSetter) { return {result: val}; }; @@ -227,12 +230,13 @@ * * // the above call roughly gets instrumented as follows: * - * var aret = analysis.forinObject(iid, y); + * var aret = analysis.forinObject(sid, iid, y); * if (aret) { * y = aret.result; * } * for (x in y) {} * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} val - Objects whose properties are iterated in a for-in loop. * @returns {{result: *} | undefined} - If the function returns an object, then the original object whose @@ -240,7 +244,7 @@ * returned object. * */ - this.forinObject = function (iid, val) { + this.forinObject = function (sid, iid, val) { return {result: val}; }; @@ -249,6 +253,7 @@ * every formal parameter, for every function defined using a function statement, for arguments * variable, and for the formal parameter passed in a catch statement. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} name - Name of the variable that is declared * @param {*} val - Initial value of the variable that is declared. Variables can be local variables, function @@ -265,13 +270,14 @@ * variables declared with var. * */ - this.declare = function (iid, name, val, isArgument, argumentIndex, isCatchParam) { + this.declare = function (sid, iid, name, val, isArgument, argumentIndex, isCatchParam) { return {result: val}; }; /** * This callback is called before a property of an object is accessed. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} base - Base object * @param {string|*} offset - Property @@ -285,13 +291,14 @@ * offset are replaced with that from the returned object if an object is returned. * */ - this.getFieldPre = function (iid, base, offset, isComputed, isOpAssign, isMethodCall) { + this.getFieldPre = function (sid, iid, base, offset, isComputed, isOpAssign, isMethodCall) { return {base: base, offset: offset, skip: false}; }; /** * This callback is called after a property of an object is accessed. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} base - Base object * @param {string|*} offset - Property @@ -304,13 +311,14 @@ * @returns {{result: *} | undefined} - If an object is returned, the value of the get field operation is * replaced with the value stored in the result property of the object. */ - this.getField = function (iid, base, offset, val, isComputed, isOpAssign, isMethodCall) { + this.getField = function (sid, iid, base, offset, val, isComputed, isOpAssign, isMethodCall) { return {result: val}; }; /** * This callback is called before a property of an object is written. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} base - Base object * @param {*} offset - Property @@ -323,13 +331,14 @@ * property is true, then the put field operation is skipped. Original base, offset, and * val are replaced with that from the returned object if an object is returned. */ - this.putFieldPre = function (iid, base, offset, val, isComputed, isOpAssign) { + this.putFieldPre = function (sid, iid, base, offset, val, isComputed, isOpAssign) { return {base: base, offset: offset, val: val, skip: false}; }; /** * This callback is called after a property of an object is written. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} base - Base object * @param {*} offset - Property @@ -341,13 +350,14 @@ * @returns {{result: *} | undefined} - If an object is returned, the result of the put field operation is * replaced with the value stored in the result property of the object. */ - this.putField = function (iid, base, offset, val, isComputed, isOpAssign) { + this.putField = function (sid, iid, base, offset, val, isComputed, isOpAssign) { return {result: val}; }; /** * This callback is called after a variable is read. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} name - Name of the variable being read * @param {*} val - Value read from the variable @@ -356,13 +366,14 @@ * @returns {{result: *} | undefined} - If an object is returned, the result of the read operation is * replaced with the value stored in the result property of the object. */ - this.read = function (iid, name, val, isGlobal, isScriptLocal) { + this.read = function (sid, iid, name, val, isGlobal, isScriptLocal) { return {result: val}; }; /** * This callback is called before a variable is written. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} name - Name of the variable being read * @param {*} val - Value to be written to the variable @@ -372,61 +383,66 @@ * @returns {{result: *} | undefined} - If an object is returned, the result of the write operation is * replaced with the value stored in the result property of the object. */ - this.write = function (iid, name, val, lhs, isGlobal, isScriptLocal) { + this.write = function (sid, iid, name, val, lhs, isGlobal, isScriptLocal) { return {result: val}; }; /** * This callback is called before a value is returned from a function using the return keyword. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} val - Value to be returned * @returns {{result: *} | undefined} - If an object is returned, the value to be returned is * replaced with the value stored in the result property of the object. */ - this._return = function (iid, val) { + this._return = function (sid, iid, val) { return {result: val}; }; /** * This callback is called before a value is thrown using the throw keyword. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} val - Value to be thrown * @returns {{result: *} | undefined} - If an object is returned, the value to be thrown is * replaced with the value stored in the result property of the object. */ - this._throw = function (iid, val) { + this._throw = function (sid, iid, val) { return {result: val}; }; /** * This callback is called when a with statement is executed * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} val - Value used as an argument to with * @returns {{result: *} | undefined} - If an object is returned, the value to be used in with is * replaced with the value stored in the result property of the object. */ - this._with = function (iid, val) { + this._with = function (sid, iid, val) { return {result: val}; }; /** * This callback is called before the execution of a function body starts. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {function} f - The function object whose body is about to get executed * @param {*} dis - The value of the this variable in the function body * @param {Array} args - List of the arguments with which the function is called * @returns {undefined} - Any return value is ignored */ - this.functionEnter = function (iid, f, dis, args) { + this.functionEnter = function (sid, iid, f, dis, args) { }; /** * This callback is called when the execution of a function body completes * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} returnVal - The value returned by the function * @param {{exception:*} | undefined} wrappedExceptionVal - If this parameter is an object, the function @@ -439,23 +455,25 @@ * isBacktrack can be set to true to repeatedly execute the function body as in MultiSE * symbolic execution. */ - this.functionExit = function (iid, returnVal, wrappedExceptionVal) { + this.functionExit = function (sid, iid, returnVal, wrappedExceptionVal) { return {returnVal: returnVal, wrappedExceptionVal: wrappedExceptionVal, isBacktrack: false}; }; /** * This callback is called before the execution of a JavaScript file * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} instrumentedFileName - Name of the instrumented script file * @param {string} originalFileName - Name of the original script file */ - this.scriptEnter = function (iid, instrumentedFileName, originalFileName) { + this.scriptEnter = function (sid, iid, instrumentedFileName, originalFileName) { }; /** * This callback is called when the execution of a JavaScript file completes * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {{exception:*} | undefined} wrappedExceptionVal - If this parameter is an object, the script * execution has thrown an uncaught exception and the exception is being stored in the exception @@ -467,7 +485,7 @@ * isBacktrack can be set to true to repeatedly execute the script body as in MultiSE * symbolic execution. */ - this.scriptExit = function (iid, wrappedExceptionVal) { + this.scriptExit = function (sid, iid, wrappedExceptionVal) { return {wrappedExceptionVal: wrappedExceptionVal, isBacktrack: false}; }; @@ -476,6 +494,7 @@ * <<, >>, >>>, <, >, <=, >=, ==, !=, ===, !==, instanceof, delete, in. No callback for delete x * because this operation cannot be performed reflectively. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} op - Operation to be performed * @param {*} left - Left operand @@ -490,7 +509,7 @@ * skip property is true, then the binary operation is skipped. Original op, left, * and right are replaced with that from the returned object if an object is returned. */ - this.binaryPre = function (iid, op, left, right, isOpAssign, isSwitchCaseComparison, isComputed) { + this.binaryPre = function (sid, iid, op, left, right, isOpAssign, isSwitchCaseComparison, isComputed) { return {op: op, left: left, right: right, skip: false}; }; @@ -498,6 +517,7 @@ * This callback is called after a binary operation. Binary operations include +, -, *, /, %, &, |, ^, * <<, >>, >>>, <, >, <=, >=, ==, !=, ===, !==, instanceof, delete, in. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} op - Operation to be performed * @param {*} left - Left operand @@ -512,13 +532,14 @@ * @returns {{result: *}|undefined} - If an object is returned, the result of the binary operation is * replaced with the value stored in the result property of the object. */ - this.binary = function (iid, op, left, right, result, isOpAssign, isSwitchCaseComparison, isComputed) { + this.binary = function (sid, iid, op, left, right, result, isOpAssign, isSwitchCaseComparison, isComputed) { return {result: result}; }; /** * This callback is called before a unary operation. Unary operations include +, -, ~, !, typeof, void. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} op - Operation to be performed * @param {*} left - Left operand @@ -526,13 +547,14 @@ * skip property is true, then the unary operation is skipped. Original op and left * are replaced with that from the returned object if an object is returned. */ - this.unaryPre = function (iid, op, left) { + this.unaryPre = function (sid, iid, op, left) { return {op: op, left: left, skip: false}; }; /** * This callback is called after a unary operation. Unary operations include +, -, ~, !, typeof, void. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {string} op - Operation to be performed * @param {*} left - Left operand @@ -541,7 +563,7 @@ * replaced with the value stored in the result property of the object. * */ - this.unary = function (iid, op, left, result) { + this.unary = function (sid, iid, op, left, result) { return {result: result}; }; @@ -549,18 +571,20 @@ * This callback is called after a condition check before branching. Branching can happen in various statements * including if-then-else, switch-case, while, for, ||, &&, ?:. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} result - The value of the conditional expression * @returns {{result: *}|undefined} - If an object is returned, the result of the conditional expression is * replaced with the value stored in the result property of the object. */ - this.conditional = function (iid, result) { + this.conditional = function (sid, iid, result) { return {result: result}; }; /** * This callback is called before a string passed as an argument to eval or Function is instrumented. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} code - Code that is going to get instrumented * @param {boolean} isDirect - true if this is a direct call to eval @@ -568,13 +592,14 @@ * skip property is true, then the instrumentation of code is skipped. * Original code is replaced with that from the returned object if an object is returned. */ - this.instrumentCodePre = function (iid, code, isDirect) { + this.instrumentCodePre = function (sid, iid, code, isDirect) { return {code: code, skip: false}; }; /** * This callback is called after a string passed as an argument to eval or Function is instrumented. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {*} newCode - Instrumented code * @param {Object} newAst - The AST of the instrumented code @@ -582,7 +607,7 @@ * @returns {{result: *}|undefined} - If an object is returned, the instrumented code is * replaced with the value stored in the result property of the object. */ - this.instrumentCode = function (iid, newCode, newAst, isDirect) { + this.instrumentCode = function (sid, iid, newCode, newAst, isDirect) { return {result: newCode}; }; @@ -590,10 +615,11 @@ * This callback is called when an expression is evaluated and its value is discarded. For example, this * callback is called when an expression statement completes its execution. * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @returns {undefined} - Any return value is ignored */ - this.endExpression = function (iid) { + this.endExpression = function (sid, iid) { }; /** @@ -609,6 +635,8 @@ * This callback is called only when instrumented with J$.Config.ENABLE_SAMPLING = true * This callback is called before the body of a function, method, or constructor is executed * if returns true, instrumented function body is executed, else uninstrumented function body is executed + * + * @param {number} sid - Static script identifier of this callback * @param {number} iid - Static unique instruction identifier of this callback * @param {function} f - The function whose body is being executed * @param {number} functionIid - The iid (i.e. the unique instruction identifier) where the function was created @@ -620,7 +648,7 @@ * @returns {boolean} - If true is returned the instrumented function body is executed, otherwise the * uninstrumented function body is executed. */ - this.runInstrumentedFunctionBody = function (iid, f, functionIid, functionSid) { + this.runInstrumentedFunctionBody = function (sid, iid, f, functionIid, functionSid) { return false; }; @@ -641,6 +669,3 @@ sandbox.analysis = new MyAnalysis(); })(J$); - - - From 32a596477276be2da53bd40b032942f03b4326f8 Mon Sep 17 00:00:00 2001 From: Eliott Robson Date: Wed, 1 Mar 2017 13:48:49 +0000 Subject: [PATCH 2/2] Adding Sid to eval instrumentation --- src/js/instrument/esnstrument.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/instrument/esnstrument.js b/src/js/instrument/esnstrument.js index 668e0194..0e17428e 100755 --- a/src/js/instrument/esnstrument.js +++ b/src/js/instrument/esnstrument.js @@ -1929,9 +1929,10 @@ if (typeof J$ === 'undefined') { } - function instrumentEvalCode(code, iid, isDirect) { + function instrumentEvalCode(code, sid, iid, isDirect) { return instrumentCode({ code: code, + thisSid: sid, thisIid: iid, isEval: true, inlineSourceMap: true,