mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-14 02:26:20 +02:00
Protect webmaker users from INFINITE LOOPS! fixes #18
This commit is contained in:
50
src/utils.js
50
src/utils.js
@ -1,6 +1,7 @@
|
||||
(function () {
|
||||
window.$ = document.querySelector.bind(document);
|
||||
window.$all = document.querySelectorAll.bind(document);
|
||||
var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
|
||||
// https://github.com/substack/semver-compare/blob/master/index.js
|
||||
function semverCompare(a, b) {
|
||||
@ -21,7 +22,7 @@
|
||||
len = len || 10;
|
||||
var id = '';
|
||||
for (var i = len; i--;) {
|
||||
id += String.fromCharCode(~~(Math.random() * 52) + 65);
|
||||
id += alphaNum[~~(Math.random() * alphaNum.length)];
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@ -39,10 +40,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Generate 2 ASTs for the code to be inserted in loops for infinite run protection.
|
||||
// The `myVar` variable names would be changed later for every insertion.
|
||||
function getLoopProtectorBlocks() {
|
||||
var ast1 = esprima.parse('var myvar = Date.now();');
|
||||
var ast2 = esprima.parse('while(a){if (Date.now() - a787897 > 1000) { window.top.previewException(new Error("Infinite loop")); break;}}');
|
||||
return {
|
||||
before: ast1.body[0],
|
||||
inside: ast2.body[0].body.body[0]
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add timed limit on the loops found in the passed AST body
|
||||
* @param {ASTBody} Body of an AST generated by esprima or any ES compliant AST
|
||||
*/
|
||||
function addInfiniteLoopProtection(astBody) {
|
||||
if (!Array.isArray(astBody)) {
|
||||
addInfiniteLoopProtection(astBody.body);
|
||||
return;
|
||||
}
|
||||
var el, randomVariableName, insertionBLocks;
|
||||
|
||||
for (var i = astBody.length; i--;) {
|
||||
el = astBody[i];
|
||||
if (el && el.type === 'ForStatement' || el.type === 'WhileStatement' || el.type === 'DoWhileStatement') {
|
||||
randomVariableName = '_' + generateRandomId(3);
|
||||
insertionBLocks = getLoopProtectorBlocks();
|
||||
insertionBLocks.before.declarations[0].id.name = insertionBLocks.inside.test.left.right.name = randomVariableName;
|
||||
// Insert time variable assignment
|
||||
astBody.splice(i, 0, insertionBLocks.before);
|
||||
// If the loop's body is a single statement, then convert it into a block statement
|
||||
// so that we can insert our conditional break inside it.
|
||||
if (!Array.isArray(el.body)) {
|
||||
el.body = {
|
||||
body: [ el.body ],
|
||||
type: 'BlockStatement'
|
||||
};
|
||||
}
|
||||
// Insert IfStatement
|
||||
el.body.body.unshift(insertionBLocks.inside);
|
||||
}
|
||||
if (el.body) {
|
||||
addInfiniteLoopProtection(el.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.utils = {
|
||||
semverCompare: semverCompare,
|
||||
generateRandomId: generateRandomId,
|
||||
onButtonClick: onButtonClick,
|
||||
addInfiniteLoopProtection: addInfiniteLoopProtection,
|
||||
log: log
|
||||
};
|
||||
})();
|
||||
|
Reference in New Issue
Block a user