Safe evaluation of arithmetic expressions in Javascript - TagMerge
6Safe evaluation of arithmetic expressions in JavascriptSafe evaluation of arithmetic expressions in Javascript

Safe evaluation of arithmetic expressions in Javascript

Asked 1 years ago
23
6 answers

You can try JavaScript Expression Evaluator:

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

Then your code will be like that:

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

The source code is on GitHub and it's published on npm as expr-eval. Can be used like so:

import { Parser } from 'expr-eval';

console.log(Parser.evaluate("2 * (3 + 4)")); // 14

Source: link

11

As already mentioned, the most damage any user could do is pretty much what they could already do using the built-in console in any of the major browsers. However, if you wanted to restrict the user to using Math properties/methods, you could write a simple regex to handle this for you. Something 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 want to use eval for security reasons, but the regex should make it pretty safe as it rules out any words that aren't direct properties of the Math object and most non-math JS operators, including the assignment operator (=) and binary operators. The harder method would be writing a tokenizer to parse the mathematical expression, because it's not a regular language.

Feel free to try and break the working example I wrote, if you can or if you notice a problem, leave a comment 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 it between the if and else statement (example).

Source: link

5

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

http://mathjs.org

Usage:

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

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

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

Source: link

0

JavaScript has both binary and unary operators, and one special ternary operator, the conditional operator. A binary operator requires two operands, one before the operator and one after the operator:
operand1 operator operand2
A unary operator requires a single operand, either before or after the operator:
operator operand
or
operand operator
If a variable refers to an object, then the left-hand side of an assignment expression may make assignments to properties of that variable. For example:
let obj = {};

obj.x = 3;
console.log(obj.x); // Prints 3.
console.log(obj); // Prints { x: 3 }.

const key = "y";
obj[key] = 5;
console.log(obj[key]); // Prints 5.
console.log(obj); // Prints { x: 3, y: 5 }.
For more complex assignments, the destructuring assignment syntax is a JavaScript expression that makes it possible to extract data from arrays or objects using a syntax that mirrors the construction of array and object literals.
var foo = ['one', 'two', 'three'];

// without destructuring
var one   = foo[0];
var two   = foo[1];
var three = foo[2];

// with destructuring
var [one, two, three] = foo;

Source: link

0

then your code will be like that:
console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14
As already mentioned, the most damage any user could do is pretty much what they could already do using the built-in console in any of the major browsers. However, if you wanted to restrict the user to using Math properties/methods, you could write a simple regex to handle this for you. Something 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"); };
}
Safe evaluation of arithmetic expressions in Javascript
else if (Math.hasOwnProperty($0.toUpperCase())
    return "Math."+$0.toUpperCase();
Usage:
var ans = math.evaluate('2 * (3 + 4)');
or use the parser (which supports variable and function assignments):
var parser = math.parser();
var ans = parser.evaluate('2 * (3 + 4)');

Source: link

0

then your code will be like that:
console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14

Source: link

Recent Questions on javascript

    Programming Languages