Skip to content

Instantly share code, notes, and snippets.

@ritwickdey
Last active November 21, 2023 12:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ritwickdey/26457775a9ade8cbca528a7f30f6f8fd to your computer and use it in GitHub Desktop.
Save ritwickdey/26457775a9ade8cbca528a7f30f6f8fd to your computer and use it in GitHub Desktop.
Infinite loop detection via AST transformation
export default function (babel) {
const { types: t } = babel;
const infiniteLoopDetector = babel.parse(`
function __infiniteLoopDetector() {
loopdetector.count += 1;
if(loopdetector.count > 10000) {
throw new Error("Infinte loop detected.")
}
}
function __infiniteLoopDetector__reset() {
loopdetector.count = 0;
}
`);
//Todo: Need diff approch;
let isGlobalFNsAreAdded = false;
function injectDetectorIntoLoop(path) {
const detectorFn = babel.parse(`
/** Injected loop detector*/
__infiniteLoopDetector()
`);
const resetFn = babel.parse(`
/** Reset Counter before loop start*/
__infiniteLoopDetector__reset()
`);
path.node.body.body.unshift(detectorFn);
const thisIndex = path.parent.body.findIndex((e) => e === path.node);
path.parent.body.splice(thisIndex, 0, resetFn);
}
return {
name: "ast-transform", // not required
visitor: {
Program(path) {
if (isGlobalFNsAreAdded) return;
path.node.body.unshift(infiniteLoopDetector);
isGlobalFNsAreAdded = true;
},
ForStatement(path) {
injectDetectorIntoLoop(path);
},
WhileStatement(path) {
injectDetectorIntoLoop(path);
}
}
};
}
@ritwickdey
Copy link
Author

ritwickdey commented Jul 9, 2021

DEMO: https://astexplorer.net/#/gist/61b6f2e1bd64913c5a3502b80fbb571b/5ec1f4ccf90aba38cb4bdb6acf0d4d5969cce2ce

Input: file1.js

const x = 10;

while(true) {
  console.log("Hey")
  console.log("hi")
}


x = 10;
x = 10;
x = 10;


for(;;) {
  console.log("Hey")
  console.log("hi")
}

Output: file1.transpiled.js

function __infiniteLoopDetector() {
  loopdetector.count += 1;

  if (loopdetector.count > 10000) {
    throw new Error("Infinte loop detected.");
  }
}

function __infiniteLoopDetector__reset() {
  loopdetector.count = 0;
}

const x = 10;

/** Reset Counter before loop start*/
__infiniteLoopDetector__reset();

while (true) {
  /** Injected loop detector*/
  __infiniteLoopDetector();

  console.log("Hey");
  console.log("hi");
}

x = 10;
x = 10;
x = 10;

/** Reset Counter before loop start*/
__infiniteLoopDetector__reset();

for (;;) {
  /** Injected loop detector*/
  __infiniteLoopDetector();

  console.log("Hey");
  console.log("hi");
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment