nourza
nourza

Reputation: 2321

Javascript .eval() returnsn undefined

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

Upvotes: 0

Views: 114

Answers (2)

ISD
ISD

Reputation: 1012

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

Upvotes: 0

Mark Madej
Mark Madej

Reputation: 1922

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.

Upvotes: 0

Related Questions