Frage

I am creating a live editor in Windows 8.1 App using JavaScript. Almost done with that, but the problem is whenever I run such bad loops or functions then it automatically hangs or exits.

I test it with a loop such as:( It just a example-user may write its loop in its own way..)

for(i=0;i<=50000;i++)
{
   for(j=0;j<5000;j++){
     $('body').append('hey I am a bug<br>');
   }
}

I know that this is a worst condition for any app or browser to handle that kind of loop. So here I want that if user uses such a loop then how I handle it, to produce their output?

Or if its not possible to protect my app for that kind of loop, if it is dangerous to my app so I alert the user that:

Running this snippet may crash the app!

I have an idea to check the code by using regular expressions if code have something like for(i=0;i<=5000;i++) then the above alert will show, how to do a Regex for that?

Also able to include C# as back-end .

War es hilfreich?

Lösung 2

I've got 2 solutions:

1.

My first solution would be defining a variable startSeconds=new Date().getSeconds();.

Then, using regex, I'm inserting this piece of code inside the nested loop.

;if(startSecond < new Date().getSeconds())break;

So, what it does is each time the loop runs, it does two things:

Checks if startSecond is less than current seconds new Date().getSeconds();.

For example, startSecond may be 22. new Date().getSeconds() may return 24.Now, the if condition succeeds so it breaks the loop.

Mostly, a non dangerous loop should run for about 2 to 3 seconds

Small loops like for(var i=0;i<30;i++){} will run fully, but big loops will run for 3 to 4 seconds, which is perfectly ok.

My solution uses your own example of 50000*5000, but it doesn't crash!

Live demo:http://jsfiddle.net/nHqUj/4

2.

My second solution would be defining two variables start, max.

Max should be the maximum number of loops that you are willing to run. Example 1000.

Then, using regex, I'm inserting this piece of code inside the nested loop.

;start+=1;if(start>max)break;

So, what it does is each time the loop runs, it does two things:

  1. Increments the value of start by 1.

  2. Checks whether start is greater than the max. If yes, it breaks the loop.

This solution also uses your own example of 50000*5000, but it doesn't crash!

Updated demo:http://jsfiddle.net/nHqUj/3

Regex I'm using:(?:(for|while|do)\s*\([^\{\}]*\))\s*\{([^\{\}]+)\}

Andere Tipps

Unfortunately, without doing some deep and complex code analysis of the edited code, you'll not be able to fully prevent errant JavaScript that kills your application. You could use, for example, a library that builds an abstract syntax tree from JavaScript and not allow code execution if certain patterns are found. But, the number of patterns that could cause an infinite loop are large, so it would not be simple to find, and it's likely to not be robust enough.

In the for example, you could modify the code to be like this:

for(i=0;!timeout() && i<=50000;i++)
{
   for(j=0;!timeout() && j<5000;j++){
     $('body').append('hey I am a bug<br>');
   }
}

I've "injected" a call to a function you'd write called timeout. In there, it would need to be able to detect whether the loop should be aborted because the script has been running too long.

But, that could have been written with a do-while, so that type of loop would need to be handled.

The example of using jQuery for example in a tight loop, and modifying the DOM means that solutions that trying to isolate the JavaScript into a Web Worker would be complex, as it's not allowed to manipulate the DOM directly. It can only send/receive "string" messages.

If you had used the XAML/C# WebView to host (and build) the JavaScript editor, you could have considered using an event that is raised called WebView.LongRunningScriptDetected. It is raised when a long running script is detected, providing the host the ability to kill the script before the entire application becomes unresponsive and is killed.

Unfortunately, this same event is not available in the x-ms-webview control which is available in a WinJS project.

One idea, but not sure what is your editor is capable of..

If some how you can understand that this loop may cause problem(like if a loop is more than 200 times then its a issue) and for a loop like that from user if you can change the code to below to provide the output then it will not hang. But frankly not sure if it will work for you.

var j = 0;
var inter = setInterval( function(){
    if( j<5000  ){
      $('#test').append('hey I am a bug<br>');
      ++j;  
    } else {
        clearInterval(inter);
    }
}, 100 );

Perhaps inject timers around for loops and check time at the first line. Do this for every loop.

Regex: /for\([^{]*\)[\s]*{/

Example:

/for\([^{]*\)[\s]*{/.test("for(var i=0; i<length; i++){");
> true

Now, if you use replace and wrap the for in a grouping you can get the result you want.

var code = "for(var i=0; i<length; i++){",
    testRegex = /(?:for\([^{]*\)[\s]*{)/g,
    matchReplace = "var timeStarted = new Date().getTime();" +
                   "$1" +
                   "if (new Date().getTime() - timeStarted > maxPossibleTime) {" +
                       "return; // do something here" +
                   "}";

code.replace(textRegex, matchReplace);

You cannot find what user is trying to do with a simple regex. Lets say, the user writes his code like...

for(i=0;i<=5;i++)
{
   for(j=0;j<=5;j++){
     if(j>=3){
         i = i * 5000;
         j = j * 5000;
     }
     $('body').append('hey I am a bug<br>');
   }
}

Then with a simple regex you cannot avoid this. Because the value of i is increased after a time period. So the best way to solve the problem is to have a benchmark. Say, your app hangs after continuos processing of 3 minutes(Assume, until your app hits 3 minutes of processing time, its running fine). Then, whatever the code the user tries to run, you just start a timer before the process and if the process takes more than 2.5 minutes, then you just kill that process in your app and raise a popup to the user saying 'Running this snippet may crash the app!'... By doing this way you dont even need a regex or to verify users code if it is bad...

Try this... Might help... Cheers!!!

Let's assume you are doing this in the window context and not in a worker. Put a function called rocketChair in every single inner loop. This function is simple. It increments a global counter and checks the value against a global ceiling. When the ceiling is reached rocketChair summarily throws "eject from perilous code". At this time you can also save to a global state variable any state you wish to preserve.

Wrap your entire app in a single try catch block and when rocket chair ejects you can save the day like the hero you are.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top