TransWikia.com

javascript .eval() gives me undifined

Stack Overflow Asked by nourza on January 10, 2021

Here is my code

<div class="row">
  <div class="col-md-4 black">
    <% @unit.attempts.order("created_at DESC").each do |attempt| %>
     <p><%= attempt.body %></p>
    <% end %>
  </div>
  <div class="col-md-4 run">
    <div class="view-lines">
      <h2>app.js</h2>
      <%= form_for [@unit, @attempt] do |f| %>
        <%= f.text_area :body,class: "editor"%>
        <%= f.submit "Run"%>
      <% end %>
      <script>
       $(document).ready(function(){
          var code = $(".editor")[0];
          var editor = CodeMirror.fromTextArea(code,{
              lineNumbers: true,
              styleActiveLine: true,
              mode: "javascript",
              matchBrackets: true
          })
          $('.view-lines').each(function(index,item) {
           var v= $(item).find('.editor').val();
           alert(eval(v));
          }); 
             })
</script>

for example if I want to add inside the text area

var favoriteFood = 'pizza';
console.log(favoriteFood);

The result I got in the alert

var favoriteFood = 'pizza';
    console.log(favoriteFood);

I want to run the javascript code in my example in the alert it should be pizza

2 Answers

You're not understanding what eval() does.
The eval takes as input the expression and returns the value of the last expression:

console.log(eval("2+2")) // -> 4
console.log(eval("Math.pow(2, 10)")) // -> 1024
console.log(eval("let x = 100; x - 1")) // -> 99

console.log() is not changed inside the eval(). It does the same as in the normal code.

OK, but what if I want console.log()?

You can redefine console and console.log():

function executeCode(code) {
  let logs = []; // Logs array
  // Redefine console
  let console = {
    log(...args) { // We can pass as many args as we want
      logs.push(args);
    }
  }
  // Eval the code
  eval(code);
  // Return the logs
  return logs;
}

// Demos
console.log(executeCode('console.log("Hello, world!")'))
console.log(executeCode('let x = 5; console.log("X is", x)'))

Note what eval is evil

let password = "1234"; // An important variable
let login = "vasya" // Another one

// Execute code
function executeCode(code) {
  let logs = []; // Logs array
  // Redefine console
  let console = {
    log(...args) { // We can pass as many args as we want
      logs.push(args);
    }
  }
  // Eval the code
  eval(code);
  // Return the logs
  return logs;
}

// Code may be not yours, as example shared to you
console.log(executeCode('console.log("Got your password: ", password)')) // Code can access to almost anything
console.log(executeCode('login = "abcdef"')) // And can modify everything
console.log("INFO: Login is", login)
// Or it can redirect you
// console.log(executeCode('window.location.href = "example.com"')) 

Of course there are some ways to secure this, and if you want — I can add them

Answered by Ivan Didyk on January 10, 2021

I'm not sure what you're trying to accomplish here, but for the purpose of just solving your problem, you could evaluate the commands first assuming that they populate a given variable name, and then alert using that variable name instead of the result of eval. So in your case, something like this might work:

eval("var favoriteFood='pizza';");
alert(favoriteFood);  // will alert with the message "pizza"

If your expectation is that a user would put a separate command on each line you could loop through the lines and evaluate them all separately, like this:

eval("var favoriteFood='pizza';");
eval("favoriteFood += ' slices';");
alert(favoriteFood);  // will alert with the message "pizza slices"

Overall you should never blindly execute user input data like this, it's a big problem from a security perspective. But I hope this helps with whatever you're cooking up today.

Edit : (responding to comment question)

In your case, instead of this:

alert(eval(v));

You could do this:

eval(v);
alert(favoriteFood);

Again this assumes that in your text area, you are setting a variable named favoriteFood. If you want to remove that qualification I don't think there's a way you can do this with eval.

Answered by Mark Madej on January 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP