How to prevent javascript loops that crash your browser or applications?

I am creating a live editor in a Windows 8.1 application using JavaScript. Almost with this, but the problem is that when I run such bad loops or functions, it automatically freezes or exits.

I am testing it with a loop such as :( This is just an example — a user can write his own loop in his own way.)

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

I know this is the worst condition for any application or browser to handle such a loop. So, here I want, if the user uses such a loop, then how do I process it to produce their output?

Or if it cannot be protected for this type of loop, if it is dangerous for my application, so I warn the user that:

Running this snippet may cause the application to crash!

I have an idea to check the code using regular expressions, if the code has something like for(i=0;i<=5000;i++) , then the warning above will appear, how to make a regular expression for it?

You can also include C # as a back-end .

+6
source share
6 answers

I have 2 solutions:

1.

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

Then, using regex, I insert this piece of code inside a nested loop.

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

So, what does he do, every time the loop runs, he does two things:

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

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

In general, a non-hazardous cycle should be performed within 2 to 3 seconds

Small loops, such as for(var i=0;i<30;i++){} , will run completely, but large loops will work for 3-4 seconds, which is quite normal.

My solution uses your own example 50,000 * 5000, but it does not crash!

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

2.

My second solution would be to define two variables start , max .

Max. there should be a maximum number of cycles that you are ready to run. Example 1000

Then, using regex, I insert this piece of code inside a nested loop.

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

So, what does he do, every time the loop runs, he does two things:

  • Increases start by 1.

  • Checks if start is greater than max . If so, this interrupts the cycle.

This solution also uses your own example 50,000 * 5000, but it does not crash!

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

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

+2
source

Unfortunately, without doing deep and complex code analysis of the edited code, you will not be able to completely prevent the erroneous JavaScript that kills your application. For example, you can use a library that creates an abstract syntax tree from JavaScript and does not allow code to be executed when certain patterns are detected. But the number of patterns that can cause an infinite loop is large, so it would not be easy to find, and it probably would not be reliable enough.

In the for example, you can change the code this way:

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

I "introduced" a call to the function you wrote called timeout . There he will have to determine if the loop should break, since the script has been running for too long.

But this could be written using do-while , so it would be necessary to handle the type of loop.

An example of using jQuery, for example, in a narrow loop and modifying the DOM, means that decisions that try to isolate JavaScript in a web worker would be difficult because they were not allowed to directly manipulate the DOM. It can send or receive only "string" messages.

If you used XAML / C # WebView to host (and create) a JavaScript editor, you might consider using an event that is triggered by WebView.LongRunningScriptDetected . It occurs when a long script is detected, giving the host the opportunity to kill the script before the whole application stops responding on requests and will be killed.

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

+5
source

One idea, but not sure if your editor is capable ...

If you understand that this cycle can cause a problem (for example, if the cycle is more than 200 times, then this is a problem) for a cycle like this user, if you can change the code below to provide the output, then it will not hang. But honestly, not sure if this 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 ); 
+2
source

Maybe inject timers around the loops and check the time on the first line. Do this for each cycle.

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

Example:

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

Now, if you use replace and finish formatting in the group, you can get the desired result.

 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); 
+2
source

You cannot find what the user is trying to do with a simple regular expression. Let's say a 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 regular expression, you cannot avoid this. Since the value of i increases after a period of time. Thus, the best way to solve the problem is to have a benchmark. Let's say your application freezes after 3 minutes of continuous processing (suppose your application stops working until your application reaches 3 minutes of processing). Then, regardless of the code that the user is trying to run, you simply start the timer before the process, and if the process takes more than 2.5 minutes, then you simply kill this process in your application and raise a pop-up window to the user, saying "Execution of this fragment may cause the application to crash! "... By doing this, you don’t even need to regex or check the user code if this is bad ...

Try it ... I can help ... Greetings !!!

+2
source

Suppose you are doing this in the context of a window, and not in a working one. Put a function called rocketChair in each inner loop. This feature is simple. It increments the global counter and checks the value on the global ceiling. When the ceiling is reached, the Cheyr racket throws an “outburst from a dangerous code”. At this time, you can also save any state that you want to save to the global state variable.

Wrap the entire application in one catch try block, and when the chair comes out of the rocket, you can save the day as your hero.

+1
source

All Articles