[ACCEPTED]-Safe evaluation of arithmetic expressions in Javascript-math

Accepted answer
Score: 23

you can try JavaScript Expression Evaluator:

This library is a modified 7 version of Raphael Graf’s ActionScript 6 Expression Parser. When I wrote the JavaScript Function 5 Plotter, I wanted a better alternative to using JavaScript’s eval function. There’s no security 4 risk currently, because you can only run code 3 in your own browser, but it’s not as convenient 2 for math (Math.pow(2^x) instead of 2^x, etc.).

then 1 your code will be like that:

console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14
Score: 11

As already mentioned, the most damage any 19 user could do is pretty much what they could 18 already do using the built-in console in 17 any of the major browsers. However, if 16 you wanted to restrict the user to using 15 Math properties/methods, you could write a simple 14 regex to handle this for you. Something 13 like this should work:

function mathEval (exp) {
    var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\[\]"'!&<>^\\?:])/ig,
        valid = true;
       
    // Detect valid JS identifier names and replace them
    exp = exp.replace(reg, function ($0) {
        // If the name is a direct member of Math, allow
        if (Math.hasOwnProperty($0))
            return "Math."+$0;
        // Otherwise the expression is invalid
        else
            valid = false;
    });
    
    // Don't eval if our replace function flagged as invalid
    if (!valid)
        alert("Invalid arithmetic expression");
    else
        try { alert(eval(exp)); } catch (e) { alert("Invalid arithmetic expression"); };
}

I realize you didn't 12 want to use eval for security reasons, but the 11 regex should make it pretty safe as it rules 10 out any words that aren't direct properties of 9 the Math object and most non-math JS operators, including 8 the assignment operator (=) and binary operators. The 7 harder method would be writing a tokenizer 6 to parse the mathematical expression, because 5 it's not a regular language.

Feel free to 4 try and break the working example I wrote, if you can or 3 if you notice a problem, leave a comment 2 and I'll see what I can do to fix it.


Note: Yi Jiang mentioned [in JavaScript chat](https://chat.stackoverflow.com/rooms/17/javascript) that it might also be useful to allow lower case for things like `Math.PI`. If that's the case, you could just add the following `else if` statement in the replacement function:
else if (Math.hasOwnProperty($0.toUpperCase())
    return "Math."+$0.toUpperCase();

Add 1 it between the if and else statement (example).

Score: 5

You can use the advanced expression parser 3 from math.js, which does not use JavaScript's 2 eval.

http://mathjs.org

Usage:

var ans = math.evaluate('2 * (3 + 4)');

or use the parser (which supports 1 variable and function assignments):

var parser = math.parser();
var ans = parser.evaluate('2 * (3 + 4)');
Score: 1

You could use a regex to replace everything 7 except for your whitelist. But since the 6 javascript is executed on the client (unless 5 you're running the AOL http server) anyone 4 who can modify the inputs can modify the 3 code as well - so you're not really making 2 it any more or less secure than it already 1 is.

Score: 1

Try nerdamer

var result = nerdamer('sqrt(4)+cos(1)-2').evaluate();
document.getElementById('text').innerHTML = result.text();
<script src="http://nerdamer.com/js/nerdamer.core.js"></script>
<div id="text"></div>

0

More Related questions