open-loop-killer
Version:
Inject timeout protection into JavaScript loops to prevent infinite loops. Supports while, for, do-while, for-in, and for-of loops with customizable timeout and error messages.
56 lines (43 loc) • 1.72 kB
JavaScript
;
const randomIdGenerator = require('../util/idGenerator.js');
const insertionCode = require('./insertionBlock');
const injectionProcess = (ast, options = {}) => {
// If this isn't actual body, recurse with the body
if (!Array.isArray(ast)) {
injectionProcess(ast.body, options);
return;
}
// Traverse the body
for (let i = ast.length; i--;) {
const currentElement = ast[i];
const loopDetected = (currentElement &&
currentElement.type === 'ForStatement') ||
currentElement.type === 'WhileStatement' ||
currentElement.type === 'DoWhileStatement' ||
currentElement.type === 'ForInStatement' ||
currentElement.type === 'ForOfStatement';
if (loopDetected){
const insertionBlocks = insertionCode(options);
const randomVariableName = randomIdGenerator();
//@ts-ignore
insertionBlocks.before.declarations[0].id.name = insertionBlocks.inside.test.left.right.name = randomVariableName;
// Insert time variable assignment as first child in the body array.
ast.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(currentElement.body)) {
currentElement.body = {
body: [currentElement.body],
type: 'BlockStatement',
};
}
// Insert the `If` Statement check
currentElement.body.body.unshift(insertionBlocks.inside);
}
// Recurse on inner body
if (currentElement.body) {
injectionProcess(currentElement.body, options);
}
}
};
module.exports = injectionProcess;