JavaScript eval check if it is safe

2

I would like to create sequenced objects and to set the object name, I could only do it with the eval() function, I did not find any other alternatives.

They say it is uninsured, and subject to attacks. I would like to know if the code below offers some insecurity to the site.

var obj1 = { but1: { Label: "button1" }, but2: { Label: "button2" }, but3: { Label: "button3" } };

for (i=4;i<=6;i++)
   x = eval("obj1.but" + i + " = {Label:'button"+i+"'};");

If so, what is the safe way to write this code? Thank you.

    
asked by anonymous 05.12.2016 / 16:10

3 answers

8

You do not need to use eval in this case. You can access a field determined by a string using the []

for (var i=4;i<=6;i++){
    obj1["but"+i] = { Label: "button"+i };
}

But in my opinion the best thing would be to put the buttons in a vector or in a hash table:

var obj1 = {
    buttons: [
        { Label: "button0" },
        { Label: "button1" },
        { Label: "button2" }
    ]
};


for (var i=3;i<=5;i++) {
   obj1.buttons[i] = { Label: "button"+i };
}

As for security, this particular example you used is not insecure because you can ensure that all strings that are passed to eval are well behaved. The security issue would arise if you passed some value determined by a user of your website into the eval.

But although the current version is not insecure I still would not recommend using eval. It is much more complicated than alternatives, if there is an error during eval the error message and stack trace are difficult to debug, and eval blocks several compiler optimizations, which causes your program to run more slowly. In addition, it is very easy to introduce a security problem by making only a small accidental modification to the code.

    
05.12.2016 / 16:18
2

This response is a addendum response from @hugomg , summarizing the problem of eval is what types of data will be executed, in the question the example is not technically insecure, however there is still the performance problem, in this example I did more similar to the original code, although I agree with the arrays approach @ hugomg, I kept it to compare performance, see for yourself:

  • Function testObject takes or arrows objects like obj1['but' + i]
  • Function testEval is your original code eval("obj1.but" + i);

The example:

var obj1 = { but1: { Label: "button1" }, but2: { Label: "button2" }, but3: { Label: "button3" } };

function testEval() {
   for (var i=4;i<=6;i++) {
      x = eval("obj1.but" + i + " = {Label:'button"+i+"'};");
   }
}

function testObject() {
   for (var i=4;i<=6;i++) {
      x = obj1['but' + i] = {Label:'button' + i };
   }
}

var d = new Date().getTime();

for (var i=0;i<100000;i++) {
   testEval();
}

console.log("eval:", (new Date().getTime() - d) + "ms");

d = new Date().getTime();

for (var i=0;i<1000;i++) {
   testObject();
}

console.log("object:", (new Date().getTime() - d) + "ms");

Chrome results:

  • testEval took ~ 477ms to complete
  • testObject took ~ 2ms to complete

In other words, using obj1['but' + i] is much more efficient than eval

In firefox the result is much worse with eval, it takes 6741ms to run the example:

  • eval: 6741ms
  • object: 3ms
05.12.2016 / 17:13
1
  

I'd like to know if the code below offers some insecurity to the site.   Contact Us |   If so, what is the safe way to write this code?

You already know that eval causes the browser to interpret / execute a code in the same scope as it was called: then "no". The code running next to the client is not able to modify the server, but it has access to the local declarations, since the global context anyone can modify quickly (now this is in case you want to evaluate a string that came from elsewhere) p>

I would worry about using eval in this case, since it can undermine the performance of a game (for example), by having the browser re-evaluate and execute a code.

The way you used eval was not very vivid, like, you wanted to get a obj1 property in a more customized way. Assignments also work with (exp)[expParaONomeDaPropriedade] instead of (exp).identificador :

obj1['0']; // o mesmo que obj1[0]
obj1['but1']; // o mesmo que obj1.but1

The difference from using . is because you are required to use an identifier in several ways currently:

({ 'a': 2 }).\u{61} // 2
({ 'a': 2 }).\u0061 // 2

({ 'B': 5 }).\u0042 // 5
({ 'B': 5 }).B // 5

Remembering that the names of all properties are forced to be strings, except a property with the type name 'symbol' ...

    
05.12.2016 / 16:44