From 46c287165152614fd8c47a7d11ce1ca3f5d7b235 Mon Sep 17 00:00:00 2001 From: dylan madisetti Date: Sun, 7 Aug 2022 12:41:06 -0400 Subject: [PATCH 1/2] Patch Khalid's infinite-loop2 + translations --- src/scripts/frame.js | 9 +++++++++ src/scripts/makeitsafe.js | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/scripts/makeitsafe.js diff --git a/src/scripts/frame.js b/src/scripts/frame.js index d44470c0..341ce40c 100644 --- a/src/scripts/frame.js +++ b/src/scripts/frame.js @@ -1,3 +1,5 @@ +let infiniteLoopDetector = import('./makeitsafe.js'); + // Defaults in case a game doesn't load. var code = "console.error('Nothing to run!!')"; let image_lookup = {}; @@ -82,9 +84,16 @@ let meta = { } console.dispatchEvent("evaluate", item); }; + + console.log("Testing for infinite loop"); + code = infiniteLoopDetector.wrap(code) try { eval(code); } catch (e) { + if (e.type === 'InfiniteLoopError') { + console.log('infinite loop detected') + } + var err = e.constructor(e.message); let trace = e.stack.split("\n")[1].split(":"); err.lineNumber = trace[trace.length - 2]; diff --git a/src/scripts/makeitsafe.js b/src/scripts/makeitsafe.js new file mode 100644 index 00000000..7e75561e --- /dev/null +++ b/src/scripts/makeitsafe.js @@ -0,0 +1,40 @@ +var infiniteLoopDetector = (function() { + var map = {} + + // define an InfiniteLoopError class + function InfiniteLoopError(msg, type) { + Error.call(this ,msg) + this.type = 'InfiniteLoopError' + } + + function infiniteLoopDetector(id) { + if (id in map) { // Not the first execution, it can be optimized here, the performance is too low + if (Date.now() - map[id] > 1000) { + delete map[id] + throw new Error('Loop running too long!', 'InfiniteLoopError') + } + } else { // First run, record the time the loop started. All the judgments that are not first run are written in the previous if because the above will be executed more times + map[id] = Date.now() + } + } + + infiniteLoopDetector.wrap = function(codeStr) { + if (typeof codeStr !== 'string') { + throw new Error('Can only wrap code represented by string, not any other thing at the time! If you want to wrap a function, convert it to string first.') + } + // this is not a strong regex, but enough to use at the time + return codeStr.replace(/for *\(.*\{|while *\(.*\{|do *\{/g, function(loopHead) { + var id = parseInt(Math.random() * Number.MAX_SAFE_INTEGER) + return `infiniteLoopDetector(${id});${loopHead}infiniteLoopDetector(${id});` + }) + } + infiniteLoopDetector.unwrap = function(codeStr) { + return codeStr.replace(/infiniteLoopDetector\([0-9]*?\);/g, '') + } + + return infiniteLoopDetector +}()) + +module.exports.infiniteLoopDetector = infiniteLoopDetector; + +// todo: copied from https://github.com/xieranmaya/infinite-loop-detector/blob/master/infinite-loop-detector.js From 6015b02c40464dd807d65e88200c06e44950f781 Mon Sep 17 00:00:00 2001 From: dylan madisetti Date: Sun, 7 Aug 2022 13:14:09 -0400 Subject: [PATCH 2/2] This works for me. I think it was just importing issues (see the TODO) --- src/scripts/frame.js | 10 ++++++---- src/scripts/makeitsafe.js | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/scripts/frame.js b/src/scripts/frame.js index 341ce40c..5db8b46b 100644 --- a/src/scripts/frame.js +++ b/src/scripts/frame.js @@ -1,4 +1,7 @@ -let infiniteLoopDetector = import('./makeitsafe.js'); +import infiniteLoopDetector from './makeitsafe.js'; +console.log(infiniteLoopDetector); +let infDetector = infiniteLoopDetector.infiniteLoopDetector; +console.log(infDetector); // Defaults in case a game doesn't load. var code = "console.error('Nothing to run!!')"; @@ -85,13 +88,12 @@ let meta = { console.dispatchEvent("evaluate", item); }; - console.log("Testing for infinite loop"); - code = infiniteLoopDetector.wrap(code) + code = infDetector.wrap(code) try { eval(code); } catch (e) { if (e.type === 'InfiniteLoopError') { - console.log('infinite loop detected') + console.err('infinite loop detected') } var err = e.constructor(e.message); diff --git a/src/scripts/makeitsafe.js b/src/scripts/makeitsafe.js index 7e75561e..06b41618 100644 --- a/src/scripts/makeitsafe.js +++ b/src/scripts/makeitsafe.js @@ -1,3 +1,7 @@ +// TODO: Clean up. Not really wriotten for modules and a bit of a hack as is. +// Imports should be better, also may as well make this a proper javascript +// class opposed to whatever this is. + var infiniteLoopDetector = (function() { var map = {} @@ -22,11 +26,16 @@ var infiniteLoopDetector = (function() { if (typeof codeStr !== 'string') { throw new Error('Can only wrap code represented by string, not any other thing at the time! If you want to wrap a function, convert it to string first.') } + // Replaces potential infite loop areas with a bit of guard code that makes + // and makes sure that the loop doesn't exceed some value of execution time. + // // this is not a strong regex, but enough to use at the time - return codeStr.replace(/for *\(.*\{|while *\(.*\{|do *\{/g, function(loopHead) { + let response = codeStr.replace(/for *\(.*\{|while *\(.*\{|do *\{/g, function(loopHead) { var id = parseInt(Math.random() * Number.MAX_SAFE_INTEGER) - return `infiniteLoopDetector(${id});${loopHead}infiniteLoopDetector(${id});` - }) + return `infDetector(${id});${loopHead}infDetector(${id});` + }); + // console.log(response); + return response; } infiniteLoopDetector.unwrap = function(codeStr) { return codeStr.replace(/infiniteLoopDetector\([0-9]*?\);/g, '')